diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..93e3914 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,4 @@ +singleQuote: true +trailingComma: all +bracketSpacing: false +arrowParens: avoid diff --git a/app.ts b/app.ts index 16a4808..fd8ff56 100644 --- a/app.ts +++ b/app.ts @@ -1,135 +1,131 @@ -import * as path from "path"; -import * as bodyParser from "body-parser"; -import * as c from "./src/context"; -import {createConnection} from "typeorm"; -import * as Tokens from "csrf"; -import * as express from "express"; -import * as handlebars from "express-handlebars"; -import * as session from "express-session"; -import * as fs from "fs"; -import * as shortid from "shortid"; -import * as request_funcs from "./src/request_funcs"; -import * as db_impl from "./src/db"; -import config from "./src/config"; -import * as password_checker from "./src/password"; -import * as pg from "./src/db-pg"; -import * as wa_api from "./src/wild_apricot"; -import * as yargs from "yargs"; -import * as http from "http"; - - -let make_logger = (logger) => { +import * as path from 'path'; +import * as bodyParser from 'body-parser'; +import * as c from './src/context'; +import {createConnection} from 'typeorm'; +import * as Tokens from 'csrf'; +import * as express from 'express'; +import * as handlebars from 'express-handlebars'; +import * as session from 'express-session'; +import * as fs from 'fs'; +import * as shortid from 'shortid'; +import * as request_funcs from './src/request_funcs'; +import * as db_impl from './src/db'; +import config from './src/config'; +import * as password_checker from './src/password'; +import * as pg from './src/db-pg'; +import * as wa_api from './src/wild_apricot'; +import * as yargs from 'yargs'; +import * as http from 'http'; + +let make_logger = logger => { let request_id = shortid.generate(); let log_func = function (level, args) { let date = new Date(); - args.unshift( "(" + request_id + ")" ); - args.unshift( "[" + date.toISOString() + "]" ); - return logger[level]( ...args ); + args.unshift('(' + request_id + ')'); + args.unshift('[' + date.toISOString() + ']'); + return logger[level](...args); }; let request_logger = { - fatal: function(...args) { log_func( "fatal", args ) } - ,error: function(...args) { log_func( "error", args ) } - ,warn: function(...args) { log_func( "warn", args ) } - ,info: function(...args) { log_func( "info", args ) } - ,debug: function(...args) { log_func( "debug", args ) } + fatal: function (...args) { + log_func('fatal', args); + }, + error: function (...args) { + log_func('error', args); + }, + warn: function (...args) { + log_func('warn', args); + }, + info: function (...args) { + log_func('info', args); + }, + debug: function (...args) { + log_func('debug', args); + }, }; return request_logger; }; -function context_middleware( logger, conf, db, wa ) -{ - return function(req, res, next) { - const request_logger = make_logger( logger ); - request_logger.info( "Begin request to", req.method, req.path ); +function context_middleware(logger, conf, db, wa) { + return function (req, res, next) { + const request_logger = make_logger(logger); + request_logger.info('Begin request to', req.method, req.path); const checker = new password_checker.Checker( - conf['preferred_password_crypt_method'] - ,db + conf['preferred_password_crypt_method'], + db, ); - req.ctx = new c.Context( conf, request_logger, checker, wa ); + req.ctx = new c.Context(conf, request_logger, checker, wa); - if(! req.session.csrf_secret ) { + if (!req.session.csrf_secret) { const tokens = new Tokens(); - request_logger.info( "Making CSRF secret for new client" ); + request_logger.info('Making CSRF secret for new client'); req.session.csrf_secret = tokens.secretSync(); } try { - next() - } - catch(err) { - request_logger.error( "Error running request: ", - err.toString() ); - request_logger.error( "Stack trace: ", err.stack ); + next(); + } catch (err) { + request_logger.error('Error running request: ', err.toString()); + request_logger.error('Stack trace: ', err.stack); - res.sendStatus( 500 ); + res.sendStatus(500); } - request_logger.info( "Finished setting up", req.method, req.path ); - } + request_logger.info('Finished setting up', req.method, req.path); + }; } let typeorm; +function error_handler_builder(logger) { + return (err, req, res, next) => { + logger.error(err.toString()); + logger.error('Stack trace: ', err.stack); -function error_handler_builder( logger ) { - return ( err, req, res, next ) => { - logger.error( err.toString() ); - logger.error( "Stack trace: ", err.stack ); - - if( res.headersSent ) return next( err ); - res.status( 500 ); + if (res.headersSent) return next(err); + res.status(500); }; -}; +} -function init_server( - conf - ,db - ,typeorm_connection - ,logger - ,wa: wa_api.WA -) -{ +function init_server(conf, db, typeorm_connection, logger, wa: wa_api.WA) { typeorm = typeorm_connection; - let server = setup_server_params( conf, db, typeorm_connection, logger ); - setup_server_routes( conf, db, logger, server, wa ); + let server = setup_server_params(conf, db, typeorm_connection, logger); + setup_server_routes(conf, db, logger, server, wa); return server; } -function get_token( req ) -{ - let auth_header = req.header( 'Authorization' ) || ""; - let tokens = auth_header.split( ' ' ); +function get_token(req) { + let auth_header = req.header('Authorization') || ''; + let tokens = auth_header.split(' '); let token = tokens[1]; return token; } -function session_authorization( logger ) -{ - return (req, res, next ) => { +function session_authorization(logger) { + return (req, res, next) => { const route = req.path; const not_allowed = () => { - logger.error( "User not allowed to access " + route ); + logger.error('User not allowed to access ' + route); res.sendStatus(401); }; - logger.info( "Checking user authorization" ); - // Eventually, we'll have more sophisticated checking for users - // accessing individual routes, but for now, any logged in user can + logger.info('Checking user authorization'); + // Eventually, we'll have more sophisticated checking for users + // accessing individual routes, but for now, any logged in user can // access anything - if( req.session.is_logged_in ) { - logger.info( "User is logged in, allowing" ); + if (req.session.is_logged_in) { + logger.info('User is logged in, allowing'); next(); } // Tests can set an env var to bypass this check // TODO remove - else if( process.env['TEST_RUN'] ) { - logger.info( "Server in test run mode, allowing" ); + else if (process.env['TEST_RUN']) { + logger.info('Server in test run mode, allowing'); next(); } // Everything else is not allowed @@ -139,38 +135,38 @@ function session_authorization( logger ) }; } -function bearer_authorization( logger, db ) -{ - return (req, res, next ) => { +function bearer_authorization(logger, db) { + return (req, res, next) => { const route = req.path; - const token = get_token( req ); + const token = get_token(req); const not_allowed = () => { - logger.error( "User not allowed to access " + route ); + logger.error('User not allowed to access ' + route); res.sendStatus(401); }; - logger.info( "Checking user authorization" ); + logger.info('Checking user authorization'); // Bearer tokens - if( token != undefined ) { - db.is_token_allowed( token - ,() => { - logger.info( "Bearer token is allowed" ); + if (token != undefined) { + db.is_token_allowed( + token, + () => { + logger.info('Bearer token is allowed'); next(); - } - ,() => { - logger.info( "Bearer token is NOT allowed" ); + }, + () => { + logger.info('Bearer token is NOT allowed'); not_allowed(); - } - ,( err: Error ) => { + }, + (err: Error) => { throw err; - } + }, ); } // Tests can set an env var to bypass this check // TODO remove - else if( process.env['TEST_RUN'] ) { - logger.info( "Server in test run mode, allowing" ); + else if (process.env['TEST_RUN']) { + logger.info('Server in test run mode, allowing'); next(); } // Everything else is not allowed @@ -180,106 +176,109 @@ function bearer_authorization( logger, db ) }; } -function setup_server_params( conf, db, typeorm_connection, logger ) -{ - let use_secure_cookie = (conf['deployment_type'] == "prod"); +function setup_server_params(conf, db, typeorm_connection, logger) { + let use_secure_cookie = conf['deployment_type'] == 'prod'; let session_options = { - secret: conf.session_secret - ,resave: false - ,saveUninitialized: true - ,cookie: { - maxAge: conf.session_length_sec - ,sameSite: true - ,secure: use_secure_cookie - ,httpOnly: true - } + secret: conf.session_secret, + resave: false, + saveUninitialized: true, + cookie: { + maxAge: conf.session_length_sec, + sameSite: true, + secure: use_secure_cookie, + httpOnly: true, + }, }; - let session_store = db.session_store( session ); - if(session_store) session_options['store'] = session_store; + let session_store = db.session_store(session); + if (session_store) session_options['store'] = session_store; let server = express(); - server.use( session( session_options ) ); - server.use( bodyParser.json() ); - server.use( bodyParser.raw({ - type: "image/*" - ,limit: conf['photo_size_limit'] - }) ); - server.use( bodyParser.urlencoded({ extended: true }) ); - server.use( express.static( 'public' ) ); - - server.engine( 'handlebars', handlebars({ - defaultLayout: 'main' - }) ); - server.set( 'view engine', 'handlebars' ); - - server.set( "trust proxy", conf.is_behind_reverse_proxy ); + server.use(session(session_options)); + server.use(bodyParser.json()); + server.use( + bodyParser.raw({ + type: 'image/*', + limit: conf['photo_size_limit'], + }), + ); + server.use(bodyParser.urlencoded({extended: true})); + server.use(express.static('public')); + + server.engine( + 'handlebars', + handlebars({ + defaultLayout: 'main', + }), + ); + server.set('view engine', 'handlebars'); + + server.set('trust proxy', conf.is_behind_reverse_proxy); // Init context - logger.setLevel( conf.log_level ); - logger.format = ( level, date, message ) => message; - server.use( error_handler_builder( logger ) ); + logger.setLevel(conf.log_level); + logger.format = (level, date, message) => message; + server.use(error_handler_builder(logger)); - request_funcs.set_db( db, typeorm_connection ); + request_funcs.set_db(db, typeorm_connection); return server; } -function setup_server_routes( - conf - ,db - ,logger - ,server - ,wa: wa_api.WA -) -{ - server.use(context_middleware( logger, conf, db, wa )); +function setup_server_routes(conf, db, logger, server, wa: wa_api.WA) { + server.use(context_middleware(logger, conf, db, wa)); const api = express.Router(); // API requires bearer token authorization - api.use(bearer_authorization( logger, db )); + api.use(bearer_authorization(logger, db)); - api.get('/', request_funcs.get_versions ); + api.get('/', request_funcs.get_versions); const api_v1 = express.Router(); - api_v1.put( '/member', - request_funcs.put_member ); - api_v1.get( '/member/:member_id', - request_funcs.get_member ); - api_v1.route( '/member/:member_id/address') - .put(request_funcs.put_member_address ) - .get(request_funcs.get_member_address ); - api_v1.route( '/member/:member_id/is_active') - .put(request_funcs.put_member_is_active ) - .get(request_funcs.get_member_is_active ); - api_v1.put( '/member/:member_id/rfid', - request_funcs.put_member_rfid ); - api_v1.post( '/member/:member_id/send_signup_email', - request_funcs.post_member_signup_email ); - api_v1.post( '/member/:member_id/send_group_signup_email', - request_funcs.post_group_member_signup_email ); - api_v1.get( '/members/pending', - request_funcs.get_members_pending ); - api_v1.put( '/member/:member_id/wildapricot', - request_funcs.put_member_wildapricot ); - api_v1.put( '/member/:member_id/google_group_signup', - request_funcs.put_member_google_group ); - api_v1.route( '/member/:member_id/photo') - .put(request_funcs.put_member_photo ) - .get(request_funcs.get_member_photo ); - api_v1.get( '/rfid/:rfid', - request_funcs.get_member_rfid ); - api_v1.get( '/rfids', - request_funcs.get_rfid_dump ); - api_v1.post( '/rfid/log_entry/:rfid/:is_allowed', - request_funcs.post_log_rfid ); + api_v1.put('/member', request_funcs.put_member); + api_v1.get('/member/:member_id', request_funcs.get_member); + api_v1 + .route('/member/:member_id/address') + .put(request_funcs.put_member_address) + .get(request_funcs.get_member_address); + api_v1 + .route('/member/:member_id/is_active') + .put(request_funcs.put_member_is_active) + .get(request_funcs.get_member_is_active); + api_v1.put('/member/:member_id/rfid', request_funcs.put_member_rfid); + api_v1.post( + '/member/:member_id/send_signup_email', + request_funcs.post_member_signup_email, + ); + api_v1.post( + '/member/:member_id/send_group_signup_email', + request_funcs.post_group_member_signup_email, + ); + api_v1.get('/members/pending', request_funcs.get_members_pending); + api_v1.put( + '/member/:member_id/wildapricot', + request_funcs.put_member_wildapricot, + ); + api_v1.put( + '/member/:member_id/google_group_signup', + request_funcs.put_member_google_group, + ); + api_v1 + .route('/member/:member_id/photo') + .put(request_funcs.put_member_photo) + .get(request_funcs.get_member_photo); + api_v1.get('/rfid/:rfid', request_funcs.get_member_rfid); + api_v1.get('/rfids', request_funcs.get_rfid_dump); + api_v1.post( + '/rfid/log_entry/:rfid/:is_allowed', + request_funcs.post_log_rfid, + ); api.use('/v1', api_v1); // Install the API router server.use('/api', api); - // Undocumented route for the callback on Google's OAuth token // No longer used //server.get( '/api/v1/google_oauth', @@ -290,152 +289,137 @@ function setup_server_routes( const session_required = session_authorization(logger); // Unauthenticated routes - views.get( '/', request_funcs.tmpl_view( 'home' ) ); - views.get( '/user/is-logged-in', - request_funcs.is_user_logged_in ); - views.post( '/user/login', - request_funcs.login_user ); + views.get('/', request_funcs.tmpl_view('home')); + views.get('/user/is-logged-in', request_funcs.is_user_logged_in); + views.post('/user/login', request_funcs.login_user); // Authenticated routes - views.get( '/members/pending', session_required, - request_funcs.tmpl_view( 'members-pending' ) ); - views.get( '/member/signup', session_required, - request_funcs.member_signup ); - views.get( '/members/active', session_required, - request_funcs.members_active ); - views.get( '/member/show/:member_id', session_required, - request_funcs.member_info ); - views.post( '/user/logout', session_required, - request_funcs.logout_user ); - views.get( '/rfid/log', session_required, - request_funcs.rfid_log ); - views.get( '/tokens', session_required, - request_funcs.tokens ); - views.post( '/tokens/add', session_required, - request_funcs.add_token ); - views.post( '/tokens/delete', session_required, - request_funcs.delete_token ); + views.get( + '/members/pending', + session_required, + request_funcs.tmpl_view('members-pending'), + ); + views.get('/member/signup', session_required, request_funcs.member_signup); + views.get( + '/members/active', + session_required, + request_funcs.members_active, + ); + views.get( + '/member/show/:member_id', + session_required, + request_funcs.member_info, + ); + views.post('/user/logout', session_required, request_funcs.logout_user); + views.get('/rfid/log', session_required, request_funcs.rfid_log); + views.get('/tokens', session_required, request_funcs.tokens); + views.post('/tokens/add', session_required, request_funcs.add_token); + views.post('/tokens/delete', session_required, request_funcs.delete_token); // Install the View routers server.use(views); // 404 handler, must be last in the list - server.use( (req, res, next) => { - logger.error( "Route {" + req.method + " " + req.path - + "} not found" ); - res - .status( 404 ) - .render( 'not-found', { - method: req.method - ,path: req.path - }); + server.use((req, res, next) => { + logger.error('Route {' + req.method + ' ' + req.path + '} not found'); + res.status(404).render('not-found', { + method: req.method, + path: req.path, + }); }); } -function default_db(conf): db_impl.DB -{ +function default_db(conf): db_impl.DB { let db: db_impl.DB = new pg.PG( - conf.db_host - ,conf.db_port - ,conf.db_name - ,conf.db_user - ,conf.db_password + conf.db_host, + conf.db_port, + conf.db_name, + conf.db_user, + conf.db_password, ); return db; } -export function default_conf(): Object -{ +export function default_conf(): Object { return config(); } -function default_wa(conf): wa_api.WA -{ +function default_wa(conf): wa_api.WA { let wa = new wa_api.WildApricot( - conf['wa_api_client'] - ,conf['wa_api_secret'] - ,conf['wa_account_id'] + conf['wa_api_client'], + conf['wa_api_secret'], + conf['wa_account_id'], ); return wa; } -function typeorm_args( conf ) -{ +function typeorm_args(conf) { return { - "name": "default" - ,"type": "postgres" as 'postgres' - ,"host": conf.db_host - ,"port": conf.db_port - ,"username": conf.db_user - ,"password": conf.db_password - ,"database": conf.db_name - ,"schema": "public" - ,"synchronize": false - ,"entities": [ - path.join(__dirname, "src/typeorm/entities/*.{js,ts}") - ] - ,...conf.db_ssl && { + name: 'default', + type: 'postgres' as 'postgres', + host: conf.db_host, + port: conf.db_port, + username: conf.db_user, + password: conf.db_password, + database: conf.db_name, + schema: 'public', + synchronize: false, + entities: [path.join(__dirname, 'src/typeorm/entities/*.{js,ts}')], + ...(conf.db_ssl && { extra: { - ssl: true - } - ,ssl: { - rejectUnauthorized: false - } - } + ssl: true, + }, + ssl: { + rejectUnauthorized: false, + }, + }), }; } - let httpServer; export let SERVER; let logger; export function start( - db?: db_impl.DB - ,conf?: Object - ,wa?: wa_api.WA -): Promise -{ - if(! conf) conf = default_conf(); - if(! db) db = default_db( conf ); - if(! wa) wa = default_wa( conf ); - logger = require( 'logger' ).createLogger( conf["log_file"] ); + db?: db_impl.DB, + conf?: Object, + wa?: wa_api.WA, +): Promise { + if (!conf) conf = default_conf(); + if (!db) db = default_db(conf); + if (!wa) wa = default_wa(conf); + logger = require('logger').createLogger(conf['log_file']); // Fix hanging connections for certain external requests. See: // https://stackoverflow.com/questions/16965582/node-js-http-get-hangs-after-5-requests-to-remote-site http.globalAgent.maxSockets = 1000; - return new Promise( (resolve, reject) => { - createConnection( typeorm_args( conf ) ) - .then( (typeorm_connection) => { - // Init server - SERVER = init_server( conf, db, typeorm_connection, logger, wa ); - httpServer = require( 'http' ).createServer( SERVER ); + return new Promise((resolve, reject) => { + createConnection(typeorm_args(conf)).then(typeorm_connection => { + // Init server + SERVER = init_server(conf, db, typeorm_connection, logger, wa); + httpServer = require('http').createServer(SERVER); - let port = conf["port"]; - // Start server running - httpServer.listen( port ); - logger.info( "Server running on port", port ); + let port = conf['port']; + // Start server running + httpServer.listen(port); + logger.info('Server running on port', port); - resolve(); - }); + resolve(); + }); }); } -export function stop (): Promise -{ - logger.info( "Stopped running server" ); +export function stop(): Promise { + logger.info('Stopped running server'); - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { httpServer.close(() => { - typeorm - .close() - .then( () => { - resolve(); - }); + typeorm.close().then(() => { + resolve(); + }); }); }); } - -if( process.argv[2] == "start" ) start(); +if (process.argv[2] == 'start') start(); diff --git a/get_google_oauth.js b/get_google_oauth.js index fa2d200..59be2d0 100644 --- a/get_google_oauth.js +++ b/get_google_oauth.js @@ -3,15 +3,14 @@ const readline = require('readline'); const {google} = require('googleapis'); const SCOPES = [ - 'https://www.googleapis.com/auth/admin.directory.group.member' - ,'https://www.googleapis.com/auth/admin.directory.group' - ,'https://mail.google.com/' - ,'https://www.googleapis.com/auth/gmail.modify' - ,'https://www.googleapis.com/auth/gmail.compose' - ,'https://www.googleapis.com/auth/gmail.send' + 'https://www.googleapis.com/auth/admin.directory.group.member', + 'https://www.googleapis.com/auth/admin.directory.group', + 'https://mail.google.com/', + 'https://www.googleapis.com/auth/gmail.modify', + 'https://www.googleapis.com/auth/gmail.compose', + 'https://www.googleapis.com/auth/gmail.send', ]; - // Load client secrets from a local file. fs.readFile('google-credentials.json', (err, content) => { if (err) return console.log('Error loading client secret file:', err); @@ -28,7 +27,10 @@ fs.readFile('google-credentials.json', (err, content) => { function authorize(credentials) { const {client_secret, client_id, redirect_uris} = credentials.installed; const oAuth2Client = new google.auth.OAuth2( - client_id, client_secret, redirect_uris[0] ); + client_id, + client_secret, + redirect_uris[0], + ); getNewToken(oAuth2Client); } diff --git a/google_auth.ts b/google_auth.ts index d14c817..308a34a 100644 --- a/google_auth.ts +++ b/google_auth.ts @@ -1,28 +1,26 @@ import * as googleAuth from 'google-auth-library'; -import { Credentials } from 'google-auth-library/build/src/auth/credentials'; +import {Credentials} from 'google-auth-library/build/src/auth/credentials'; import * as fs from 'fs'; import * as readline from 'readline'; - -// TODO +// TODO // * Get credentials from file in config.yaml -> google_credentials_file // * Generate auth URL // * Wait for user to come back with code // * Take code and get the access token // * Dump credentials data to file // * Have main app read from the seprate file, rather than config.yaml -// * Have main app update access, refresh, and expiration configs +// * Have main app update access, refresh, and expiration configs // automatically const scopes: Array = [ - 'https://www.googleapis.com/auth/admin.directory.group.member' - ,'https://www.googleapis.com/auth/admin.directory.group' - ,'https://mail.google.com/' - ,'https://www.googleapis.com/auth/gmail.modify' - ,'https://www.googleapis.com/auth/gmail.compose' - ,'https://www.googleapis.com/auth/gmail.send' + 'https://www.googleapis.com/auth/admin.directory.group.member', + 'https://www.googleapis.com/auth/admin.directory.group', + 'https://mail.google.com/', + 'https://www.googleapis.com/auth/gmail.modify', + 'https://www.googleapis.com/auth/gmail.compose', + 'https://www.googleapis.com/auth/gmail.send', ]; - /** * Step 0: Create OAuth2 credentials at the Google Console (make sure to download JSON, not only just get key and secret) */ @@ -32,78 +30,68 @@ const scopes: Array = [ */ export function getAuthorizeUrl( - credentials - ,callback: (err: any, url: string) => any + credentials, + callback: (err: any, url: string) => any, ): void { const oauth2Client = new googleAuth.OAuth2Client( - credentials.installed.client_id - ,credentials.installed.client_secret - ,credentials.installed.redirect_uris[0] + credentials.installed.client_id, + credentials.installed.client_secret, + credentials.installed.redirect_uris[0], ); - const authUrl = oauth2Client.generateAuthUrl({ - access_type: 'offline', - scope: scopes - }); + const authUrl = oauth2Client.generateAuthUrl({ + access_type: 'offline', + scope: scopes, + }); - callback(null, authUrl); + callback(null, authUrl); } - /** * Step 2: Get auth token */ - export function getAccessToken( - code - ,credentials - ,callback: (err: any, token?: Credentials | null) => any): void -{ + code, + credentials, + callback: (err: any, token?: Credentials | null) => any, +): void { const oauth2Client = new googleAuth.OAuth2Client( - credentials.installed.client_id - ,credentials.installed.client_secret - ,credentials.installed.redirect_uris[0] + credentials.installed.client_id, + credentials.installed.client_secret, + credentials.installed.redirect_uris[0], ); - oauth2Client.getToken( code, (err, token) => { - if(err) return console.log(err); + oauth2Client.getToken(code, (err, token) => { + if (err) return console.log(err); - callback(null, token); - }); + callback(null, token); + }); } - -fs.readFile( 'google-credentials.json', (err, content) => { +fs.readFile('google-credentials.json', (err, content) => { if (err) return console.log('Error loading client secret file:', err); - let credentials = JSON.parse( content.toString() ); - - getAuthorizeUrl( - credentials - ,(err, url) => { - if(err) return console.log(err); - console.log("Auth url is: ", url); - - let rl = readline.createInterface({ - input: process.stdin - ,output: process.stdout + let credentials = JSON.parse(content.toString()); + + getAuthorizeUrl(credentials, (err, url) => { + if (err) return console.log(err); + console.log('Auth url is: ', url); + + let rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + rl.question('Input token: ', token => { + getAccessToken(token, credentials, (err, access) => { + if (err) return console.log(err); + //console.log("Auth token is: ", token); + console.log('google_client_token: ' + token); + console.log('google_access_token: ' + access['access_token']); + console.log('google_token_type: ' + access['token_type']); + console.log('google_refresh_token: ' + access['refresh_token']); + console.log('google_expires_date: ' + access['expiry_date']); }); - - rl.question( "Input token: ", (token) => { - getAccessToken( token, credentials, (err, access) => { - if(err) return console.log(err); - //console.log("Auth token is: ", token); - console.log( "google_client_token: " + token ); - console.log( "google_access_token: " - + access['access_token'] ); - console.log( "google_token_type: " - + access['token_type'] ); - console.log( "google_refresh_token: " - + access['refresh_token'] ); - console.log( "google_expires_date: " - + access['expiry_date'] ); - }); - }); - } - ); + }); + }); }); diff --git a/node.d.ts b/node.d.ts index 065a438..1cdb891 100644 --- a/node.d.ts +++ b/node.d.ts @@ -1 +1 @@ -declare module "short-uuid"; +declare module 'short-uuid'; diff --git a/package-lock.json b/package-lock.json index 6fa7e83..21af980 100644 --- a/package-lock.json +++ b/package-lock.json @@ -951,11 +951,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "env-var": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/env-var/-/env-var-6.3.0.tgz", - "integrity": "sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA==" - }, "es-abstract": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", @@ -2626,6 +2621,11 @@ "xtend": "^4.0.0" } }, + "prettier": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz", + "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==" + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", diff --git a/package.json b/package.json index 74c47e7..8ef9c09 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "start": "ts-node app.ts start", "build": "tsc", + "format": "prettier --write '{src,test,util}/**/*.{js,jsx,ts,tsx}' '*.{js,ts}'", "test": "mocha --require ts-node/register --watch-extensions ts,tsx --timeout 5000 \"test/**/*.{ts,tsx}\"" }, "dependencies": { @@ -56,6 +57,7 @@ "@types/mocha": "^5.2.6", "@types/supertest": "^2.0.7", "mocha": "^5.2.0", + "prettier": "^2.1.1", "supertest": "^3.3.0", "ts-mocha": "^6.0.0", "ts-node": "^8.0.3" diff --git a/src/config.ts b/src/config.ts index a60d1a8..9ff7e2d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,95 +1,98 @@ -import * as fs from "fs"; -import * as yaml from "js-yaml"; +import * as fs from 'fs'; +import * as yaml from 'js-yaml'; // import * as env from 'env-var'; -import * as nconf from "nconf"; -import nconf_yaml from "nconf-yaml"; +import * as nconf from 'nconf'; +import nconf_yaml from 'nconf-yaml'; interface AppConfig { - port: number, - deployment_type: "dev" | "prod", - log_file: string, - log_level: "debug" | "info" | "warn" | "error", + port: number; + deployment_type: 'dev' | 'prod'; + log_file: string; + log_level: 'debug' | 'info' | 'warn' | 'error'; } interface PasswordConfig { - preferred_password_crypt_method: string, + preferred_password_crypt_method: string; } interface SessionConfig { - session_secret: string, - session_length_sec: number + session_secret: string; + session_length_sec: number; } interface WildApricotConfig { - wa_api_client: string, - wa_api_secret: string, - wa_account_id: number, + wa_api_client: string; + wa_api_secret: string; + wa_account_id: number; } // TODO: Add Google and Email configuration interface DatabaseConfig { - db_user: string, - db_password: string, - db_name: string, - db_host: string, - db_port: number, - db_ssl: boolean, -}; + db_user: string; + db_password: string; + db_name: string; + db_host: string; + db_port: number; + db_ssl: boolean; +} type Config = AppConfig & PasswordConfig & DatabaseConfig & WildApricotConfig; const appConfigDefaults = { port: 3001, - deployment_type: "dev", - log_file: "dev.log", - log_level: "info" -} + deployment_type: 'dev', + log_file: 'dev.log', + log_level: 'info', +}; const passwordConfigDefaults = { - preferred_password_crypt_method: "bcrypt_10" + preferred_password_crypt_method: 'bcrypt_10', }; const sessionConfigDefaults = { - session_secret: "xxxx", + session_secret: 'xxxx', session_length_sec: 3600000, -} +}; const wildApricotConfigDefaults = { - wa_api_client: "", - wa_api_secret: "", + wa_api_client: '', + wa_api_secret: '', wa_account_id: 0, -} +}; const databaseConfigDefaults = { - db_user: "bodgery", - db_password: "", - db_name: "bodgery_members", - db_host: "localhost", + db_user: 'bodgery', + db_password: '', + db_name: 'bodgery_members', + db_host: 'localhost', db_port: 5432, - db_ssl: false -} - + db_ssl: false, +}; -export default function(): Config { - return nconf.argv({ - port: { - description: "Port to listen on", - alias: "p", - type: "number" - } - }).env({ - lowerCase: true, - parseValues: true, - }).file({ - file: 'config.yaml', - format: nconf_yaml, - }) - .defaults({ - ...appConfigDefaults, - ...passwordConfigDefaults, - ...sessionConfigDefaults, - ...databaseConfigDefaults, - ...wildApricotConfigDefaults, - }).get() +export default function (): Config { + return nconf + .argv({ + port: { + description: 'Port to listen on', + alias: 'p', + type: 'number', + }, + }) + .env({ + lowerCase: true, + parseValues: true, + }) + .file({ + file: 'config.yaml', + format: nconf_yaml, + }) + .defaults({ + ...appConfigDefaults, + ...passwordConfigDefaults, + ...sessionConfigDefaults, + ...databaseConfigDefaults, + ...wildApricotConfigDefaults, + }) + .get(); } diff --git a/src/context.ts b/src/context.ts index 211b17d..8cefb8c 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,9 +1,7 @@ -import * as password from "./password"; -import * as wa_api from "./wild_apricot"; +import * as password from './password'; +import * as wa_api from './wild_apricot'; - -export interface Logger -{ +export interface Logger { fatal(...args): void; error(...args): void; warn(...args): void; @@ -11,20 +9,17 @@ export interface Logger debug(...args): void; } - -export class Context -{ +export class Context { public conf: any; public logger: Logger; public password_checker: password.Checker; public wa: wa_api.WA; - constructor( - conf: any - ,logger: Logger - ,password_checker: password.Checker - ,wa: wa_api.WA + conf: any, + logger: Logger, + password_checker: password.Checker, + wa: wa_api.WA, ) { this.conf = conf; this.logger = logger; @@ -32,13 +27,11 @@ export class Context this.wa = wa; } - isDev(): boolean - { - return "dev" == this.conf['deployment_type']; + isDev(): boolean { + return 'dev' == this.conf['deployment_type']; } - isProd(): boolean - { - return "prod" == this.conf['deployment_type']; + isProd(): boolean { + return 'prod' == this.conf['deployment_type']; } } diff --git a/src/db-fixture-pg.ts b/src/db-fixture-pg.ts index 4926b00..7928227 100644 --- a/src/db-fixture-pg.ts +++ b/src/db-fixture-pg.ts @@ -1,27 +1,17 @@ -import * as pg_db from "./db-pg"; -import * as shortid from "shortid"; +import * as pg_db from './db-pg'; +import * as shortid from 'shortid'; - -export class PGFixture -{ +export class PGFixture { tool1ID: number = null; tool1Name: string = null; tool2ID: number = null; tool2Name: string = null; + constructor() {} - constructor() - { - } - - - public addToDB( - db_frontend: pg_db.PG - ,success_callback: () => void - ): void - { + public addToDB(db_frontend: pg_db.PG, success_callback: () => void): void { // @ts-ignore - let db = db_frontend.client; + let db = db_frontend.client; let tool2_callback = (tool_id, tool_name, area_id, member_id) => { this.tool2ID = tool_id; @@ -31,108 +21,100 @@ export class PGFixture let tool1_callback = (tool_id, tool_name, area_id, member_id) => { this.tool1ID = tool_id; this.tool1Name = tool_name; - this.addTool( db, area_id, member_id, - (tool2_id, tool2_name) => tool2_callback( - tool2_id, tool2_name, area_id, member_id ) + this.addTool(db, area_id, member_id, (tool2_id, tool2_name) => + tool2_callback(tool2_id, tool2_name, area_id, member_id), ); }; let member_callback = (member_id, area_id) => { - this.addTool( db, area_id, member_id, - (tool1_id, tool1_name) => tool1_callback( - tool1_id, tool1_name, area_id, member_id ) + this.addTool(db, area_id, member_id, (tool1_id, tool1_name) => + tool1_callback(tool1_id, tool1_name, area_id, member_id), ); }; - let area_callback = (area_id) => { - this.addMember( db, - (member_id) => member_callback( member_id, area_id ) ); + let area_callback = area_id => { + this.addMember(db, member_id => + member_callback(member_id, area_id), + ); }; - this.addArea( db, area_callback ); + this.addArea(db, area_callback); } - - private addArea( - db - ,success_callback: ( area_id: number ) => void - ): void - { - db.query({ - text: [ - "INSERT INTO areas (" - ,"area_name" - ,") VALUES ($1) RETURNING id" - ].join( " " ) - ,values: [ - "test_area" - ] - }, (err, res) => { - if( err ) { - throw new Error( "Error inserting new area into database: " - + err.toString() ); - } - else { - success_callback( res.rows[0].id ); - } - }); + private addArea(db, success_callback: (area_id: number) => void): void { + db.query( + { + text: [ + 'INSERT INTO areas (', + 'area_name', + ') VALUES ($1) RETURNING id', + ].join(' '), + values: ['test_area'], + }, + (err, res) => { + if (err) { + throw new Error( + 'Error inserting new area into database: ' + + err.toString(), + ); + } else { + success_callback(res.rows[0].id); + } + }, + ); } - private addMember( - db - ,success_callback: ( member_id: number ) => void - ): void - { - db.query({ - text: [ - "INSERT INTO members (" - ,"full_name" - ,") VALUES ($1) RETURNING id" - ].join( " " ) - ,values: [ - "Test Member" - ] - }, (err, res) => { - if( err ) { - throw new Error( "Error inserting new member into database: " - + err.toString() ); - } - else { - success_callback( res.rows[0].id ); - } - }); + private addMember(db, success_callback: (member_id: number) => void): void { + db.query( + { + text: [ + 'INSERT INTO members (', + 'full_name', + ') VALUES ($1) RETURNING id', + ].join(' '), + values: ['Test Member'], + }, + (err, res) => { + if (err) { + throw new Error( + 'Error inserting new member into database: ' + + err.toString(), + ); + } else { + success_callback(res.rows[0].id); + } + }, + ); } private addTool( - db - ,area_id: number - ,owner_id: number - ,success_callback: ( tool_id: number, tool_name: string ) => void - ): void - { + db, + area_id: number, + owner_id: number, + success_callback: (tool_id: number, tool_name: string) => void, + ): void { let tool_name = shortid.generate(); - db.query({ - text: [ - "INSERT INTO tools (" - ,"name" - ,",area_id" - ,",color" - ,",owner_id" - ,") VALUES ( $1, $2, $3, $4 ) RETURNING id" - ].join( " " ) - ,values: [ - tool_name - ,area_id - ,"green" - ,owner_id - ] - }, (err, res) => { - if( err ) { - throw new Error( "Error inserting new tool into database: " - + err.toString() ); - } - else { - success_callback( res.rows[0].id, tool_name ); - } - }); + db.query( + { + text: [ + 'INSERT INTO tools (', + 'name', + ',area_id', + ',color', + ',owner_id', + ') VALUES ( $1, $2, $3, $4 ) RETURNING id', + ].join(' '), + values: [tool_name, area_id, 'green', owner_id], + }, + (err, res) => { + if (err) { + throw new Error( + 'Error inserting new tool into database: ' + + err.toString(), + ); + } else { + success_callback(res.rows[0].id, tool_name); + } + }, + ); } } diff --git a/src/db-mock.ts b/src/db-mock.ts index 246f346..9082920 100644 --- a/src/db-mock.ts +++ b/src/db-mock.ts @@ -1,58 +1,50 @@ -import * as db_impl from "./db"; +import * as db_impl from './db'; - -export class MockDB -{ +export class MockDB { members: Object = {}; users: Object = {}; - rfid_log: Array<[ string, boolean ]>; + rfid_log: Array<[string, boolean]>; tokens: Object = {}; - constructor( - members: Object - ,users: Object - ,rfid_log?: Array<[ string, boolean ]> - ,tokens?: Object - ) - { + members: Object, + users: Object, + rfid_log?: Array<[string, boolean]>, + tokens?: Object, + ) { this.members = members; this.users = users; this.rfid_log = rfid_log || []; this.tokens = tokens || {}; } - add_member( - member: db_impl.SimpleMember - ,success_callback: ( member_id ) => void - ,error_callback: (err: Error) => void - ): boolean - { + member: db_impl.SimpleMember, + success_callback: (member_id) => void, + error_callback: (err: Error) => void, + ): boolean { let id = member.rfid; this.members[id] = {}; this.members[id].simple_data = member; - success_callback( id ); + success_callback(id); return true; } get_member( - member_id: string - ,success_callback: ( member: db_impl.Member ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (member: db_impl.Member) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { - success_callback( member_matched.simple_data ); - } - else { + if (member_matched != null) { + success_callback(member_matched.simple_data); + } else { no_member_found_callback( - new Error( "Could not find match for member ID '" - + member_id + "'" - ) + new Error( + "Could not find match for member ID '" + member_id + "'", + ), ); } @@ -60,14 +52,13 @@ export class MockDB } set_member_photo( - member_id: string - ,path: string - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: (err: Error) => void - ): boolean - { - if( ! this.members[member_id] ){ + member_id: string, + path: string, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { + if (!this.members[member_id]) { this.members[member_id] = {}; } this.members[member_id].photo = path; @@ -76,18 +67,16 @@ export class MockDB } get_member_photo( - member_id: string - ,success_callback: ( path: string ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { - if( this.members[member_id].photo ) { - success_callback( this.members[member_id].photo ); - } - else { + member_id: string, + success_callback: (path: string) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { + if (this.members[member_id].photo) { + success_callback(this.members[member_id].photo); + } else { no_member_found_callback( - new Error( "No member found with ID " + member_id ) + new Error('No member found with ID ' + member_id), ); } @@ -95,24 +84,22 @@ export class MockDB } put_member_address( - member_id: string - ,address: db_impl.USAddress - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + address: db_impl.USAddress, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { + if (member_matched != null) { member_matched.address = address; success_callback(); - } - else { + } else { no_member_found_callback( - new Error( "Could not find match for member ID '" - + member_id + "'" - ) + new Error( + "Could not find match for member ID '" + member_id + "'", + ), ); } @@ -120,22 +107,20 @@ export class MockDB } get_member_address( - member_id: string - ,success_callback: ( address: db_impl.USAddress ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (address: db_impl.USAddress) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { - success_callback( member_matched.address ); - } - else { + if (member_matched != null) { + success_callback(member_matched.address); + } else { no_member_found_callback( - new Error( "Could not find match for member ID '" - + member_id + "'" - ) + new Error( + "Could not find match for member ID '" + member_id + "'", + ), ); } @@ -143,24 +128,22 @@ export class MockDB } set_member_is_active( - member_id: string - ,is_active: boolean - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + is_active: boolean, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { + if (member_matched != null) { member_matched.is_active = is_active; success_callback(); - } - else { + } else { no_member_found_callback( - new Error( "Could not find match for member ID '" - + member_id + "'" - ) + new Error( + "Could not find match for member ID '" + member_id + "'", + ), ); } @@ -168,22 +151,20 @@ export class MockDB } get_member_is_active( - member_id: string - ,success_callback: ( is_active: boolean ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (is_active: boolean) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { - success_callback( member_matched.is_active ); - } - else { + if (member_matched != null) { + success_callback(member_matched.is_active); + } else { no_member_found_callback( - new Error( "Could not find match for member ID '" - + member_id + "'" - ) + new Error( + "Could not find match for member ID '" + member_id + "'", + ), ); } @@ -191,20 +172,18 @@ export class MockDB } put_member_wild_apricot( - member_id: string - ,wild_apricot_id: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + wild_apricot_id: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { - member_matched['full_data']['wild_apricot_id'] = wild_apricot_id + if (member_matched != null) { + member_matched['full_data']['wild_apricot_id'] = wild_apricot_id; success_callback(); - } - else { + } else { no_member_found_callback(); } @@ -212,18 +191,16 @@ export class MockDB } get_member_wild_apricot( - member_id: string - ,success_callback: ( wild_apricot_id: string ) => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (wild_apricot_id: string) => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { - success_callback( member_matched.wild_apricot_id ); - } - else { + if (member_matched != null) { + success_callback(member_matched.wild_apricot_id); + } else { no_member_found_callback(); } @@ -231,20 +208,18 @@ export class MockDB } set_member_rfid( - member_id: string - ,rfid: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + rfid: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let member_matched = this.members[member_id]; - if( member_matched != null ) { + if (member_matched != null) { member_matched.rfid = rfid; success_callback(); - } - else { + } else { no_member_found_callback(); } @@ -252,26 +227,24 @@ export class MockDB } get_member_rfid( - rfid: string - ,success_callback: () => void - ,inactive_member_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { - let member_id_matched = Object.keys( this.members ) - .find( (_, i, obj) => this.members[_].rfid == rfid ); - - if( member_id_matched != null ) { + rfid: string, + success_callback: () => void, + inactive_member_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { + let member_id_matched = Object.keys(this.members).find( + (_, i, obj) => this.members[_].rfid == rfid, + ); + + if (member_id_matched != null) { let member_matched = this.members[member_id_matched]; - if( member_matched.is_active ) { + if (member_matched.is_active) { success_callback(); - } - else { + } else { inactive_member_callback(); } - } - else { + } else { no_member_found_callback(); } @@ -279,99 +252,93 @@ export class MockDB } rfid_dump( - success_callback: ( dump: any ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + success_callback: (dump: any) => void, + error_callback: (err: Error) => void, + ): boolean { let rfids = {}; - Object.values( this.members ).forEach( (item) => { + Object.values(this.members).forEach(item => { let rfid_tag = item.simple_data.rfid; rfids[rfid_tag] = true; }); - success_callback( rfids ); + success_callback(rfids); return true; } log_rfid_entry( - rfid: string - ,is_active: boolean - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { - this.rfid_log.push([ rfid, is_active ]); + rfid: string, + is_active: boolean, + success_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { + this.rfid_log.push([rfid, is_active]); success_callback(); return true; } get_rfid_log( - offset: number - ,per_page: number - ,success_callback: ( logs: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO as this is currently only for the frontend, and we - // connect to a real database when we run that, this isn't + offset: number, + per_page: number, + success_callback: (logs: Array) => void, + error_callback: (err: Error) => void, + ): void { + // TODO as this is currently only for the frontend, and we + // connect to a real database when we run that, this isn't // implemented. success_callback([]); } add_user( - username: string - ,password: string - ,salt: string - ,crypt_type: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + username: string, + password: string, + salt: string, + crypt_type: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { this.users[username] = { - password: password - ,crypt_type: crypt_type - ,salt: salt + password: password, + crypt_type: crypt_type, + salt: salt, }; success_callback(); } get_password_data_for_user( - username: string - ,success_callback: ( stored_data: { - password: string - ,crypt_type: string - ,salt: string - }) => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { - if(! this.users.hasOwnProperty( username ) ) { + username: string, + success_callback: (stored_data: { + password: string; + crypt_type: string; + salt: string; + }) => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { + if (!this.users.hasOwnProperty(username)) { no_user_found_callback(); return; } let user = this.users[username]; success_callback({ - password: user.password - ,crypt_type: user.crypt_type - ,salt: user.salt + password: user.password, + crypt_type: user.crypt_type, + salt: user.salt, }); } set_password_data_for_user( - username: string - ,new_password: string - ,new_crypt_method: string - ,salt: string - ,success_callback: () => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + username: string, + new_password: string, + new_crypt_method: string, + salt: string, + success_callback: () => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { let user = this.users[username]; - if(! user) no_user_found_callback(); + if (!user) no_user_found_callback(); user.password = new_password; user.crypt_type = new_crypt_method; @@ -380,67 +347,60 @@ export class MockDB success_callback(); } - session_store( express_session ) - { + session_store(express_session) { return null; } add_token( - username: string - ,token: string - ,name: string - ,notes: string - ,success_handler: () => void - ,no_user_found_callback: () => void - ,error_handler: ( err: Error ) => void - ): void - { + username: string, + token: string, + name: string, + notes: string, + success_handler: () => void, + no_user_found_callback: () => void, + error_handler: (err: Error) => void, + ): void { this.tokens[token] = true; success_handler(); } is_token_allowed( - token: string - ,success_callback: () => void - ,no_token_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { - if( token in this.tokens ) { + token: string, + success_callback: () => void, + no_token_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { + if (token in this.tokens) { success_callback(); - } - else { + } else { no_token_found_callback(); } } get_members( - offset: number - ,per_page: number - ,success_callback: ( members: Array ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { - let members = Object.values( this.members ) - .map( (_) => _.simple_data ); - - if( offset ) { - members = members.filter( function (member, index) { + offset: number, + per_page: number, + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): boolean { + let members = Object.values(this.members).map(_ => _.simple_data); + + if (offset) { + members = members.filter(function (member, index) { return index >= offset; }); } - if( per_page ) { - members = members.filter( function (member, index) { + if (per_page) { + members = members.filter(function (member, index) { return index < per_page; }); } - success_callback( members ); + success_callback(members); return true; } - end(): void - { + end(): void { // Do nothing, and do it well } } diff --git a/src/db-pg.ts b/src/db-pg.ts index 03c123e..d31290c 100644 --- a/src/db-pg.ts +++ b/src/db-pg.ts @@ -1,1008 +1,911 @@ -import * as db_impl from "./db"; -import * as pg from "pg"; -import * as pg_escape from "pg-escape"; -import * as session from "connect-pg-simple"; - +import * as db_impl from './db'; +import * as pg from 'pg'; +import * as pg_escape from 'pg-escape'; +import * as session from 'connect-pg-simple'; let no_rows_callback_builder = (member_id, callback) => { - return () => callback( - new Error( "Could not find member for ID " + member_id ) - ); + return () => + callback(new Error('Could not find member for ID ' + member_id)); }; -let success_no_rows_callback_builder = (success_callback) => { - return (rows) => success_callback(); +let success_no_rows_callback_builder = success_callback => { + return rows => success_callback(); }; -let success_first_rows_callback_builder = (success_callback) => { - return (rows) => success_callback( rows[0] ); +let success_first_rows_callback_builder = success_callback => { + return rows => success_callback(rows[0]); }; - -export class PG -{ +export class PG { private pool: any; - constructor( - host: string - ,port: number - ,name: string - ,user: string - ,pass: string - ,use_ssl: boolean = false - ) - { + host: string, + port: number, + name: string, + user: string, + pass: string, + use_ssl: boolean = false, + ) { this.pool = new pg.Pool({ - host: host - ,port: port - ,database: name - ,user: user - ,password: pass - ,...use_ssl && { + host: host, + port: port, + database: name, + user: user, + password: pass, + ...(use_ssl && { ssl: { - rejectUnauthorized: false - } - } + rejectUnauthorized: false, + }, + }), }); } - add_member( - member: db_impl.SimpleMember - ,success_callback: (member_id) => void - ,error_callback: (err: Error) => void - ): boolean - { + member: db_impl.SimpleMember, + success_callback: (member_id) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "add-member" - ,text: [ - "INSERT INTO members (" - ,"rfid" - ,",first_name" - ,",last_name" - ,",phone" - ,",email" - ,") VALUES ($1, $2, $3, $4, $5) RETURNING member_id" - ].join( " " ) - ,values: [ - member.rfid - ,member.firstName - ,member.lastName - ,member.phone - ,member.email - ] + name: 'add-member', + text: [ + 'INSERT INTO members (', + 'rfid', + ',first_name', + ',last_name', + ',phone', + ',email', + ') VALUES ($1, $2, $3, $4, $5) RETURNING member_id', + ].join(' '), + values: [ + member.rfid, + member.firstName, + member.lastName, + member.phone, + member.email, + ], }; - let main_callback = (rows) => success_callback( rows[0].member_id ); + let main_callback = rows => success_callback(rows[0].member_id); - this.call_query( - query - ,main_callback - ,null - ,error_callback - ); + this.call_query(query, main_callback, null, error_callback); return true; } get_member( - member_id: string - ,success_callback: ( member: db_impl.Member ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (member: db_impl.Member) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member" - ,text: [ - "SELECT" - ,"member_id" - ,",rfid" - ,",first_name" - ,",last_name" - ,",phone" - ,",email" - ,"FROM members WHERE member_id = $1" - ].join( " " ) - ,values: [ member_id ] + name: 'get-member', + text: [ + 'SELECT', + 'member_id', + ',rfid', + ',first_name', + ',last_name', + ',phone', + ',email', + 'FROM members WHERE member_id = $1', + ].join(' '), + values: [member_id], }; - let main_callback = (rows) => { + let main_callback = rows => { let member = rows[0]; - // Would like to use aliases in the SQL statement - // (e.g., "first_name AS firstName"), but PostgreSQL + // Would like to use aliases in the SQL statement + // (e.g., "first_name AS firstName"), but PostgreSQL // returns it in all lowercase member.firstName = member.first_name; member.lastName = member.last_name; delete member.first_name; delete member.last_name; - success_callback( member ); + success_callback(member); }; this.call_query( - query - ,main_callback - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + main_callback, + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } set_member_photo( - member_id: string - ,path: string - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + path: string, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "update-member-photo" - ,text: [ - "UPDATE members" - ,"SET photo = $1" - ,"WHERE member_id = $2" - ].join( " " ) - ,values: [ - path - ,member_id - ] + name: 'update-member-photo', + text: [ + 'UPDATE members', + 'SET photo = $1', + 'WHERE member_id = $2', + ].join(' '), + values: [path, member_id], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + success_no_rows_callback_builder(success_callback), + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } get_member_photo( - member_id: string - ,success_callback: ( path: string ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (path: string) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member-photo" - ,text: [ - "SELECT" - ,"photo" - ,"FROM members WHERE member_id = $1" - ].join( " " ) - ,values: [ member_id ] + name: 'get-member-photo', + text: ['SELECT', 'photo', 'FROM members WHERE member_id = $1'].join( + ' ', + ), + values: [member_id], }; - let main_callback = (rows) => { + let main_callback = rows => { let member = rows[0]; let photo = member.photo; - success_callback( photo ); + success_callback(photo); }; this.call_query( - query - ,main_callback - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + main_callback, + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } put_member_address( - member_id: string - ,address: db_impl.USAddress - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + address: db_impl.USAddress, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { this.transaction( - (client, done) => this.insert_address( - client - ,address - ,(addr_id) => { - this.update_user_address( - client - ,member_id - ,addr_id - ,done - ,no_member_found_callback - ,error_callback - ); - } - ,error_callback - ) - ,success_callback - ,error_callback + (client, done) => + this.insert_address( + client, + address, + addr_id => { + this.update_user_address( + client, + member_id, + addr_id, + done, + no_member_found_callback, + error_callback, + ); + }, + error_callback, + ), + success_callback, + error_callback, ); return true; } get_member_address( - member_id: string - ,success_callback: ( address: db_impl.USAddress ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (address: db_impl.USAddress) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member-address" - ,text: [ - "SELECT" - ,"address1" - ,",address2" - ,",city" - ,",state" - ,",zip" - ,"FROM us_address" - ,"JOIN members ON (members.address_id = us_address.id)" - ,"WHERE members.member_id = $1" - ].join( " " ) - ,values: [ member_id ] + name: 'get-member-address', + text: [ + 'SELECT', + 'address1', + ',address2', + ',city', + ',state', + ',zip', + 'FROM us_address', + 'JOIN members ON (members.address_id = us_address.id)', + 'WHERE members.member_id = $1', + ].join(' '), + values: [member_id], }; - let main_callback = (rows) => success_callback( rows[0] ); + let main_callback = rows => success_callback(rows[0]); this.call_query( - query - ,success_first_rows_callback_builder( success_callback ) - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + success_first_rows_callback_builder(success_callback), + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } put_member_wild_apricot( - member_id: string - ,wild_apricot_id: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + wild_apricot_id: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "update-member-wild-apricot" - ,text: [ - "UPDATE members" - ,"SET wildapricot_id = $1" - ,"WHERE member_id = $2" - ].join( " " ) - ,values: [ - wild_apricot_id - ,member_id - ] + name: 'update-member-wild-apricot', + text: [ + 'UPDATE members', + 'SET wildapricot_id = $1', + 'WHERE member_id = $2', + ].join(' '), + values: [wild_apricot_id, member_id], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + success_no_rows_callback_builder(success_callback), + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } get_member_wild_apricot( - member_id: string - ,success_callback: ( wild_apricot_id: string ) => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (wild_apricot_id: string) => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member-wild-apricot" - ,text: [ - "SELECT" - ,"wildapricot_id" - ,"FROM members" - ,"WHERE member_id = $1" - ].join( " " ) - ,values: [ member_id ] + name: 'get-member-wild-apricot', + text: [ + 'SELECT', + 'wildapricot_id', + 'FROM members', + 'WHERE member_id = $1', + ].join(' '), + values: [member_id], }; - let main_callback = (rows) => success_callback( - rows[0]['wildapricot_id'] ); + let main_callback = rows => success_callback(rows[0]['wildapricot_id']); this.call_query( - query - ,main_callback - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + main_callback, + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } set_member_is_active( - member_id: string - ,is_active: boolean - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + is_active: boolean, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "update-member-active" - ,text: [ - "UPDATE members" - ,"SET status = $1" - ,"WHERE member_id = $2" - ].join( " " ) - ,values: [ - is_active - ,member_id - ] + name: 'update-member-active', + text: [ + 'UPDATE members', + 'SET status = $1', + 'WHERE member_id = $2', + ].join(' '), + values: [is_active, member_id], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + success_no_rows_callback_builder(success_callback), + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } get_member_is_active( - member_id: string - ,success_callback: ( is_active: boolean ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + success_callback: (is_active: boolean) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member-active" - ,text: [ - "SELECT status" - ,"FROM members" - ,"WHERE members.member_id = $1" - ].join( " " ) - ,values: [ member_id ] + name: 'get-member-active', + text: [ + 'SELECT status', + 'FROM members', + 'WHERE members.member_id = $1', + ].join(' '), + values: [member_id], }; - let main_callback = (rows) => { - success_callback( rows[0].status ); + let main_callback = rows => { + success_callback(rows[0].status); }; this.call_query( - query - ,main_callback - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback + query, + main_callback, + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, ); return true; } set_member_rfid( - member_id: string - ,rfid: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + member_id: string, + rfid: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "set-member-rfid" - ,text: [ - "UPDATE members" - ,"SET rfid = $1" - ,"WHERE member_id = $2" - ].join( " " ) - ,values: [ - rfid - ,member_id - ] + name: 'set-member-rfid', + text: [ + 'UPDATE members', + 'SET rfid = $1', + 'WHERE member_id = $2', + ].join(' '), + values: [rfid, member_id], }; this.call_query( - query - ,(rows) => success_callback() - ,no_member_found_callback - ,error_callback + query, + rows => success_callback(), + no_member_found_callback, + error_callback, ); return true; } get_member_rfid( - rfid: string - ,success_callback: () => void - ,inactive_member_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + rfid: string, + success_callback: () => void, + inactive_member_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "get-member-rfid" - ,text: [ - "SELECT status" - ,"FROM members" - ,"WHERE rfid = $1" - ].join( " " ) - ,values: [ rfid ] + name: 'get-member-rfid', + text: ['SELECT status', 'FROM members', 'WHERE rfid = $1'].join( + ' ', + ), + values: [rfid], }; this.call_query( - query - ,(rows) => { - if( rows[0].status ) { - success_callback() - } - else { - inactive_member_callback() + query, + rows => { + if (rows[0].status) { + success_callback(); + } else { + inactive_member_callback(); } - } - ,no_member_found_callback - ,error_callback + }, + no_member_found_callback, + error_callback, ); return true; } rfid_dump( - success_callback: ( dump: any ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + success_callback: (dump: any) => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "dump-rfid" - ,text: [ - "SELECT rfid" - ,"FROM members" - ,"WHERE status = true" - ].join( " " ) - ,values: [ ] + name: 'dump-rfid', + text: ['SELECT rfid', 'FROM members', 'WHERE status = true'].join( + ' ', + ), + values: [], }; this.call_query( - query - ,(rows) => { + query, + rows => { let rfid = {}; - rows.forEach( (_) => { + rows.forEach(_ => { let tag = _['rfid']; rfid[tag] = true; }); - success_callback( rfid ); - } - ,() => { success_callback( {} ) } - ,error_callback + success_callback(rfid); + }, + () => { + success_callback({}); + }, + error_callback, ); return true; } log_rfid_entry( - rfid: string - ,is_active: boolean - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): boolean - { + rfid: string, + is_active: boolean, + success_callback: () => void, + error_callback: (err: Error) => void, + ): boolean { let query = { - name: "insert-rfid-log" - ,text: [ - "INSERT INTO rfid_log" - ,"(rfid, is_active, member_id)" - ,"VALUES ($1, $2," - ,"(SELECT id FROM members WHERE rfid = $1 LIMIT 1)" - ,")" - ].join( " " ) - ,values: [ - rfid - ,is_active - ] + name: 'insert-rfid-log', + text: [ + 'INSERT INTO rfid_log', + '(rfid, is_active, member_id)', + 'VALUES ($1, $2,', + '(SELECT id FROM members WHERE rfid = $1 LIMIT 1)', + ')', + ].join(' '), + values: [rfid, is_active], }; - this.call_query( - query - ,success_callback - ,null - ,error_callback - ); + this.call_query(query, success_callback, null, error_callback); return true; } get_rfid_log( - offset: number - ,per_page: number - ,success_callback: ( logs: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { + offset: number, + per_page: number, + success_callback: (logs: Array) => void, + error_callback: (err: Error) => void, + ): void { let placeholder = this.placeholder_generator(); let query_text = [ - "SELECT" - ,"rfid_log.rfid rfid" - ,",rfid_log.is_active is_active" - ,",rfid_log.log_timestamp date" - ,",members.first_name first_name" - ,",members.last_name last_name" - ,",members.member_id member_id" - ,"FROM rfid_log" - ,"LEFT JOIN members ON members.id = rfid_log.member_id" - ,"ORDER BY rfid_log.log_timestamp" + 'SELECT', + 'rfid_log.rfid rfid', + ',rfid_log.is_active is_active', + ',rfid_log.log_timestamp date', + ',members.first_name first_name', + ',members.last_name last_name', + ',members.member_id member_id', + 'FROM rfid_log', + 'LEFT JOIN members ON members.id = rfid_log.member_id', + 'ORDER BY rfid_log.log_timestamp', ]; - let name = "get-rfid-log"; + let name = 'get-rfid-log'; let values = []; - if( per_page != null ) { - name += "-limit"; - query_text.push( "LIMIT " + placeholder() ); - values.push( per_page ); + if (per_page != null) { + name += '-limit'; + query_text.push('LIMIT ' + placeholder()); + values.push(per_page); } - if( offset != null ) { - name += "-offset"; - query_text.push( "OFFSET " + placeholder() ); - values.push( offset ); + if (offset != null) { + name += '-offset'; + query_text.push('OFFSET ' + placeholder()); + values.push(offset); } let query = { - name: name - ,text: query_text.join( " " ) - ,values: values + name: name, + text: query_text.join(' '), + values: values, }; - this.call_query( query - ,( rows ) => { - let results = rows.map( (row) => { + this.call_query( + query, + rows => { + let results = rows.map(row => { return { - rfid: row.rfid - ,firstName: row.first_name - ,lastName: row.last_name - ,memberID: row.member_id - ,isAllowed: row.is_active - ,date: row.date + rfid: row.rfid, + firstName: row.first_name, + lastName: row.last_name, + memberID: row.member_id, + isAllowed: row.is_active, + date: row.date, }; }); - success_callback( results ); - } - ,() => { - success_callback( [] ); - } - ,error_callback + success_callback(results); + }, + () => { + success_callback([]); + }, + error_callback, ); } add_user( - username: string - ,password: string - ,salt: string - ,crypt_type: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + username: string, + password: string, + salt: string, + crypt_type: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "add-user" - ,text: [ - "INSERT INTO users (" - ,"email" - ,",password" - ,",password_salt" - ,",password_storage" - ,") VALUES ($1, $2, $3, $4)" - ].join( " " ) - ,values: [ - username - ,password - ,salt - ,crypt_type - ] + name: 'add-user', + text: [ + 'INSERT INTO users (', + 'email', + ',password', + ',password_salt', + ',password_storage', + ') VALUES ($1, $2, $3, $4)', + ].join(' '), + values: [username, password, salt, crypt_type], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,null - ,error_callback + query, + success_no_rows_callback_builder(success_callback), + null, + error_callback, ); } get_password_data_for_user( - username: string - ,success_callback: ( stored_data: { - password: string - ,crypt_type: string - ,salt: string - }) => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + username: string, + success_callback: (stored_data: { + password: string; + crypt_type: string; + salt: string; + }) => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "get-user-password" - ,text: [ - "SELECT" - ,"password" - ,",password_storage" - ,",password_salt" - ,"FROM users" - ,"WHERE email = $1" - ].join( " " ) - ,values: [ username ] + name: 'get-user-password', + text: [ + 'SELECT', + 'password', + ',password_storage', + ',password_salt', + 'FROM users', + 'WHERE email = $1', + ].join(' '), + values: [username], }; this.call_query( - query - ,(rows) => success_callback({ - password: rows[0].password - ,crypt_type: rows[0].password_storage - ,salt: rows[0].password_salt - }) - ,no_user_found_callback - ,error_callback + query, + rows => + success_callback({ + password: rows[0].password, + crypt_type: rows[0].password_storage, + salt: rows[0].password_salt, + }), + no_user_found_callback, + error_callback, ); } set_password_data_for_user( - username: string - ,new_password: string - ,new_crypt_method: string - ,salt: string - ,success_callback: () => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + username: string, + new_password: string, + new_crypt_method: string, + salt: string, + success_callback: () => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "set-user-password" - ,text: [ - "UPDATE users" - ,"SET" - ,"password = $1" - ,",password_storage = $2" - ,",password_salt = $3" - ,"WHERE email = $4" - ].join( " " ) - ,values: [ - new_password - ,new_crypt_method - ,salt - ,username - ] + name: 'set-user-password', + text: [ + 'UPDATE users', + 'SET', + 'password = $1', + ',password_storage = $2', + ',password_salt = $3', + 'WHERE email = $4', + ].join(' '), + values: [new_password, new_crypt_method, salt, username], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,no_user_found_callback - ,error_callback + query, + success_no_rows_callback_builder(success_callback), + no_user_found_callback, + error_callback, ); } - session_store( express_session ) - { - let pg_session = session( express_session ); + session_store(express_session) { + let pg_session = session(express_session); let full_session = new pg_session({ - pool: this.pool + pool: this.pool, }); return full_session; } is_token_allowed( - token: string - ,success_callback: () => void - ,no_token_found_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + token: string, + success_callback: () => void, + no_token_found_callback: () => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "is-token-allowed" - ,text: [ - "SELECT" - ,"id" - ,"FROM access_token" - ,"WHERE token = $1" - ].join( " " ) - ,values: [ token ] + name: 'is-token-allowed', + text: [ + 'SELECT', + 'id', + 'FROM access_token', + 'WHERE token = $1', + ].join(' '), + values: [token], }; this.call_query( - query - ,(rows) => success_callback() - ,no_token_found_callback - ,error_callback + query, + rows => success_callback(), + no_token_found_callback, + error_callback, ); } add_token( - username: string - ,token: string - ,name: string - ,notes: string - ,success_handler: () => void - ,no_user_found_callback: () => void - ,error_handler: ( err: Error ) => void - ): void - { + username: string, + token: string, + name: string, + notes: string, + success_handler: () => void, + no_user_found_callback: () => void, + error_handler: (err: Error) => void, + ): void { let user_id_query = { - name: "user-id-lookup" - ,text: [ - "SELECT" - ,"id" - ,"FROM users" - ,"WHERE email = $1 LIMIT 1" - ].join( " " ) - ,values: [ - username - ] + name: 'user-id-lookup', + text: [ + 'SELECT', + 'id', + 'FROM users', + 'WHERE email = $1 LIMIT 1', + ].join(' '), + values: [username], }; let query = { - name: "add-token" - ,text: [ - "INSERT INTO access_token (" - ,"user_id" - ,",token" - ,",name" - ,",notes" - ,") VALUES ($1, $2, $3, $4)" - ].join( " " ) - ,values: [ - null - ,token - ,name - ,notes - ] + name: 'add-token', + text: [ + 'INSERT INTO access_token (', + 'user_id', + ',token', + ',name', + ',notes', + ') VALUES ($1, $2, $3, $4)', + ].join(' '), + values: [null, token, name, notes], }; this.call_query( - user_id_query - ,( rows ) => { + user_id_query, + rows => { query.values[0] = rows[0].id; this.call_query( - query - ,success_no_rows_callback_builder( success_handler ) - ,null - ,error_handler + query, + success_no_rows_callback_builder(success_handler), + null, + error_handler, ); - } - ,no_user_found_callback - ,error_handler + }, + no_user_found_callback, + error_handler, ); - } get_members( - offset: number - ,per_page: number - ,success_callback: ( members: Array ) => void - ,error_callback: ( err: Error ) => void - ): boolean - { + offset: number, + per_page: number, + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): boolean { let placeholder = this.placeholder_generator(); let query_text = [ - "SELECT" - ,"member_id" - ,",rfid" - ,",first_name" - ,",last_name" - ,",phone" - ,",email" - ,",wildapricot_id" - ,",status" - ,"FROM members" - ,"ORDER BY last_name, first_name" + 'SELECT', + 'member_id', + ',rfid', + ',first_name', + ',last_name', + ',phone', + ',email', + ',wildapricot_id', + ',status', + 'FROM members', + 'ORDER BY last_name, first_name', ]; - let name = "get-member"; + let name = 'get-member'; let values = []; - if( per_page != null ) { - name += "-limit"; - query_text.push( "LIMIT " + placeholder() ); - values.push( per_page ); + if (per_page != null) { + name += '-limit'; + query_text.push('LIMIT ' + placeholder()); + values.push(per_page); } - if( offset != null ) { - name += "-offset"; - query_text.push( "OFFSET " + placeholder() ); - values.push( offset ); + if (offset != null) { + name += '-offset'; + query_text.push('OFFSET ' + placeholder()); + values.push(offset); } let query = { - name: name - ,text: query_text.join( " " ) - ,values: values + name: name, + text: query_text.join(' '), + values: values, }; - this.call_query( query - ,( rows ) => { - let results = rows.map( (row) => { + this.call_query( + query, + rows => { + let results = rows.map(row => { return { - member_id: row.member_id - ,rfid: row.rfid - ,firstName: row.first_name - ,lastName: row.last_name - ,phone: row.phone - ,email: row.email + member_id: row.member_id, + rfid: row.rfid, + firstName: row.first_name, + lastName: row.last_name, + phone: row.phone, + email: row.email, }; }); - success_callback( results ); - } - ,() => { - success_callback( [] ); - } - ,error_callback + success_callback(results); + }, + () => { + success_callback([]); + }, + error_callback, ); return true; } - end(): void - { + end(): void { this.pool.end(); } - private transaction( - transaction_callback: (client, done) => void - ,success_callback: () => void - ,error_callback: (err: Error) => void - ): void - { + transaction_callback: (client, done) => void, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { let abort = (client, done) => { - client.query( 'ROLLBACK', (err, res) => { + client.query('ROLLBACK', (err, res) => { done(); - if( err ) { + if (err) { throw err; } - error_callback( err ); + error_callback(err); }); }; let finish = (client, done) => { - client.query( 'COMMIT', (err, res) => { - if( err ) { - error_callback( err ); + client.query('COMMIT', (err, res) => { + if (err) { + error_callback(err); } done(); }); }; - this.pool.connect( (err, client, done) => { - client.query( 'BEGIN', (err, res) => { - if( err ) { - abort( client, done ); - } - else { + this.pool.connect((err, client, done) => { + client.query('BEGIN', (err, res) => { + if (err) { + abort(client, done); + } else { try { - transaction_callback( client, () => { - finish( client, () => { + transaction_callback(client, () => { + finish(client, () => { done(); success_callback(); }); }); - } - catch( err ) { - abort( client, done ); + } catch (err) { + abort(client, done); } } }); }); } - private placeholder_generator(): - () => string - { + private placeholder_generator(): () => string { let placeholder_num: number = 1; return () => { - let placeholder = "$" + placeholder_num; + let placeholder = '$' + placeholder_num; placeholder_num++; return placeholder; }; } private call_query( - query - ,success_callback: ( rows: Array ) => void - ,no_rows_callback: () => void - ,error_callback?: ( err: Error ) => void - ,client? - ): void - { + query, + success_callback: (rows: Array) => void, + no_rows_callback: () => void, + error_callback?: (err: Error) => void, + client?, + ): void { let main_callback = (client, done) => { - client.query( query, (err, res) => { + client.query(query, (err, res) => { done(); - if( err ) { - error_callback( err ); - } - else if(! res.rowCount ) { - if( no_rows_callback ) no_rows_callback(); - } - else { - success_callback( res.rows ); + if (err) { + error_callback(err); + } else if (!res.rowCount) { + if (no_rows_callback) no_rows_callback(); + } else { + success_callback(res.rows); } }); }; - if( client ) { - main_callback( client, () => {} ); - } - else { - this.pool.connect( (err, client, done) => { - if( err ) throw err; - main_callback( client, done ); + if (client) { + main_callback(client, () => {}); + } else { + this.pool.connect((err, client, done) => { + if (err) throw err; + main_callback(client, done); }); } } - private insert_address( - client - ,address: db_impl.USAddress - ,success_callback: (addr_id: number) => void - ,error_callback: ( err: Error ) => void - ): void - { + client, + address: db_impl.USAddress, + success_callback: (addr_id: number) => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "add-address" - ,text: [ - "INSERT INTO us_address (" - ,"address1" - ,",address2" - ,",city" - ,",state" - ,",zip" - ,") VALUES ($1, $2, $3, $4, $5) RETURNING id" - ].join( " " ) - ,values: [ - address.address1 - ,address.address2 - ,address.city - ,address.state - ,address.zip - ] + name: 'add-address', + text: [ + 'INSERT INTO us_address (', + 'address1', + ',address2', + ',city', + ',state', + ',zip', + ') VALUES ($1, $2, $3, $4, $5) RETURNING id', + ].join(' '), + values: [ + address.address1, + address.address2, + address.city, + address.state, + address.zip, + ], }; - let main_callback = (rows) => { - success_callback( rows[0].id ); + let main_callback = rows => { + success_callback(rows[0].id); }; - this.call_query( - query - ,main_callback - ,null - ,error_callback - ,client - ); + this.call_query(query, main_callback, null, error_callback, client); } private update_user_address( - client - ,member_id: string - ,addr_id: number - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void - ): void - { + client, + member_id: string, + addr_id: number, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, + ): void { let query = { - name: "update-user-address" - ,text: [ - "UPDATE members" - ,"SET address_id = $1" - ,"WHERE member_id = $2" - ].join( " " ) - ,values: [ - addr_id - ,member_id - ] + name: 'update-user-address', + text: [ + 'UPDATE members', + 'SET address_id = $1', + 'WHERE member_id = $2', + ].join(' '), + values: [addr_id, member_id], }; this.call_query( - query - ,success_no_rows_callback_builder( success_callback ) - ,no_rows_callback_builder( member_id, no_member_found_callback ) - ,error_callback - ,client + query, + success_no_rows_callback_builder(success_callback), + no_rows_callback_builder(member_id, no_member_found_callback), + error_callback, + client, ); } } diff --git a/src/db.ts b/src/db.ts index 45582a5..c274320 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,5 +1,4 @@ -export interface USAddress -{ +export interface USAddress { address1: string; address2?: string; city: string; @@ -7,21 +6,18 @@ export interface USAddress zip: string; } -export interface Question -{ +export interface Question { question: string; answer: string; } -enum ToolColor -{ - Green = "green", - Yellow = "yellow", - Red = "red", +enum ToolColor { + Green = 'green', + Yellow = 'yellow', + Red = 'red', } -export interface Tool -{ +export interface Tool { id: string; toolName: string; description: string; @@ -33,8 +29,7 @@ export interface Tool owner: Member; } -export interface SimpleMember -{ +export interface SimpleMember { rfid: string; firstName: string; lastName: string; @@ -42,8 +37,7 @@ export interface SimpleMember email: string; } -export interface Member -{ +export interface Member { member_id: string; rfid: string; firstName: string; @@ -52,8 +46,7 @@ export interface Member email: string; } -export interface RFIDLog -{ +export interface RFIDLog { memberID: string; rfid: string; firstName: string; @@ -62,170 +55,169 @@ export interface RFIDLog date: string; } -export interface DB -{ +export interface DB { add_member( - member: SimpleMember - ,success_callback: ( member_id ) => void - ,error_callback: ( err: Error ) => void + member: SimpleMember, + success_callback: (member_id) => void, + error_callback: (err: Error) => void, ): boolean; get_member( - member_id: string - ,success_callback: ( member: Member ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (member: Member) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; set_member_photo( - member_id: string - ,path: string - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + path: string, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; get_member_photo( - member_id: string - ,success_callback: ( path: string ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (path: string) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; put_member_address( - member_id: string - ,address: USAddress - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + address: USAddress, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; get_member_address( - member_id: string - ,success_callback: ( address: USAddress ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (address: USAddress) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; put_member_wild_apricot( - member_id: string - ,wild_apricot_id: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void + member_id: string, + wild_apricot_id: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, ): boolean; get_member_wild_apricot( - member_id: string - ,success_callback: ( wild_apricot_id: string ) => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (wild_apricot_id: string) => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, ): boolean; set_member_is_active( - member_id: string - ,is_active: boolean - ,success_callback: () => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + is_active: boolean, + success_callback: () => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; get_member_is_active( - member_id: string - ,success_callback: ( is_active: boolean ) => void - ,no_member_found_callback: ( err: Error ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (is_active: boolean) => void, + no_member_found_callback: (err: Error) => void, + error_callback: (err: Error) => void, ): boolean; set_member_rfid( - member_id: string - ,rfid: string - ,success_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void + member_id: string, + rfid: string, + success_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, ): boolean; get_member_rfid( - rfid: string - ,success_callback: () => void - ,inactive_member_callback: () => void - ,no_member_found_callback: () => void - ,error_callback: ( err: Error ) => void + rfid: string, + success_callback: () => void, + inactive_member_callback: () => void, + no_member_found_callback: () => void, + error_callback: (err: Error) => void, ): boolean; rfid_dump( - success_callback: ( dump: any ) => void - ,error_callback: ( err: Error ) => void + success_callback: (dump: any) => void, + error_callback: (err: Error) => void, ): boolean; log_rfid_entry( - rfid: string - ,is_active: boolean - ,success_callback: () => void - ,error_callback: ( err: Error ) => void + rfid: string, + is_active: boolean, + success_callback: () => void, + error_callback: (err: Error) => void, ): boolean; get_rfid_log( - offset: number - ,per_page: number - ,success_callback: ( logs: Array ) => void - ,error_callback: ( err: Error ) => void + offset: number, + per_page: number, + success_callback: (logs: Array) => void, + error_callback: (err: Error) => void, ): void; add_user( - username: string - ,password: string - ,salt: string - ,crypt_type: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void + username: string, + password: string, + salt: string, + crypt_type: string, + success_callback: () => void, + error_callback: (err: Error) => void, ): void; get_password_data_for_user( - username: string - ,success_callback: ( stored_data: { - password: string - ,crypt_type: string - ,salt: string - }) => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void + username: string, + success_callback: (stored_data: { + password: string; + crypt_type: string; + salt: string; + }) => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, ): void; set_password_data_for_user( - username: string - ,new_password: string - ,new_crypt_method: string - ,salt: string - ,success_callback: () => void - ,no_user_found_callback: () => void - ,error_callback: ( err: Error ) => void + username: string, + new_password: string, + new_crypt_method: string, + salt: string, + success_callback: () => void, + no_user_found_callback: () => void, + error_callback: (err: Error) => void, ): void; - session_store( express_session ); + session_store(express_session); is_token_allowed( - token: string - ,success_callback: () => void - ,no_token_found_callback: () => void - ,error_callback: ( err: Error ) => void + token: string, + success_callback: () => void, + no_token_found_callback: () => void, + error_callback: (err: Error) => void, ): void; add_token( - username: string - ,token: string - ,name: string - ,notes: string - ,success_handler: () => void - ,no_user_found_callback: () => void - ,error_handler: ( err: Error ) => void + username: string, + token: string, + name: string, + notes: string, + success_handler: () => void, + no_user_found_callback: () => void, + error_handler: (err: Error) => void, ): void; get_members( - offset: number - ,per_page: number - ,success_callback: ( members: Array ) => void - ,error_callback: ( err: Error ) => void + offset: number, + per_page: number, + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, ): boolean; end(): void; diff --git a/src/email_sender.ts b/src/email_sender.ts index 1d4acb5..466dd59 100644 --- a/src/email_sender.ts +++ b/src/email_sender.ts @@ -1,231 +1,216 @@ import * as google from 'googleapis'; import * as fs from 'fs'; import * as oauth from 'google-auth-library'; -import * as Handlebars from "./handlebars-preloader"; +import * as Handlebars from './handlebars-preloader'; import * as wa_api from './wild_apricot'; const EMAIL_TMPL_PATH = './emails'; let email_tmpls; - -export class Email -{ +export class Email { private auth: oauth.OAuth2Client; - constructor( args: { - auth: oauth.OAuth2Client - }) - { + constructor(args: {auth: oauth.OAuth2Client}) { this.auth = args.auth; } - public init( - callback: () => void - ): void - { - if(! email_tmpls) { - email_tmpls = new Handlebars.handlebars( EMAIL_TMPL_PATH ); - email_tmpls.load( callback ); - } - else { + public init(callback: () => void): void { + if (!email_tmpls) { + email_tmpls = new Handlebars.handlebars(EMAIL_TMPL_PATH); + email_tmpls.load(callback); + } else { callback(); } } - - public send_new_member_signup( args: { - to_name: string - ,to_email: string - ,from_name: string - ,from_email: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - }): void - { - if(! email_tmpls ) { - let err = new Error( "Need to call init() before sending email" ); - args.error_callback( err ); + public send_new_member_signup(args: { + to_name: string; + to_email: string; + from_name: string; + from_email: string; + success_callback: () => void; + error_callback: (err: Error) => void; + }): void { + if (!email_tmpls) { + let err = new Error('Need to call init() before sending email'); + args.error_callback(err); return; } const gmail = new google.gmail_v1.Gmail({ - auth: this.auth + auth: this.auth, }); - const message = email_tmpls.execute( 'member_signup', { - from_name: args.from_name - ,from_email: args.from_email - ,to_name: args.to_name - ,to_email: args.to_email - ,subject: "Welcome to the Bodgery" + const message = email_tmpls.execute('member_signup', { + from_name: args.from_name, + from_email: args.from_email, + to_name: args.to_name, + to_email: args.to_email, + subject: 'Welcome to the Bodgery', }); // TODO below should be wrapped into send() private method - const encoded_message = Buffer.from( message ) - .toString( 'base64' ) + const encoded_message = Buffer.from(message) + .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); gmail.users.messages.send( { - userId: 'me' - ,requestBody: { - raw: encoded_message - } - } - ,(err) => { - if( err ) { - args.error_callback( err ); - } - else { + userId: 'me', + requestBody: { + raw: encoded_message, + }, + }, + err => { + if (err) { + args.error_callback(err); + } else { args.success_callback(); } - } + }, ); } - public send_new_group_member_signup( args: { - to_name: string - ,to_email: string - ,from_name: string - ,from_email: string - ,member_first_name: string - ,photo_path: string - ,answers: Array - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - }): void - { - if(! email_tmpls ) { - let err = new Error( "Need to call init() before sending email" ); - args.error_callback( err ); + public send_new_group_member_signup(args: { + to_name: string; + to_email: string; + from_name: string; + from_email: string; + member_first_name: string; + photo_path: string; + answers: Array; + success_callback: () => void; + error_callback: (err: Error) => void; + }): void { + if (!email_tmpls) { + let err = new Error('Need to call init() before sending email'); + args.error_callback(err); return; } const gmail = new google.gmail_v1.Gmail({ - auth: this.auth + auth: this.auth, }); - const photo_base64 = this.encode_file_attachment( args.photo_path - ,(base64_photo) => { - const message = email_tmpls.execute( 'group_new_member', { - from_name: args.from_name - ,from_email: args.from_email - ,to_name: args.to_name - ,to_email: args.to_email - ,first_name: args.member_first_name - ,photo_base64: base64_photo - ,answer1: args.answers[0].answer - ,answer2: args.answers[1].answer - ,answer3: args.answers[2].answer - ,answer4: args.answers[3].answer - ,answer5: args.answers[4].answer - ,subject: "Welcome to our new member, " + args.member_first_name + const photo_base64 = this.encode_file_attachment( + args.photo_path, + base64_photo => { + const message = email_tmpls.execute('group_new_member', { + from_name: args.from_name, + from_email: args.from_email, + to_name: args.to_name, + to_email: args.to_email, + first_name: args.member_first_name, + photo_base64: base64_photo, + answer1: args.answers[0].answer, + answer2: args.answers[1].answer, + answer3: args.answers[2].answer, + answer4: args.answers[3].answer, + answer5: args.answers[4].answer, + subject: + 'Welcome to our new member, ' + args.member_first_name, }); // TODO below should be wrapped into send() private method - const encoded_message = Buffer.from( message ) - .toString( 'base64' ) + const encoded_message = Buffer.from(message) + .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); gmail.users.messages.send( { - userId: 'me' - ,requestBody: { - raw: encoded_message - } - } - ,(err) => { - if( err ) { - args.error_callback( err ); - } - else { + userId: 'me', + requestBody: { + raw: encoded_message, + }, + }, + err => { + if (err) { + args.error_callback(err); + } else { args.success_callback(); } - } + }, ); - } - ,(err) => args.error_callback( err ) + }, + err => args.error_callback(err), ); } - public send_reconciliation( args: { - to_name: string - ,to_email: string - ,from_name: string - ,from_email: string - ,active_in_local_not_wa: Array - ,active_in_wa_not_local: Array - ,total_active_members: number - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - }): void - { - if(! email_tmpls ) { - let err = new Error( "Need to call init() before sending email" ); - args.error_callback( err ); + public send_reconciliation(args: { + to_name: string; + to_email: string; + from_name: string; + from_email: string; + active_in_local_not_wa: Array; + active_in_wa_not_local: Array; + total_active_members: number; + success_callback: () => void; + error_callback: (err: Error) => void; + }): void { + if (!email_tmpls) { + let err = new Error('Need to call init() before sending email'); + args.error_callback(err); return; } const gmail = new google.gmail_v1.Gmail({ - auth: this.auth + auth: this.auth, }); const today = new Date(); - const message = email_tmpls.execute( 'reconciliation', { - from_name: args.from_name - ,from_email: args.from_email - ,to_name: args.to_name - ,to_email: args.to_email - ,subject: "Bodgery Reconciliation Report [" - + [ - today.getFullYear() - ,today.getMonth() + 1 - ,today.getDate() - ].join( "-" ) - ,total_wa: args.total_active_members - ,active_in_wa_not_local: args.active_in_wa_not_local - ,active_in_local_not_wa: args.active_in_local_not_wa + const message = email_tmpls.execute('reconciliation', { + from_name: args.from_name, + from_email: args.from_email, + to_name: args.to_name, + to_email: args.to_email, + subject: + 'Bodgery Reconciliation Report [' + + [ + today.getFullYear(), + today.getMonth() + 1, + today.getDate(), + ].join('-'), + total_wa: args.total_active_members, + active_in_wa_not_local: args.active_in_wa_not_local, + active_in_local_not_wa: args.active_in_local_not_wa, }); // TODO below should be wrapped into send() private method - const encoded_message = Buffer.from( message ) - .toString( 'base64' ) + const encoded_message = Buffer.from(message) + .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); gmail.users.messages.send( { - userId: 'me' - ,requestBody: { - raw: encoded_message - } - } - ,(err) => { - if( err ) { - args.error_callback( err ); - } - else { + userId: 'me', + requestBody: { + raw: encoded_message, + }, + }, + err => { + if (err) { + args.error_callback(err); + } else { args.success_callback(); } - } + }, ); } - private encode_file_attachment( - photo_path: string - ,success_callback: ( encoded_photo: string ) => void - ,error_callback: (err: Error) => void - ): void - { - fs.readFile( photo_path, (err, data) => { - if( err ) error_callback( err ); + photo_path: string, + success_callback: (encoded_photo: string) => void, + error_callback: (err: Error) => void, + ): void { + fs.readFile(photo_path, (err, data) => { + if (err) error_callback(err); else { - const encoded_photo = data.toString( 'base64' ); - success_callback( encoded_photo ); + const encoded_photo = data.toString('base64'); + success_callback(encoded_photo); } }); } diff --git a/src/handlebars-preloader.ts b/src/handlebars-preloader.ts index 1b276b8..37676ba 100644 --- a/src/handlebars-preloader.ts +++ b/src/handlebars-preloader.ts @@ -1,78 +1,74 @@ import * as Handlebars from 'handlebars'; import * as fs from 'fs'; - -export class handlebars -{ +export class handlebars { private path: string; private tmpl_by_name = {}; - constructor( - path: string - ) { + constructor(path: string) { this.path = path; } - - public load( - callback: () => void - ): void - { + public load(callback: () => void): void { // TODO A lot of redundancy in this. Clean up. let partials_path = this.path + '/partials'; - fs.readdir( partials_path, (err, files) => { - if( err ) throw err; + fs.readdir(partials_path, (err, files) => { + if (err) throw err; - let promises = files.map( (_) => { + let promises = files.map(_ => { let clean_name = _; - clean_name = clean_name.replace( "^" + partials_path, '' ); - clean_name = clean_name.replace( /.handlebars/, '' ); + clean_name = clean_name.replace('^' + partials_path, ''); + clean_name = clean_name.replace(/.handlebars/, ''); let file_path = partials_path + '/' + _; - return file_path.match( /\.handlebars$/ ) - ? new Promise( ( resolve, reject ) => { - fs.readFile( file_path, (err, data) => { - if( err ) reject( err ); - - let compiled_partial = Handlebars.compile( - data.toString() ); - Handlebars.registerPartial( clean_name, - compiled_partial ); - resolve(); - }); - }) - // Ignore non handlebars files - : new Promise( ( resolve, reject ) => resolve() ); + return file_path.match(/\.handlebars$/) + ? new Promise((resolve, reject) => { + fs.readFile(file_path, (err, data) => { + if (err) reject(err); + + let compiled_partial = Handlebars.compile( + data.toString(), + ); + Handlebars.registerPartial( + clean_name, + compiled_partial, + ); + resolve(); + }); + }) + : // Ignore non handlebars files + new Promise((resolve, reject) => resolve()); }); - Promise.all( promises ).then( (values) => { - fs.readdir( this.path, (err, files) => { - if( err ) throw err; + Promise.all(promises).then(values => { + fs.readdir(this.path, (err, files) => { + if (err) throw err; - let promises = files.map( (_) => { + let promises = files.map(_ => { let clean_name = _; - clean_name = clean_name.replace( "^" + this.path, '' ); - clean_name = clean_name.replace( /.handlebars/, '' ); - - let file_path = this.path + "/" + _; - - return file_path.match( /\.handlebars$/ ) - ? new Promise( ( resolve, reject ) => { - fs.readFile( file_path, (err, data) => { - if( err ) reject(err); - - let tmpl = Handlebars.compile( - data.toString() ); - this.tmpl_by_name[clean_name] = tmpl; - resolve(); - }); - }) - // Ignore non handlebars files - : new Promise( ( resolve, reject ) => resolve() ); + clean_name = clean_name.replace('^' + this.path, ''); + clean_name = clean_name.replace(/.handlebars/, ''); + + let file_path = this.path + '/' + _; + + return file_path.match(/\.handlebars$/) + ? new Promise((resolve, reject) => { + fs.readFile(file_path, (err, data) => { + if (err) reject(err); + + let tmpl = Handlebars.compile( + data.toString(), + ); + this.tmpl_by_name[clean_name] = tmpl; + resolve(); + }); + }) + : // Ignore non handlebars files + new Promise((resolve, reject) => resolve()); }); - Promise.all( promises ).then( (values) => { + Promise.all(promises).then(values => { callback(); }); }); @@ -80,18 +76,15 @@ export class handlebars }); } - public execute( - tmpl_name: string - ,params: any - ): string - { + public execute(tmpl_name: string, params: any): string { let tmpl = this.tmpl_by_name[tmpl_name]; - if(! tmpl) { - throw new Error( "No template found for " + tmpl_name - + " under " + this.path ); + if (!tmpl) { + throw new Error( + 'No template found for ' + tmpl_name + ' under ' + this.path, + ); } - let text = tmpl( params ); + let text = tmpl(params); return text; } } diff --git a/src/password.ts b/src/password.ts index 4f02bbc..86d2b5a 100644 --- a/src/password.ts +++ b/src/password.ts @@ -1,78 +1,62 @@ -import * as db from "./db"; -import * as argon from "./password/argon2"; -import * as bcrypt from "./password/bcrypt"; -import * as crypto from "crypto"; -import * as plaintext from "./password/plaintext"; -import * as scrypt from "./password/scrypt"; +import * as db from './db'; +import * as argon from './password/argon2'; +import * as bcrypt from './password/bcrypt'; +import * as crypto from 'crypto'; +import * as plaintext from './password/plaintext'; +import * as scrypt from './password/scrypt'; const SALT_SIZE_BYTES = 16; +export function string_match(str1: string, str2: string): boolean { + if (str1.length != str2.length) return false; -export function string_match( str1: string, str2: string ): boolean -{ - if( str1.length != str2.length ) return false; - - // Constant time string eq algorithm. Do not return until + // Constant time string eq algorithm. Do not return until // entire string is matched let str2_chars = str2.split(''); let is_match = true; - str1.split('').forEach( (val, i) => { - if( val != str2_chars[i] ) is_match = false; + str1.split('').forEach((val, i) => { + if (val != str2_chars[i]) is_match = false; }); return is_match; } -export function make_salt(): Buffer -{ - let rnd_buf = crypto.randomBytes( SALT_SIZE_BYTES ); +export function make_salt(): Buffer { + let rnd_buf = crypto.randomBytes(SALT_SIZE_BYTES); return rnd_buf; } -export interface Crypter -{ - crypt( - password: string - ,salt: Buffer - ,callback: (string) => void - ): void; +export interface Crypter { + crypt(password: string, salt: Buffer, callback: (string) => void): void; isMatch( - plaintext: string - ,crypted: string - ,salt_hex: string - ,callback: (boolean) => void + plaintext: string, + crypted: string, + salt_hex: string, + callback: (boolean) => void, ): void; } -export class Checker -{ +export class Checker { private db: db.DB; private preferred_method: Crypter; private preferred_method_str: string; - - constructor( - preferred_method: string - ,db: db.DB - ) - { + constructor(preferred_method: string, db: db.DB) { this.db = db; - let preferred = this._parseCryptType( preferred_method ); + let preferred = this._parseCryptType(preferred_method); this.preferred_method_str = preferred_method; this.preferred_method = preferred; } - - public isMatch( args: { - username: string - ,passwd: string - ,is_match_callback: () => void - ,is_not_match_callback: () => void - }): void - { + public isMatch(args: { + username: string; + passwd: string; + is_match_callback: () => void; + is_not_match_callback: () => void; + }): void { let username = args.username; let passwd = args.passwd; let is_match_callback = args.is_match_callback; @@ -80,124 +64,121 @@ export class Checker let stored_crypt_type: string; let match_success_callback = (is_matched: boolean) => { - if( is_matched - && (stored_crypt_type == this.preferred_method_str)) { + if (is_matched && stored_crypt_type == this.preferred_method_str) { is_match_callback(); - } - else if( is_matched ) { + } else if (is_matched) { // Matched fine, but we aren't using the preferred method of // password encryption, so reencrypt let new_salt = make_salt(); - this.preferred_method.crypt( passwd, new_salt - ,(new_crypt_passwd) => { + this.preferred_method.crypt( + passwd, + new_salt, + new_crypt_passwd => { this.db.set_password_data_for_user( - username - ,new_crypt_passwd - ,this.preferred_method_str - ,new_salt.toString( 'hex' ) - ,is_match_callback - ,() => { + username, + new_crypt_passwd, + this.preferred_method_str, + new_salt.toString('hex'), + is_match_callback, + () => { // How did we get to a 'no user found' error - // when we already checked it? DB interface + // when we already checked it? DB interface // would likely be buggy if we get here. is_not_match_callback(); - } - ,( err: Error ) => { + }, + (err: Error) => { throw err; - } + }, ); - } + }, ); - } - else { + } else { is_not_match_callback(); } }; - let db_success_callback = (stored_data) => { + let db_success_callback = stored_data => { let stored_password = stored_data.password; stored_crypt_type = stored_data.crypt_type; let stored_salt = stored_data.salt; - let crypter = this._parseCryptType( stored_crypt_type ); - - crypter.isMatch( passwd, - stored_password, stored_salt, match_success_callback ); + let crypter = this._parseCryptType(stored_crypt_type); + + crypter.isMatch( + passwd, + stored_password, + stored_salt, + match_success_callback, + ); }; this.db.get_password_data_for_user( - username - ,db_success_callback - ,() => { + username, + db_success_callback, + () => { is_not_match_callback(); - } - ,( err: Error ) => { + }, + (err: Error) => { throw err; - } + }, ); } public addNewUser( - user: string - ,pass: string - ,callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + user: string, + pass: string, + callback: () => void, + error_callback: (err: Error) => void, + ): void { let salt = make_salt(); - this.preferred_method.crypt( - pass - ,salt - ,(crypted_pass) => { - this.db.add_user( - user - ,crypted_pass - ,salt.toString( 'hex' ) - ,this.preferred_method_str - ,callback - ,error_callback - ); - } - ); + this.preferred_method.crypt(pass, salt, crypted_pass => { + this.db.add_user( + user, + crypted_pass, + salt.toString('hex'), + this.preferred_method_str, + callback, + error_callback, + ); + }); } - private _parseCryptType( crypt_string: string ): Crypter - { - let parts = crypt_string.split( '_' ); - if( parts.length < 1 ) { - throw new Error( "Error parsing crypt string ('" - + crypt_string + "')" ); + private _parseCryptType(crypt_string: string): Crypter { + let parts = crypt_string.split('_'); + if (parts.length < 1) { + throw new Error( + "Error parsing crypt string ('" + crypt_string + "')", + ); } let crypt_type = parts[0]; let crypt_args = parts.slice(1); - let crypter = this._fetchCrypterByName( crypt_type, crypt_args ); + let crypter = this._fetchCrypterByName(crypt_type, crypt_args); return crypter; } private _fetchCrypterByName( - crypt_type: string - ,crypt_args: Array - ): Crypter - { + crypt_type: string, + crypt_args: Array, + ): Crypter { let crypter: Crypter; - switch( crypt_type ) { + switch (crypt_type) { case 'bcrypt': - crypter = new bcrypt.BCrypt( crypt_args ); + crypter = new bcrypt.BCrypt(crypt_args); break; case 'scrypt': - crypter = new scrypt.SCrypt( crypt_args ); + crypter = new scrypt.SCrypt(crypt_args); break; case 'argon2': - crypter = new argon.Argon2( crypt_args ); + crypter = new argon.Argon2(crypt_args); break; case 'terribadplaintext': - crypter = new plaintext.Plaintext( crypt_args ); + crypter = new plaintext.Plaintext(crypt_args); break; default: - throw new Error( "Unknown crypter type: " + crypt_type ); + throw new Error('Unknown crypter type: ' + crypt_type); } return crypter; diff --git a/src/password/argon2.ts b/src/password/argon2.ts index 5844908..75ac739 100644 --- a/src/password/argon2.ts +++ b/src/password/argon2.ts @@ -1,46 +1,41 @@ -import * as argon from "argon2"; +import * as argon from 'argon2'; - -export class Argon2 -{ +export class Argon2 { private hash_len: number; private time_cost: number; private mem_cost: number; private parallelism: number; private argon_type = argon.argon2i; - - constructor( args: Array ) - { - this.hash_len = parseInt( args[0] ); - this.time_cost = parseInt( args[1] ); - this.mem_cost = parseInt( args[2] ); - this.parallelism = parseInt( args[3] ); + constructor(args: Array) { + this.hash_len = parseInt(args[0]); + this.time_cost = parseInt(args[1]); + this.mem_cost = parseInt(args[2]); + this.parallelism = parseInt(args[3]); } - crypt( - password: string - ,salt: Buffer = Buffer.from( '' ) - ,callback: (string) => void - ): void - { - argon.hash( password, { - hashLength: this.hash_len - ,timeCost: this.time_cost - ,memoryCost: this.mem_cost - ,parallelism: this.parallelism - ,type: this.argon_type - }).then( callback ); + password: string, + salt: Buffer = Buffer.from(''), + callback: (string) => void, + ): void { + argon + .hash(password, { + hashLength: this.hash_len, + timeCost: this.time_cost, + memoryCost: this.mem_cost, + parallelism: this.parallelism, + type: this.argon_type, + }) + .then(callback); } isMatch( - plaintext: string - ,crypted: string - ,salt_hex: string = "" - ,callback: (boolean) => void - ): void - { - argon.verify( crypted, plaintext ).then( callback ); + plaintext: string, + crypted: string, + salt_hex: string = '', + callback: (boolean) => void, + ): void { + argon.verify(crypted, plaintext).then(callback); } } diff --git a/src/password/bcrypt.ts b/src/password/bcrypt.ts index 3d3d93d..cd3ca47 100644 --- a/src/password/bcrypt.ts +++ b/src/password/bcrypt.ts @@ -1,35 +1,26 @@ -import * as bcrypt from "bcrypt"; +import * as bcrypt from 'bcrypt'; - -export class BCrypt -{ +export class BCrypt { private rounds: number; - - constructor( args: Array ) - { - this.rounds = parseInt( args[0] ); + constructor(args: Array) { + this.rounds = parseInt(args[0]); } - crypt( - password: string - ,salt: Buffer = Buffer.from( '' ) - ,callback: (string) => void - ): void - { - bcrypt.hash( password, this.rounds, - (err, hash) => callback( hash ) ); + password: string, + salt: Buffer = Buffer.from(''), + callback: (string) => void, + ): void { + bcrypt.hash(password, this.rounds, (err, hash) => callback(hash)); } isMatch( - plaintext: string - ,crypted: string - ,salt_hex: string = "" - ,callback: (boolean) => void - ): void - { - bcrypt.compare( plaintext, crypted, - (err, res) => callback(res) ); + plaintext: string, + crypted: string, + salt_hex: string = '', + callback: (boolean) => void, + ): void { + bcrypt.compare(plaintext, crypted, (err, res) => callback(res)); } } diff --git a/src/password/plaintext.ts b/src/password/plaintext.ts index 61de81c..367bb48 100644 --- a/src/password/plaintext.ts +++ b/src/password/plaintext.ts @@ -1,31 +1,24 @@ -import * as crypto from "crypto"; -import * as password from "../password"; - - -export class Plaintext -{ - constructor( args: Array ) - { - } +import * as crypto from 'crypto'; +import * as password from '../password'; +export class Plaintext { + constructor(args: Array) {} crypt( - key: string - ,salt: Buffer = password.make_salt() - ,callback: (string) => void - ): void - { - callback( key ); + key: string, + salt: Buffer = password.make_salt(), + callback: (string) => void, + ): void { + callback(key); } isMatch( - plaintext: string - ,crypted: string - ,salt_hex: string - ,callback: (boolean) => void - ): void - { - let val = password.string_match( plaintext, crypted ); - callback( val ); + plaintext: string, + crypted: string, + salt_hex: string, + callback: (boolean) => void, + ): void { + let val = password.string_match(plaintext, crypted); + callback(val); } } diff --git a/src/password/scrypt.ts b/src/password/scrypt.ts index b0793b6..1331a2a 100644 --- a/src/password/scrypt.ts +++ b/src/password/scrypt.ts @@ -1,56 +1,54 @@ -import * as crypto from "crypto"; -import * as password from "../password"; - +import * as crypto from 'crypto'; +import * as password from '../password'; const KEYLEN = 64; - -export class SCrypt -{ +export class SCrypt { private cost: number; private block_size: number; private parallelization: number; - - constructor( args: Array ) - { - this.cost = parseInt( args[0] ); - this.block_size = parseInt( args[1] ); - this.parallelization = parseInt( args[2] ); + constructor(args: Array) { + this.cost = parseInt(args[0]); + this.block_size = parseInt(args[1]); + this.parallelization = parseInt(args[2]); } - crypt( - key: string - ,salt: Buffer = password.make_salt() - ,callback: (string) => void - ): void - { - let salt_hex = salt.toString( 'hex' ); - let result = crypto.scrypt( key, salt_hex, KEYLEN, { - // Typescript type mapping does not have the options - // mapped for 'cost', 'blockSize', or 'parallelization'. - // Boo this API! - N: this.cost - ,r: this.block_size - ,p: this.parallelization - }, (err, res) => { - let str = res.toString( 'hex' ); - callback( str ); - }); + key: string, + salt: Buffer = password.make_salt(), + callback: (string) => void, + ): void { + let salt_hex = salt.toString('hex'); + let result = crypto.scrypt( + key, + salt_hex, + KEYLEN, + { + // Typescript type mapping does not have the options + // mapped for 'cost', 'blockSize', or 'parallelization'. + // Boo this API! + N: this.cost, + r: this.block_size, + p: this.parallelization, + }, + (err, res) => { + let str = res.toString('hex'); + callback(str); + }, + ); } isMatch( - plaintext: string - ,crypted: string - ,salt_hex: string - ,callback: (boolean) => void - ): void - { - let salt_buf = Buffer.from( salt_hex, 'hex' ); - this.crypt( plaintext, salt_buf, (check_crypted) => { - let val = password.string_match( check_crypted, crypted ); - callback( val ); + plaintext: string, + crypted: string, + salt_hex: string, + callback: (boolean) => void, + ): void { + let salt_buf = Buffer.from(salt_hex, 'hex'); + this.crypt(plaintext, salt_buf, check_crypted => { + let val = password.string_match(check_crypted, crypted); + callback(val); }); } } diff --git a/src/request_funcs.ts b/src/request_funcs.ts index 93cc710..bb83e08 100644 --- a/src/request_funcs.ts +++ b/src/request_funcs.ts @@ -1,519 +1,457 @@ -import * as db_access_token from "./typeorm/entities/access_token"; -import * as db_user from "./typeorm/entities/users"; -import * as c from "./context"; -import * as email_sender from "./email_sender"; -import * as Tokens from "csrf"; -import * as db_impl from "./db"; -import * as fs from "fs"; +import * as db_access_token from './typeorm/entities/access_token'; +import * as db_user from './typeorm/entities/users'; +import * as c from './context'; +import * as email_sender from './email_sender'; +import * as Tokens from 'csrf'; +import * as db_impl from './db'; +import * as fs from 'fs'; import * as google from 'googleapis'; import * as google_auth from 'google-auth-library'; -import * as shortid from "shortid"; -import * as sprintf from "sprintf-js"; -import * as util from "./util"; -import * as valid from "./validation"; -import * as wa_api from "./wild_apricot"; +import * as shortid from 'shortid'; +import * as sprintf from 'sprintf-js'; +import * as util from './util'; +import * as valid from './validation'; +import * as wa_api from './wild_apricot'; - -let db : db_impl.DB; +let db: db_impl.DB; let typeorm_connection; -export function set_db ( - new_db: db_impl.DB - ,new_typeorm_connection -) -{ +export function set_db(new_db: db_impl.DB, new_typeorm_connection) { db = new_db; typeorm_connection = new_typeorm_connection; } -function get_generic_db_error( logger, res ) -{ - return ( err: Error ) => { - logger.error( "Error writing to database: " + err.toString() ); - res.sendStatus( 500 ).end(); +function get_generic_db_error(logger, res) { + return (err: Error) => { + logger.error('Error writing to database: ' + err.toString()); + res.sendStatus(500).end(); }; } -function get_member_id_not_found_error( logger, res, member_id ) -{ +function get_member_id_not_found_error(logger, res, member_id) { return () => { - logger.info( "No member found for RFID " + member_id ); - res.sendStatus( 404 ).end(); + logger.info('No member found for RFID ' + member_id); + res.sendStatus(404).end(); }; } -function handle_generic_validation_error( logger, res, err ): void -{ - logger.error( "Errors: " + err.toString() ); - res - .status( 400 ) - .json({ - error: err.toString() - }); +function handle_generic_validation_error(logger, res, err): void { + logger.error('Errors: ' + err.toString()); + res.status(400).json({ + error: err.toString(), + }); } export function fetch_google_auth( - conf - ,scopes: Array - ,callback: ( client ) => void -): void -{ - fs.readFile( conf.google_credentials_file, (err, data) => { - if(err) throw err; - let keys = JSON.parse( data.toString() ); + conf, + scopes: Array, + callback: (client) => void, +): void { + fs.readFile(conf.google_credentials_file, (err, data) => { + if (err) throw err; + let keys = JSON.parse(data.toString()); let auth = new google_auth.OAuth2Client( - keys.installed.client_id - ,keys.installed.client_secret - ,keys.installed.redirect_uris[0] + keys.installed.client_id, + keys.installed.client_secret, + keys.installed.redirect_uris[0], ); auth.setCredentials({ - access_token: conf.google_access_token - ,refresh_token: conf.google_refresh_token - ,expiry_date: conf.google_expires_date + access_token: conf.google_access_token, + refresh_token: conf.google_refresh_token, + expiry_date: conf.google_expires_date, }); - callback( auth ); + callback(auth); }); } -export function fetch_google_email_scopes(): Array -{ +export function fetch_google_email_scopes(): Array { return [ - 'https://mail.google.com/' - ,'https://www.googleapis.com/auth/gmail.modify' - ,'https://www.googleapis.com/auth/gmail.compose' - ,'https://www.googleapis.com/auth/gmail.send' + 'https://mail.google.com/', + 'https://www.googleapis.com/auth/gmail.modify', + 'https://www.googleapis.com/auth/gmail.compose', + 'https://www.googleapis.com/auth/gmail.send', ]; } -function fetch_google_group_scopes(): Array -{ +function fetch_google_group_scopes(): Array { return [ - 'https://www.googleapis.com/auth/admin.directory.group' - ,'https://www.googleapis.com/auth/admin.directory.group.member', + 'https://www.googleapis.com/auth/admin.directory.group', + 'https://www.googleapis.com/auth/admin.directory.group.member', ]; } - -export function get_versions ( req, res ) -{ - res - .status(200) - .json([ '/v1' ]); +export function get_versions(req, res) { + res.status(200).json(['/v1']); } -export function put_member( req, res ) -{ +export function put_member(req, res) { let logger = req.ctx.logger; let body = req.body; try { - valid.validate( body, [ - valid.isInteger( 'rfid' ) - ,valid.isName( 'firstName' ) - ,valid.isName( 'lastName' ) - ,valid.isUSPhone( 'phone' ) - ,valid.isPublicEmail( 'email' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(body, [ + valid.isInteger('rfid'), + valid.isName('firstName'), + valid.isName('lastName'), + valid.isUSPhone('phone'), + valid.isPublicEmail('email'), + ]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - db.add_member( body - ,( member_id ) => { - logger.info( "Member added successfully" ); - res - .status( 201 ) - .send({ id: member_id }) - .end(); - } - ,get_generic_db_error( logger, res ) + db.add_member( + body, + member_id => { + logger.info('Member added successfully'); + res.status(201).send({id: member_id}).end(); + }, + get_generic_db_error(logger, res), ); } -export function get_member( req, res ) -{ +export function get_member(req, res) { let logger = req.req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.get_member( member_id - ,( member: db_impl.SimpleMember ) => { - logger.info( "Fetched member" ); - res - .status( 200 ) - .send( member ) - .end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + db.get_member( + member_id, + (member: db_impl.SimpleMember) => { + logger.info('Fetched member'); + res.status(200).send(member).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function put_member_address( req, res ) -{ +export function put_member_address(req, res) { let logger = req.ctx.logger; let body = req.body; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - valid.validate( body, [ - valid.isUSAddress() - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + valid.validate(body, [valid.isUSAddress()]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.put_member_address( member_id, body - ,() => { - logger.info( "Address set on member successfully" ); - res.sendStatus( 204 ).end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + db.put_member_address( + member_id, + body, + () => { + logger.info('Address set on member successfully'); + res.sendStatus(204).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function get_member_address( req, res ) -{ +export function get_member_address(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.get_member_address( member_id - ,( address: db_impl.USAddress ) => { - logger.info( "Fetched member address" ); - res - .status( 200 ) - .send( address ) - .end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + db.get_member_address( + member_id, + (address: db_impl.USAddress) => { + logger.info('Fetched member address'); + res.status(200).send(address).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function put_member_is_active( req, res ) -{ +export function put_member_is_active(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - valid.validate( req.body, [ - valid.isBoolean( 'is_active' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + valid.validate(req.body, [valid.isBoolean('is_active')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - let member_id = req.params.member_id; let status = req.body.is_active; - logger.info( "Setting member status to " - + status + " in Wild Apricot: " + member_id ); + logger.info( + 'Setting member status to ' + status + ' in Wild Apricot: ' + member_id, + ); let wa_active_call = status ? req.ctx.wa.set_member_active : req.ctx.wa.set_member_inactive; - db.get_member_wild_apricot( member_id - ,( wa_id ) => { + db.get_member_wild_apricot( + member_id, + wa_id => { let success_callback = () => { - logger.info( "Setting member status to " - + status + " in database: " + member_id ); - db.set_member_is_active( member_id, status - ,() => { - logger.info( "Member status now " - + status + ": " + member_id ); - res.sendStatus( 200 ); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + logger.info( + 'Setting member status to ' + + status + + ' in database: ' + + member_id, + ); + db.set_member_is_active( + member_id, + status, + () => { + logger.info( + 'Member status now ' + status + ': ' + member_id, + ); + res.sendStatus(200); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); }; - let error_callback = ( err: Error ) => { - logger.error( "Error calling Wild Apricot to set active: " - + err.toString() ); - res.sendStatus( 500 ).end(); + let error_callback = (err: Error) => { + logger.error( + 'Error calling Wild Apricot to set active: ' + + err.toString(), + ); + res.sendStatus(500).end(); }; - if( status ) { + if (status) { req.ctx.wa.set_member_active( - wa_id - ,success_callback - ,error_callback + wa_id, + success_callback, + error_callback, ); - } - else { + } else { req.ctx.wa.set_member_inactive( - wa_id - ,success_callback - ,error_callback + wa_id, + success_callback, + error_callback, ); } - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function get_member_is_active( req, res ) -{ +export function get_member_is_active(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.get_member_is_active( member_id - ,(is_active: boolean) => { - logger.info( "Set is active: " + is_active ); - res - .status( 200 ) - .send( is_active ) - .end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + db.get_member_is_active( + member_id, + (is_active: boolean) => { + logger.info('Set is active: ' + is_active); + res.status(200).send(is_active).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function put_member_rfid( req, res ) -{ +export function put_member_rfid(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - valid.validate( req.body, [ - valid.isInteger( 'rfid' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + valid.validate(req.body, [valid.isInteger('rfid')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - let member_id = req.params.member_id; let rfid = req.body.rfid; - db.set_member_rfid( member_id, rfid - ,() => { + db.set_member_rfid( + member_id, + rfid, + () => { // Don't put RFID in log - logger.info( "Set RFID on member " + member_id ); - res.sendStatus( 200 ).end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + logger.info('Set RFID on member ' + member_id); + res.sendStatus(200).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function get_member_rfid( req, res ) -{ +export function get_member_rfid(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isInteger( 'rfid' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isInteger('rfid')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let rfid = req.params.rfid; - db.get_member_rfid( rfid - ,() => { + db.get_member_rfid( + rfid, + () => { // Don't put RFID tag in log - logger.info( "RFID check OK" ); - res.sendStatus( 200 ).end(); - } - ,() => { - logger.info( "RFID is inactive for RFID check" ); - res.sendStatus( 403 ).end(); - } - ,() => { - logger.info( "RFID is not found for check" ); - res.sendStatus( 404 ).end(); - } - ,get_generic_db_error( logger, res ) + logger.info('RFID check OK'); + res.sendStatus(200).end(); + }, + () => { + logger.info('RFID is inactive for RFID check'); + res.sendStatus(403).end(); + }, + () => { + logger.info('RFID is not found for check'); + res.sendStatus(404).end(); + }, + get_generic_db_error(logger, res), ); } -export function get_rfid_dump( req, res ) -{ +export function get_rfid_dump(req, res) { let logger = req.ctx.logger; - db.rfid_dump( - (dump) => { - res - .status(200) - .json( dump ) - .end(); - } - ,get_generic_db_error( logger, res ) - ); + db.rfid_dump(dump => { + res.status(200).json(dump).end(); + }, get_generic_db_error(logger, res)); } -export function post_log_rfid( req, res ) -{ +export function post_log_rfid(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isInteger( 'rfid' ) - ,valid.isBoolean( 'is_allowed' ) + valid.validate(req.params, [ + valid.isInteger('rfid'), + valid.isBoolean('is_allowed'), ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let rfid = req.params.rfid; - let is_allowed = (req.params.is_allowed === 'true'); - - db.log_rfid_entry( rfid, is_allowed - ,() => { - logger.info( "RFID logged" ); - res.sendStatus( 200 ).end(); - } - ,get_generic_db_error( logger, res ) + let is_allowed = req.params.is_allowed === 'true'; + + db.log_rfid_entry( + rfid, + is_allowed, + () => { + logger.info('RFID logged'); + res.sendStatus(200).end(); + }, + get_generic_db_error(logger, res), ); } -export function put_member_wildapricot( req, res ) -{ +export function put_member_wildapricot(req, res) { let logger = req.ctx.logger; let body = req.body; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - valid.validate( body, [ - valid.isInteger( 'wild_apricot_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + valid.validate(body, [valid.isInteger('wild_apricot_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; let wild_apricot_id = body.wild_apricot_id; - db.put_member_wild_apricot( member_id, wild_apricot_id - ,() => { - logger.info( "Wild Apricot ID set on member successfully" ); - res.sendStatus( 204 ).end(); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + db.put_member_wild_apricot( + member_id, + wild_apricot_id, + () => { + logger.info('Wild Apricot ID set on member successfully'); + res.sendStatus(204).end(); + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function put_member_google_group( req, res ) -{ +export function put_member_google_group(req, res) { let logger = req.ctx.logger; let body = req.body; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.get_member( member_id - ,( member_data ) => { + db.get_member( + member_id, + member_data => { const email = member_data.email; fetch_google_auth( - req.ctx.conf - ,fetch_google_group_scopes() - ,( auth ) => { + req.ctx.conf, + fetch_google_group_scopes(), + auth => { const groups = new google.admin_directory_v1.Admin({ - auth: auth + auth: auth, }); - let promises = req.ctx.conf['google_groups_signup_list'].map( - (_) => { - return groups.members.insert({ - groupKey: _ - ,requestBody: { - email: email - } - }); - } - ); + let promises = req.ctx.conf[ + 'google_groups_signup_list' + ].map(_ => { + return groups.members.insert({ + groupKey: _, + requestBody: { + email: email, + }, + }); + }); - Promise - .all( promises ) - .then( () => { - logger.info( "Signed up for Google Groups" ); - res.sendStatus( 200 ).end(); + Promise.all(promises) + .then(() => { + logger.info('Signed up for Google Groups'); + res.sendStatus(200).end(); }) - .catch( (err) => { - logger.error( "Error signing up for Google Groups:" - + " " + err ); - res.sendStatus( 500 ).end(); + .catch(err => { + logger.error( + 'Error signing up for Google Groups:' + + ' ' + + err, + ); + res.sendStatus(500).end(); }); - } + }, ); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function login_user( req, res ) -{ +export function login_user(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.body, [ - valid.isPublicEmail( 'username' ) + valid.validate(req.body, [ + valid.isPublicEmail('username'), // Password field is allowed to be anything ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } @@ -521,167 +459,161 @@ export function login_user( req, res ) let password = req.body.password; let is_match_callback = () => { - logger.info( "User " + username + " logged in successfully" ); + logger.info('User ' + username + ' logged in successfully'); req.session.username = username; req.session.is_logged_in = true; - let render = tmpl_view( "login", { - user: username - }, [], 200 ); - render( req, res ); + let render = tmpl_view( + 'login', + { + user: username, + }, + [], + 200, + ); + render(req, res); }; let is_not_match_callback = () => { - logger.info( "User " + username + " failed to login" ); + logger.info('User ' + username + ' failed to login'); - let render = tmpl_view( "home", {}, [ - "Invalid username or password" - ], 403); - render( req, res ); + let render = tmpl_view( + 'home', + {}, + ['Invalid username or password'], + 403, + ); + render(req, res); }; let checker = req.ctx.password_checker; checker.isMatch({ - username: username - ,passwd: password - ,is_match_callback: is_match_callback - ,is_not_match_callback: is_not_match_callback + username: username, + passwd: password, + is_match_callback: is_match_callback, + is_not_match_callback: is_not_match_callback, }); } -export function logout_user( req, res ) -{ +export function logout_user(req, res) { let logger = req.ctx.logger; let username = req.session.username; let is_logged_in = req.session.is_logged_in; - if( is_logged_in ) { - logger.info( "Username " + username + " is logging out" ); - req.session.destroy( () => { - res - .status( 200 ) - .render( "home" ); + if (is_logged_in) { + logger.info('Username ' + username + ' is logging out'); + req.session.destroy(() => { + res.status(200).render('home'); + }); + } else { + logger.info('Asked for logout, but is not logged in'); + res.status(403).render('home', { + errors: ["Not logged in, so you can't log out"], }); - } - else { - logger.info( "Asked for logout, but is not logged in" ); - res - .status( 403 ) - .render( "home", { - errors: [ - "Not logged in, so you can't log out" - ] - }); } } -export function rfid_log( req, res ) -{ +export function rfid_log(req, res) { let logger = req.ctx.logger; let query = req.query; - if(! query['offset'] ) query['offset'] = 0; - if(! query['per_page'] ) query['per_page'] = 20; + if (!query['offset']) query['offset'] = 0; + if (!query['per_page']) query['per_page'] = 20; try { - valid.validate( query, [ - valid.isInteger( 'offset' ) - ,valid.isInteger( 'per_page' ) + valid.validate(query, [ + valid.isInteger('offset'), + valid.isInteger('per_page'), ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - let offset: number = parseInt( query['offset'] ); - let per_page: number = parseInt( query['per_page'] ); + let offset: number = parseInt(query['offset']); + let per_page: number = parseInt(query['per_page']); - db.get_rfid_log( offset, per_page - ,( logs ) => { - logger.info( "Fetched " + logs.length - + " logs starting at " + offset ); + db.get_rfid_log( + offset, + per_page, + logs => { + logger.info( + 'Fetched ' + logs.length + ' logs starting at ' + offset, + ); let prev_offset: number = offset - per_page; let render_args = { - next_offset: offset + per_page - ,prev_offset: prev_offset + next_offset: offset + per_page, + prev_offset: prev_offset, // TODO detect if there are any left and set next as needed - ,next: true - ,prev: (prev_offset >= 0) - ,per_page: per_page - ,logs: logs.map( (_) => { + next: true, + prev: prev_offset >= 0, + per_page: per_page, + logs: logs.map(_ => { let name = _.firstName - ? _.firstName + " " + _.lastName - : ""; + ? _.firstName + ' ' + _.lastName + : ''; let log = { - rfid: _.rfid - ,member_uuid: { uuid: _.memberID } - ,name: name - ,is_allowed: _.isAllowed - ,date: _.date + rfid: _.rfid, + member_uuid: {uuid: _.memberID}, + name: name, + is_allowed: _.isAllowed, + date: _.date, }; return log; - }) + }), }; - let render = tmpl_view( "entry-log" - ,render_args - ,[] - ,200 - ); - render( req, res ); - } - ,get_generic_db_error( logger, res ) + let render = tmpl_view('entry-log', render_args, [], 200); + render(req, res); + }, + get_generic_db_error(logger, res), ); } -function render_tokens( req, res ) -{ +function render_tokens(req, res) { let username = req.session.username; let db_manager = typeorm_connection.manager; let logger = req.ctx.logger; db_manager - .getRepository( db_user.users ) + .getRepository(db_user.users) .findOne({ - email: username + email: username, }) - .then( (db_user) => { - return db_manager - .getRepository( db_access_token.access_token ) - .find({ - user: db_user - }); + .then(db_user => { + return db_manager.getRepository(db_access_token.access_token).find({ + user: db_user, + }); }) - .then( (tokens) => { - let render = tmpl_view( "tokens", { - tokens: tokens - ,suggested_token_value: util.make_secure_token() - }, [], 200 ); - render( req, res ); + .then(tokens => { + let render = tmpl_view( + 'tokens', + { + tokens: tokens, + suggested_token_value: util.make_secure_token(), + }, + [], + 200, + ); + render(req, res); }) - .catch( get_generic_db_error( logger, res ) ); + .catch(get_generic_db_error(logger, res)); } -export function tokens( req, res ) -{ +export function tokens(req, res) { let logger = req.ctx.logger; - logger.info( "Showing tokens view" ); - render_tokens( req, res ); + logger.info('Showing tokens view'); + render_tokens(req, res); } -export function add_token( req, res ) -{ +export function add_token(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.body, [ - valid.isWords( 'name' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.body, [valid.isWords('name')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let token = req.body.token; @@ -689,300 +621,289 @@ export function add_token( req, res ) let notes = req.body.notes; let user = req.session.username; - logger.info( "Adding token" ); + logger.info('Adding token'); let db_manager = typeorm_connection.manager; db_manager - .getRepository( db_user.users ) + .getRepository(db_user.users) .findOne({ - email: user + email: user, }) - .then( (db_user) => { + .then(db_user => { let db_token = new db_access_token.access_token(); db_token.user = db_user; db_token.token = token; db_token.name = name; db_token.notes = notes; - return db_manager.save( db_token ); + return db_manager.save(db_token); }) - .then( () => { - logger.info( "New API token added for user: " + user ); - render_tokens( req, res ); + .then(() => { + logger.info('New API token added for user: ' + user); + render_tokens(req, res); }) - .catch( get_generic_db_error( logger, res ) ); + .catch(get_generic_db_error(logger, res)); } -export function delete_token( req, res ) -{ +export function delete_token(req, res) { let logger = req.ctx.logger; let token = req.body.token; let username = req.session.username; let db_manager = typeorm_connection.manager; - logger.info( "Deleting token" ); + logger.info('Deleting token'); db_manager - .getRepository( db_user.users ) + .getRepository(db_user.users) .findOne({ - email: username + email: username, }) - .then( (got_user) => { - logger.info( "API token deleted for user: " + username ); + .then(got_user => { + logger.info('API token deleted for user: ' + username); return db_manager - .getRepository( db_access_token.access_token ) + .getRepository(db_access_token.access_token) .delete({ - token: token - ,user: got_user + token: token, + user: got_user, }); }) - .then( () => { - logger.info( "API token deleted for user: " + username ); - render_tokens( req, res ); + .then(() => { + logger.info('API token deleted for user: ' + username); + render_tokens(req, res); }) - .catch( get_generic_db_error( logger, res ) ); + .catch(get_generic_db_error(logger, res)); } -export function is_user_logged_in( req, res ) -{ +export function is_user_logged_in(req, res) { let logger = req.ctx.logger; let username = req.session.username; let is_logged_in = req.session.is_logged_in; - if(! req.session.check_login) req.session.check_login = 0; + if (!req.session.check_login) req.session.check_login = 0; req.session.check_login += 1; - logger.info( "Username [" + username + "], checking logged in setting" - + ", which is " + is_logged_in ); + logger.info( + 'Username [' + + username + + '], checking logged in setting' + + ', which is ' + + is_logged_in, + ); - res - .status( is_logged_in ? 200 : 403 ) - .send({ username: username }) + res.status(is_logged_in ? 200 : 403) + .send({username: username}) .end(); } -export function get_members_pending( req, res ) -{ +export function get_members_pending(req, res) { let logger = req.ctx.logger; let wa = req.ctx.wa; - let success_callback = ( members: Array ) => { - logger.info( "Fetched pending members from Wild Apricot" ); - res - .status( 200 ) - .send( members ) - .end(); + let success_callback = (members: Array) => { + logger.info('Fetched pending members from Wild Apricot'); + res.status(200).send(members).end(); }; - let error_callback = ( err: Error ) => { - logger.error( "Could not fetch pending members from Wild Apricot: " - + err.toString() ); - res - .status( 500 ) - .send( "Error fetching data from Wild Apricot" ) - .end(); + let error_callback = (err: Error) => { + logger.error( + 'Could not fetch pending members from Wild Apricot: ' + + err.toString(), + ); + res.status(500).send('Error fetching data from Wild Apricot').end(); }; - wa.fetch_pending_members( - success_callback - ,error_callback - ); + wa.fetch_pending_members(success_callback, error_callback); } -export function member_signup( req, res ) -{ +export function member_signup(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.query, [ - valid.isInteger( 'wa_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.query, [valid.isInteger('wa_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let wa_id = req.query['wa_id']; let wa = req.ctx.wa; wa.fetch_member_data( - wa_id - ,(member) => { + wa_id, + member => { let size_limit = req.ctx.conf['photo_size_limit']; - size_limit = sprintf.sprintf( "%0.1f MB", - size_limit / 1024 / 1024); - - let render = tmpl_view( "member-signup", { - first_name: member['first_name'] - ,last_name: member['last_name'] - ,phone: member['phone'] - ,email: member['email'] - ,wa_id: wa_id - ,photo_size_limit: size_limit - }, [], 200 ); - render( req, res ); - } - ,(err) => { - logger.info( "Error fetching WA info for member <" + wa_id + ">: " - + err.toString() ); - res.sendStatus( 500 ).end(); - } + size_limit = sprintf.sprintf('%0.1f MB', size_limit / 1024 / 1024); + + let render = tmpl_view( + 'member-signup', + { + first_name: member['first_name'], + last_name: member['last_name'], + phone: member['phone'], + email: member['email'], + wa_id: wa_id, + photo_size_limit: size_limit, + }, + [], + 200, + ); + render(req, res); + }, + err => { + logger.info( + 'Error fetching WA info for member <' + + wa_id + + '>: ' + + err.toString(), + ); + res.sendStatus(500).end(); + }, ); } -export function members_active( req, res ) -{ +export function members_active(req, res) { let logger = req.ctx.logger; let query = req.query; - if(! query['offset'] ) query['offset'] = 0; - if(! query['per_page'] ) query['per_page'] = 20; + if (!query['offset']) query['offset'] = 0; + if (!query['per_page']) query['per_page'] = 20; try { - valid.validate( query, [ - valid.isInteger( 'offset' ) - ,valid.isInteger( 'per_page' ) + valid.validate(query, [ + valid.isInteger('offset'), + valid.isInteger('per_page'), ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - let offset: number = parseInt( query['offset'] ); - let per_page: number = parseInt( query['per_page'] ); + let offset: number = parseInt(query['offset']); + let per_page: number = parseInt(query['per_page']); - db.get_members( offset, per_page - ,( members ) => { - logger.info( "Fetched " + members.length - + " members starting at " + offset ); + db.get_members( + offset, + per_page, + members => { + logger.info( + 'Fetched ' + members.length + ' members starting at ' + offset, + ); let prev_offset: number = offset - per_page; let render_args = { - next_offset: offset + per_page - ,prev_offset: prev_offset + next_offset: offset + per_page, + prev_offset: prev_offset, // TODO detect if there are any left and set next as needed - ,next: true - ,prev: (prev_offset >= 0) - ,per_page: per_page - ,members: members.map( (_) => { + next: true, + prev: prev_offset >= 0, + per_page: per_page, + members: members.map(_ => { let member = { - member_id: _.member_id - ,first_name: _.firstName - ,last_name: _.lastName + member_id: _.member_id, + first_name: _.firstName, + last_name: _.lastName, }; return member; - }) + }), }; - let render = tmpl_view( "members-active" - ,render_args - ,[] - ,200 - ); - render( req, res ); - } - ,get_generic_db_error( logger, res ) + let render = tmpl_view('members-active', render_args, [], 200); + render(req, res); + }, + get_generic_db_error(logger, res), ); } -export function member_info( req, res ) -{ +export function member_info(req, res) { let logger = req.ctx.logger; let params = req.params; try { - valid.validate( params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - db.get_member( params['member_id'] - ,( member ) => { - logger.info( "Fetched member" ); + db.get_member( + params['member_id'], + member => { + logger.info('Fetched member'); let render_args = { - member_id: member.member_id - ,rfid: member.rfid - ,first_name: member.firstName - ,last_name: member.lastName - ,status: "Active" + member_id: member.member_id, + rfid: member.rfid, + first_name: member.firstName, + last_name: member.lastName, + status: 'Active', }; - let render = tmpl_view( "member" - ,render_args - ,[] - ,200 - ); - render( req, res ); - } - ,get_member_id_not_found_error( logger, res, params['member_id'] ) - ,get_generic_db_error( logger, res ) + let render = tmpl_view('member', render_args, [], 200); + render(req, res); + }, + get_member_id_not_found_error(logger, res, params['member_id']), + get_generic_db_error(logger, res), ); } -export function post_member_signup_email( req, res ) -{ +export function post_member_signup_email(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params['member_id']; - db.get_member( member_id - ,(member) => { - let to_name = member.firstName + " " + member.lastName; + db.get_member( + member_id, + member => { + let to_name = member.firstName + ' ' + member.lastName; let to_email = member.email; let auth = fetch_google_auth( - req.ctx.conf - ,fetch_google_email_scopes() - ,( google_client ) => { + req.ctx.conf, + fetch_google_email_scopes(), + google_client => { let sender = new email_sender.Email({ - auth: google_client + auth: google_client, }); - sender.init( () => { + sender.init(() => { sender.send_new_member_signup({ - to_name: to_name - ,to_email: to_email - ,from_name: req.ctx.conf['email_new_member_signup_from_name'] - ,from_email: req.ctx.conf['email_new_member_signup_from_email'] - ,success_callback: () => { - logger.info( "New member signup email sent" ); - res.sendStatus( 200 ).end(); - } - ,error_callback: ( err: Error ) => { - logger.error( "Error sending new member email: " - + err.toString() ); - res.sendStatus( 500 ).end(); - } + to_name: to_name, + to_email: to_email, + from_name: + req.ctx.conf[ + 'email_new_member_signup_from_name' + ], + from_email: + req.ctx.conf[ + 'email_new_member_signup_from_email' + ], + success_callback: () => { + logger.info('New member signup email sent'); + res.sendStatus(200).end(); + }, + error_callback: (err: Error) => { + logger.error( + 'Error sending new member email: ' + + err.toString(), + ); + res.sendStatus(500).end(); + }, }); }); - } + }, ); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function post_group_member_signup_email( req, res ) -{ +export function post_group_member_signup_email(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } @@ -991,153 +912,171 @@ export function post_group_member_signup_email( req, res ) let send_email = ( first_name: string, photo_path: string, - answers: Array + answers: Array, ) => { let auth = fetch_google_auth( - req.ctx.conf - ,fetch_google_email_scopes() - ,( google_client ) => { + req.ctx.conf, + fetch_google_email_scopes(), + google_client => { let sender = new email_sender.Email({ - auth: google_client + auth: google_client, }); - sender.init( () => { + sender.init(() => { sender.send_new_group_member_signup({ - to_name: req.ctx.conf['email_group_new_member_signup_to_name'] - ,to_email: req.ctx.conf['email_group_new_member_signup_to_email'] - ,from_name: req.ctx.conf['email_new_member_signup_from_name'] - ,from_email: req.ctx.conf['email_new_member_signup_from_email'] - ,member_first_name: first_name - ,photo_path: photo_path - ,answers: answers - ,success_callback: () => { - logger.info( "New member group signup email sent" ); - res.sendStatus( 200 ).end(); - } - ,error_callback: ( err: Error ) => { + to_name: + req.ctx.conf[ + 'email_group_new_member_signup_to_name' + ], + to_email: + req.ctx.conf[ + 'email_group_new_member_signup_to_email' + ], + from_name: + req.ctx.conf['email_new_member_signup_from_name'], + from_email: + req.ctx.conf['email_new_member_signup_from_email'], + member_first_name: first_name, + photo_path: photo_path, + answers: answers, + success_callback: () => { + logger.info('New member group signup email sent'); + res.sendStatus(200).end(); + }, + error_callback: (err: Error) => { throw err; - } + }, }); }); - } + }, ); }; // TODO This got out of hand with callbacks. Cleanup. - db.get_member_wild_apricot( member_id - ,( wild_apricot_id ) => { - req.ctx.wa.fetch_member_answers( wild_apricot_id - ,( member_answers: Array ) => { - db.get_member( member_id - ,(member) => { + db.get_member_wild_apricot( + member_id, + wild_apricot_id => { + req.ctx.wa.fetch_member_answers( + wild_apricot_id, + (member_answers: Array) => { + db.get_member( + member_id, + member => { db.get_member_photo( - member_id - ,(photo_path) => { + member_id, + photo_path => { send_email( - member.firstName - ,photo_path - ,member_answers + member.firstName, + photo_path, + member_answers, ); - } - ,get_member_id_not_found_error( - logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error( + logger, + res, + member_id, + ), + get_generic_db_error(logger, res), ); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); - } - ,( err: Error ) => { - logger.error( "Error fetching member answers from" - + " Wild Apricot: " + err.toString() ); - res.sendStatus( 500 ).end(); - } + }, + (err: Error) => { + logger.error( + 'Error fetching member answers from' + + ' Wild Apricot: ' + + err.toString(), + ); + res.sendStatus(500).end(); + }, ); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -export function put_member_photo( req, res ) -{ +export function put_member_photo(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) + valid.validate(req.params, [valid.isUUID('member_id')]); + valid.validate(req.body, [ + valid.byteLengthLimit(req.ctx.conf['photo_size_limit']), ]); - valid.validate( req.body, [ - valid.byteLengthLimit( req.ctx.conf['photo_size_limit'] ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } - let decoded_photo = Buffer.from( req.body.toString(), 'base64' ); + let decoded_photo = Buffer.from(req.body.toString(), 'base64'); let member_id = req.params['member_id']; - let path = req.ctx.conf['photo_dir'] + "/" + shortid.generate(); - logger.info( "Saving photo (" + decoded_photo.length + " bytes)" - + " to " + path + " for member ID " + member_id ); + let path = req.ctx.conf['photo_dir'] + '/' + shortid.generate(); + logger.info( + 'Saving photo (' + + decoded_photo.length + + ' bytes)' + + ' to ' + + path + + ' for member ID ' + + member_id, + ); let promises = [ - new Promise( (resolve, reject) => fs.writeFile( - path - ,decoded_photo - ,(err) => { - if( err ) reject( err ); + new Promise((resolve, reject) => + fs.writeFile(path, decoded_photo, err => { + if (err) reject(err); else resolve(); - }) - ) - ,new Promise( (resolve, reject) => db.set_member_photo( - member_id - ,path - ,resolve - ,(err) => reject( err ) - ,(err) => reject( err ) - ) ) + }), + ), + new Promise((resolve, reject) => + db.set_member_photo( + member_id, + path, + resolve, + err => reject(err), + err => reject(err), + ), + ), ]; - Promise.all( promises ).then( () => { - res.sendStatus( 204 ).end(); - }).catch( (err) => { - logger.error( "Error setting photo: " + err ); - res.sendStatus( 500 ).end(); - }); + Promise.all(promises) + .then(() => { + res.sendStatus(204).end(); + }) + .catch(err => { + logger.error('Error setting photo: ' + err); + res.sendStatus(500).end(); + }); } -export function get_member_photo( req, res ) -{ +export function get_member_photo(req, res) { let logger = req.ctx.logger; try { - valid.validate( req.params, [ - valid.isUUID( 'member_id' ) - ]); - } - catch (err) { - handle_generic_validation_error( logger, res, err ); + valid.validate(req.params, [valid.isUUID('member_id')]); + } catch (err) { + handle_generic_validation_error(logger, res, err); return; } let member_id = req.params.member_id; - db.get_member_photo( member_id - ,(path: string) => { - fs.realpath( path, ( err, real_path ) => { - logger.info( "Member photo: " + real_path ); - res - .status( 200 ) + db.get_member_photo( + member_id, + (path: string) => { + fs.realpath(path, (err, real_path) => { + logger.info('Member photo: ' + real_path); + res.status(200) // TODO set content type based on image - .set( 'Content-Type', 'image/jpeg' ) - .sendFile( real_path ); + .set('Content-Type', 'image/jpeg') + .sendFile(real_path); }); - } - ,get_member_id_not_found_error( logger, res, member_id ) - ,get_generic_db_error( logger, res ) + }, + get_member_id_not_found_error(logger, res, member_id), + get_generic_db_error(logger, res), ); } -// No longer use this alternative method to fetch the OAuth2 ID from Google, +// No longer use this alternative method to fetch the OAuth2 ID from Google, // but keep it around just in case. /* export function google_oauth( req, res ) @@ -1168,21 +1107,18 @@ export function google_oauth( req, res ) */ export function tmpl_view( - view: string - ,args = {} - ,errors = [] - ,status_code = 200 -) -{ - return ( req, res ) => { - req.ctx.logger.info( "Rendering view: " + view ); + view: string, + args = {}, + errors = [], + status_code = 200, +) { + return (req, res) => { + req.ctx.logger.info('Rendering view: ' + view); let tokens = new Tokens(); - let csrf_token = tokens.create( req.session.csrf_secret ); - args["csrf"] = csrf_token; + let csrf_token = tokens.create(req.session.csrf_secret); + args['csrf'] = csrf_token; - res - .status( status_code ) - .render( view, args ); + res.status(status_code).render(view, args); }; } diff --git a/src/typeorm/entities/access_token.ts b/src/typeorm/entities/access_token.ts index 7fdff99..a7cf95a 100644 --- a/src/typeorm/entities/access_token.ts +++ b/src/typeorm/entities/access_token.ts @@ -1,44 +1,52 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -import {users} from "./users"; - - -@Entity("access_token" ,{schema:"public" } ) -@Index("access_token_token_key",["token",],{unique:true}) +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; +import {users} from './users'; + +@Entity('access_token', {schema: 'public'}) +@Index('access_token_token_key', ['token'], {unique: true}) export class access_token { - @PrimaryGeneratedColumn({ - type:"integer", - name:"id" - }) - id:number; - - - - @ManyToOne(()=>users, (users: users)=>users.accessTokens,{ nullable:false, }) - @JoinColumn({ name:'user_id'}) - user:users | null; - - - @Column("text",{ - nullable:false, + type: 'integer', + name: 'id', + }) + id: number; + + @ManyToOne(() => users, (users: users) => users.accessTokens, { + nullable: false, + }) + @JoinColumn({name: 'user_id'}) + user: users | null; + + @Column('text', { + nullable: false, unique: true, - name:"token" - }) - token:string; - - - @Column("text",{ - nullable:false, - name:"name" - }) - name:string; - - - @Column("text",{ - nullable:false, + name: 'token', + }) + token: string; + + @Column('text', { + nullable: false, + name: 'name', + }) + name: string; + + @Column('text', { + nullable: false, default: () => "''", - name:"notes" - }) - notes:string; - + name: 'notes', + }) + notes: string; } diff --git a/src/typeorm/entities/members.ts b/src/typeorm/entities/members.ts index 7d67dc2..5fb724c 100644 --- a/src/typeorm/entities/members.ts +++ b/src/typeorm/entities/members.ts @@ -1,109 +1,110 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -import {us_address} from "./us_address"; -import {rfid_log} from "./rfid_log"; - - -@Entity("members" ,{schema:"public" } ) -@Index("members_email_key",["email",],{unique:true}) -@Index("member_name",["first_name","last_name",]) -@Index("members_member_id_key",["member_id",],{unique:true}) -@Index("members_rfid_key",["rfid",],{unique:true}) -@Index("members_slack_id_key",["slack_id",],{unique:true}) -@Index("members_wildapricot_id_key",["wildapricot_id",],{unique:true}) +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; +import {us_address} from './us_address'; +import {rfid_log} from './rfid_log'; + +@Entity('members', {schema: 'public'}) +@Index('members_email_key', ['email'], {unique: true}) +@Index('member_name', ['first_name', 'last_name']) +@Index('members_member_id_key', ['member_id'], {unique: true}) +@Index('members_rfid_key', ['rfid'], {unique: true}) +@Index('members_slack_id_key', ['slack_id'], {unique: true}) +@Index('members_wildapricot_id_key', ['wildapricot_id'], {unique: true}) export class members { - @PrimaryGeneratedColumn({ - type:"integer", - name:"id" - }) - id:number; - + type: 'integer', + name: 'id', + }) + id: number; - @Column("uuid",{ - nullable:true, + @Column('uuid', { + nullable: true, unique: true, - default: () => "uuid_generate_v4()", - name:"member_id" - }) - member_id:string | null; - + default: () => 'uuid_generate_v4()', + name: 'member_id', + }) + member_id: string | null; - @Column("text",{ - nullable:true, + @Column('text', { + nullable: true, unique: true, - name:"wildapricot_id" - }) - wildapricot_id:string | null; - + name: 'wildapricot_id', + }) + wildapricot_id: string | null; - @Column("text",{ - nullable:true, + @Column('text', { + nullable: true, unique: true, - name:"rfid" - }) - rfid:string | null; - + name: 'rfid', + }) + rfid: string | null; - @Column("integer",{ - nullable:true, + @Column('integer', { + nullable: true, unique: true, - name:"slack_id" - }) - slack_id:number | null; - - - - @ManyToOne(()=>us_address, (us_address: us_address)=>us_address.memberss,{ }) - @JoinColumn({ name:'address_id'}) - address:us_address | null; - - - @Column("text",{ - nullable:true, - name:"first_name" - }) - first_name:string | null; - - - @Column("text",{ - nullable:true, - name:"last_name" - }) - last_name:string | null; - - - @Column("text",{ - nullable:true, - name:"phone" - }) - phone:string | null; - - - @Column("text",{ - nullable:false, + name: 'slack_id', + }) + slack_id: number | null; + + @ManyToOne( + () => us_address, + (us_address: us_address) => us_address.memberss, + {}, + ) + @JoinColumn({name: 'address_id'}) + address: us_address | null; + + @Column('text', { + nullable: true, + name: 'first_name', + }) + first_name: string | null; + + @Column('text', { + nullable: true, + name: 'last_name', + }) + last_name: string | null; + + @Column('text', { + nullable: true, + name: 'phone', + }) + phone: string | null; + + @Column('text', { + nullable: false, unique: true, - name:"email" - }) - email:string; - - - @Column("boolean",{ - nullable:true, - default: () => "false", - name:"status" - }) - status:boolean | null; - - - @Column("text",{ - nullable:true, - name:"photo" - }) - photo:string | null; - - - - @OneToMany(()=>rfid_log, (rfid_log: rfid_log)=>rfid_log.member) - rfidLogs:rfid_log[]; - + name: 'email', + }) + email: string; + + @Column('boolean', { + nullable: true, + default: () => 'false', + name: 'status', + }) + status: boolean | null; + + @Column('text', { + nullable: true, + name: 'photo', + }) + photo: string | null; + + @OneToMany(() => rfid_log, (rfid_log: rfid_log) => rfid_log.member) + rfidLogs: rfid_log[]; } diff --git a/src/typeorm/entities/rfid_log.ts b/src/typeorm/entities/rfid_log.ts index fc2200f..571e1b5 100644 --- a/src/typeorm/entities/rfid_log.ts +++ b/src/typeorm/entities/rfid_log.ts @@ -1,42 +1,48 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -import {members} from "./members"; - - -@Entity("rfid_log" ,{schema:"public" } ) +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; +import {members} from './members'; + +@Entity('rfid_log', {schema: 'public'}) export class rfid_log { - @PrimaryGeneratedColumn({ - type:"integer", - name:"id" - }) - id:number; - - - @Column("text",{ - nullable:false, - name:"rfid" - }) - rfid:string; - - - @Column("boolean",{ - nullable:false, - name:"is_active" - }) - is_active:boolean; - - - - @ManyToOne(()=>members, (members: members)=>members.rfidLogs,{ }) - @JoinColumn({ name:'member_id'}) - member:members | null; - - - @Column("timestamp without time zone",{ - nullable:false, - default: () => "now()", - name:"log_timestamp" - }) - log_timestamp:Date; - + type: 'integer', + name: 'id', + }) + id: number; + + @Column('text', { + nullable: false, + name: 'rfid', + }) + rfid: string; + + @Column('boolean', { + nullable: false, + name: 'is_active', + }) + is_active: boolean; + + @ManyToOne(() => members, (members: members) => members.rfidLogs, {}) + @JoinColumn({name: 'member_id'}) + member: members | null; + + @Column('timestamp without time zone', { + nullable: false, + default: () => 'now()', + name: 'log_timestamp', + }) + log_timestamp: Date; } diff --git a/src/typeorm/entities/session.ts b/src/typeorm/entities/session.ts index f91f35a..724d587 100644 --- a/src/typeorm/entities/session.ts +++ b/src/typeorm/entities/session.ts @@ -1,28 +1,37 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; - -@Entity("session" ,{schema:"public" } ) +@Entity('session', {schema: 'public'}) export class session { + @Column('character varying', { + nullable: false, + primary: true, + name: 'sid', + }) + sid: string; - @Column("character varying",{ - nullable:false, - primary:true, - name:"sid" - }) - sid:string; - - - @Column("json",{ - nullable:false, - name:"sess" - }) - sess:object; - + @Column('json', { + nullable: false, + name: 'sess', + }) + sess: object; - @Column("timestamp without time zone",{ - nullable:false, - name:"expire" - }) - expire:Date; - + @Column('timestamp without time zone', { + nullable: false, + name: 'expire', + }) + expire: Date; } diff --git a/src/typeorm/entities/us_address.ts b/src/typeorm/entities/us_address.ts index 59f7dd6..1524e3e 100644 --- a/src/typeorm/entities/us_address.ts +++ b/src/typeorm/entities/us_address.ts @@ -1,54 +1,58 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -import {members} from "./members"; - - -@Entity("us_address" ,{schema:"public" } ) +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; +import {members} from './members'; + +@Entity('us_address', {schema: 'public'}) export class us_address { - @PrimaryGeneratedColumn({ - type:"integer", - name:"id" - }) - id:number; - - - @Column("text",{ - nullable:false, - name:"address1" - }) - address1:string; - - - @Column("text",{ - nullable:true, - name:"address2" - }) - address2:string | null; - - - @Column("text",{ - nullable:false, - name:"city" - }) - city:string; - - - @Column("text",{ - nullable:false, - name:"state" - }) - state:string; - - - @Column("text",{ - nullable:false, - name:"zip" - }) - zip:string; - - - - @OneToMany(()=>members, (members: members)=>members.address) - memberss:members[]; - + type: 'integer', + name: 'id', + }) + id: number; + + @Column('text', { + nullable: false, + name: 'address1', + }) + address1: string; + + @Column('text', { + nullable: true, + name: 'address2', + }) + address2: string | null; + + @Column('text', { + nullable: false, + name: 'city', + }) + city: string; + + @Column('text', { + nullable: false, + name: 'state', + }) + state: string; + + @Column('text', { + nullable: false, + name: 'zip', + }) + zip: string; + + @OneToMany(() => members, (members: members) => members.address) + memberss: members[]; } diff --git a/src/typeorm/entities/users.ts b/src/typeorm/entities/users.ts index 8a1b672..813c5ea 100644 --- a/src/typeorm/entities/users.ts +++ b/src/typeorm/entities/users.ts @@ -1,49 +1,57 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -import {access_token} from "./access_token"; - - -@Entity("users" ,{schema:"public" } ) -@Index("users_email_key",["email",],{unique:true}) +import { + BaseEntity, + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + OneToOne, + PrimaryColumn, + PrimaryGeneratedColumn, + RelationId, +} from 'typeorm'; +import {access_token} from './access_token'; + +@Entity('users', {schema: 'public'}) +@Index('users_email_key', ['email'], {unique: true}) export class users { - @PrimaryGeneratedColumn({ - type:"integer", - name:"id" - }) - id:number; - + type: 'integer', + name: 'id', + }) + id: number; - @Column("text",{ - nullable:false, + @Column('text', { + nullable: false, unique: true, - name:"email" - }) - email:string; - - - @Column("text",{ - nullable:false, - name:"password" - }) - password:string; - - - @Column("text",{ - nullable:false, - name:"password_salt" - }) - password_salt:string; - - - @Column("text",{ - nullable:false, - name:"password_storage" - }) - password_storage:string; - - - - @OneToMany(()=>access_token, (access_token: access_token)=>access_token.user) - accessTokens:access_token[]; - + name: 'email', + }) + email: string; + + @Column('text', { + nullable: false, + name: 'password', + }) + password: string; + + @Column('text', { + nullable: false, + name: 'password_salt', + }) + password_salt: string; + + @Column('text', { + nullable: false, + name: 'password_storage', + }) + password_storage: string; + + @OneToMany( + () => access_token, + (access_token: access_token) => access_token.user, + ) + accessTokens: access_token[]; } diff --git a/src/util.ts b/src/util.ts index 6a04b6a..2dc6b9b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,54 +1,49 @@ -import * as db from "./db"; -import * as fs from "fs"; -import config from "./config"; -import * as pg from "./db-pg"; -import * as rnd_str from "crypto-random-string"; -import * as shortid from "shortid"; -import * as yaml from "js-yaml"; +import * as db from './db'; +import * as fs from 'fs'; +import config from './config'; +import * as pg from './db-pg'; +import * as rnd_str from 'crypto-random-string'; +import * as shortid from 'shortid'; +import * as yaml from 'js-yaml'; // const CONF_FILE = "./config.yaml"; // Base64 gives you 6 bits per character. A length of 40 gives us 240-bits. const TOKEN_LEN_BASE64 = 40; - -export function error_handler (err) -{ +export function error_handler(err) { throw err; } -export function get_pg_connection(): pg.PG -{ +export function get_pg_connection(): pg.PG { let conf = config(); let db = new pg.PG( - conf["db_host"] - ,conf["db_port"] - ,conf["db_name"] - ,conf["db_user"] - ,conf["db_password"] + conf['db_host'], + conf['db_port'], + conf['db_name'], + conf['db_user'], + conf['db_password'], ); return db; } -export function test_member_data ( - rfid: string = shortid.generate() -): db.SimpleMember -{ - let email = shortid.generate() + "@example.com"; +export function test_member_data( + rfid: string = shortid.generate(), +): db.SimpleMember { + let email = shortid.generate() + '@example.com'; let member_data = { - rfid: rfid - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "555 555 4567" - ,email: email + rfid: rfid, + firstName: 'Foo', + lastName: 'Bar', + phone: '555 555 4567', + email: email, }; return member_data; } -export function make_secure_token(): string -{ +export function make_secure_token(): string { let token = rnd_str({ - length: TOKEN_LEN_BASE64 - ,type: 'url-safe' + length: TOKEN_LEN_BASE64, + type: 'url-safe', }); return token; } diff --git a/src/validation.ts b/src/validation.ts index dec90f7..9e7ff6c 100644 --- a/src/validation.ts +++ b/src/validation.ts @@ -29,40 +29,38 @@ export let validate = function (params, validation_list) { let errors = []; - validation_list.forEach( (callback) => { + validation_list.forEach(callback => { try { - callback( params ); - } - catch (err) { - errors.push( err ); + callback(params); + } catch (err) { + errors.push(err); } }); - if( errors.length > 0 ) { - throw new Error( "Validation errors: " - + errors.map( - (err) => "<<" + err.toString() + ">>" - ).join( " " ) + if (errors.length > 0) { + throw new Error( + 'Validation errors: ' + + errors.map(err => '<<' + err.toString() + '>>').join(' '), ); } return true; }; - let matchSingleField = function (field, regex, typeName, allowNull = false) { - return (params) => { + return params => { let value = params[field]; - if( allowNull && value == null ) return true; - - if(! regex.exec( value )) { - throw new Error( "Field '" - + field - + "' was supposed to be " - + typeName - + ", value is '" - + value - + "'" + if (allowNull && value == null) return true; + + if (!regex.exec(value)) { + throw new Error( + "Field '" + + field + + "' was supposed to be " + + typeName + + ", value is '" + + value + + "'", ); } @@ -70,98 +68,108 @@ let matchSingleField = function (field, regex, typeName, allowNull = false) { }; }; -export let isInteger = - (field, allowNull = false) => matchSingleField( field, /^-?[0-9]*$/, - "integer", allowNull ); -export let isName = - (field, allowNull = false) => matchSingleField( field, /^[A-Za-z0-9]+$/, - "name", allowNull ); -export let isWords = - (field, allowNull = false ) => matchSingleField( field, /^[A-Za-z0-9\s]*$/, - "words", allowNull ); -export let isUSPhone = - (field, allowNull = false) => matchSingleField( field, +export let isInteger = (field, allowNull = false) => + matchSingleField(field, /^-?[0-9]*$/, 'integer', allowNull); +export let isName = (field, allowNull = false) => + matchSingleField(field, /^[A-Za-z0-9]+$/, 'name', allowNull); +export let isWords = (field, allowNull = false) => + matchSingleField(field, /^[A-Za-z0-9\s]*$/, 'words', allowNull); +export let isUSPhone = (field, allowNull = false) => + matchSingleField( + field, // Why can't JavaScript support /x? /^(?:1[\s\-]*)?(?:[0-9]{3}[\s\-]*)?[0-9]{3}[\s\-]?[0-9]{4}$/, - "phone", allowNull ); -export let isIdentifier = - (field, allowNull = false ) => matchSingleField( field, /^[A-Za-z0-9\-\_]*$/, - "identifier", allowNull ); + 'phone', + allowNull, + ); +export let isIdentifier = (field, allowNull = false) => + matchSingleField(field, /^[A-Za-z0-9\-\_]*$/, 'identifier', allowNull); // From: https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url -let urlRegex = new RegExp('^(https?:\\/\\/)?'+ // protocol - '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name - '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address - '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path - '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string - '(\\#[-a-z\\d_]*)?$','i'); // fragment locator -export let isUrl = - (field, allowNull = false) => matchSingleField( field, urlRegex, "URL", - allowNull ); - -export let isUSAddress = () => function (params) { - validate( params, [ - // TODO - // This set of validations is all wrong. Address1 and 2 might have - // puncutation, zip needs a more formal validation, county and - // country potentially should verify from a list. State, too - isWords( 'address1' ) - ,isWords( 'address2' ) - ,isWords( 'city' ) - ,isName( 'state' ) - ,isWords( 'zip' ) - ,isWords( 'county' ) - ,isWords( 'country' ) - ]); -}; - -export let isBoolean = (field) => function (params) { - if(! ( - ("boolean" == typeof params[field]) - || ( params[field] === "true" ) - || ( params[field] === "false" ) - )) { - throw new Error( "Field '" - + field - + "' was supposed to be a boolean" - + ", value is '" - + params[field] - + "'" ); - } -}; +let urlRegex = new RegExp( + '^(https?:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', + 'i', +); // fragment locator +export let isUrl = (field, allowNull = false) => + matchSingleField(field, urlRegex, 'URL', allowNull); + +export let isUSAddress = () => + function (params) { + validate(params, [ + // TODO + // This set of validations is all wrong. Address1 and 2 might have + // puncutation, zip needs a more formal validation, county and + // country potentially should verify from a list. State, too + isWords('address1'), + isWords('address2'), + isWords('city'), + isName('state'), + isWords('zip'), + isWords('county'), + isWords('country'), + ]); + }; -export let byteLengthLimit = (limit) => function (param) { - let buf = Buffer.from( param ); - let length = buf.toString( 'binary' ).length; +export let isBoolean = field => + function (params) { + if ( + !( + 'boolean' == typeof params[field] || + params[field] === 'true' || + params[field] === 'false' + ) + ) { + throw new Error( + "Field '" + + field + + "' was supposed to be a boolean" + + ", value is '" + + params[field] + + "'", + ); + } + }; - if( length > limit ) { - throw new Error( "Parameter is " - + length - + " bytes, limit is " - + limit - ); - } -}; +export let byteLengthLimit = limit => + function (param) { + let buf = Buffer.from(param); + let length = buf.toString('binary').length; + if (length > limit) { + throw new Error( + 'Parameter is ' + length + ' bytes, limit is ' + limit, + ); + } + }; /* - * OK, let's talk about email validation. There's a big, long, scary looking - * regex that supposedly validates email addresses. It actually still misses - * some of the insane things that are allowed inside email addresses (like - * deeply nested comments). It also can't tell you that an email address - * goes to an actual user on the other end. Only sending a validation message + * OK, let's talk about email validation. There's a big, long, scary looking + * regex that supposedly validates email addresses. It actually still misses + * some of the insane things that are allowed inside email addresses (like + * deeply nested comments). It also can't tell you that an email address + * goes to an actual user on the other end. Only sending a validation message * can do this ("click here to validate your account"). * - * Since this is for a public web site, we don't need to deal with internal + * Since this is for a public web site, we don't need to deal with internal * email addresses that have no domain, or have a domain with no TLD suffix. - * Therefore, we sanity check that there's at least an @-sign and a dot in - * the domain. There's also no sense letting whitespace through. Checking for + * Therefore, we sanity check that there's at least an @-sign and a dot in + * the domain. There's also no sense letting whitespace through. Checking for * almost anything else doesn't get us anywhere. */ - export let isPublicEmail = (field, allowNull = false) => matchSingleField( - field, /^[^\s>]+@[^\s>]+\.[^\s>]+$/, "email", allowNull ); +export let isPublicEmail = (field, allowNull = false) => + matchSingleField(field, /^[^\s>]+@[^\s>]+\.[^\s>]+$/, 'email', allowNull); // Taken from: // https://stackoverflow.com/questions/7905929/how-to-test-valid-uuid-guid -export let isUUID = (field, allowNull = false) => matchSingleField( - field, /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, "uuid", allowNull ); +export let isUUID = (field, allowNull = false) => + matchSingleField( + field, + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, + 'uuid', + allowNull, + ); diff --git a/src/wild_apricot.ts b/src/wild_apricot.ts index cea3b3d..0ef8767 100644 --- a/src/wild_apricot.ts +++ b/src/wild_apricot.ts @@ -1,12 +1,10 @@ -import * as request from "request"; +import * as request from 'request'; -const wa_domain = "api.wildapricot.org"; -const wa_base_uri = "/v2.1"; -const wa_oauth_uri = "https://oauth.wildapricot.org/auth/token"; +const wa_domain = 'api.wildapricot.org'; +const wa_base_uri = '/v2.1'; +const wa_oauth_uri = 'https://oauth.wildapricot.org/auth/token'; - -export interface WAMember -{ +export interface WAMember { wild_apricot_id: number; first_name: string; last_name: string; @@ -15,52 +13,48 @@ export interface WAMember is_active: boolean; } -export interface WAMemberAnswers -{ +export interface WAMemberAnswers { question: string; answer: string; } -export interface WA -{ +export interface WA { fetch_pending_members( - success_callback: (members: Array) => void - ,error_callback: ( err: Error ) => void + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, ): void; fetch_member_data( - wa_member_id: number - ,success_callback: (member: WAMember) => void - ,error_callback: ( err: Error ) => void + wa_member_id: number, + success_callback: (member: WAMember) => void, + error_callback: (err: Error) => void, ): void; fetch_member_answers( - member_id: string - ,success_callback: (answers: Array ) => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: (answers: Array) => void, + error_callback: (err: Error) => void, ): void; set_member_active( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, ): void; set_member_inactive( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, ): void; fetch_all_members( - success_callback: (members: Array) => void - ,error_callback: ( err: Error ) => void + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, ): void; } - -export class WildApricot -{ +export class WildApricot { private client_name: string; private client_secret: string; private account_id: string; @@ -70,310 +64,333 @@ export class WildApricot private account_uri: string; private approve_uri: string; - constructor( - client_name: string - ,client_secret: string - ,account_id: string - ) - { + client_name: string, + client_secret: string, + account_id: string, + ) { this.client_name = client_name; this.client_secret = client_secret; this.account_id = account_id; - this.contact_uri = "https://" - + wa_domain - + wa_base_uri - + "/Accounts" - + "/" + this.account_id - + "/Contacts?$async=false"; - this.account_uri = "https://" - + wa_domain - + wa_base_uri - + "/accounts" - + "/" + this.account_id - + "/contacts"; - this.approve_uri = "https://" - + wa_domain - + wa_base_uri - + "/rpc" - + "/" + this.account_id - + "/ApprovePendingMembership"; + this.contact_uri = + 'https://' + + wa_domain + + wa_base_uri + + '/Accounts' + + '/' + + this.account_id + + '/Contacts?$async=false'; + this.account_uri = + 'https://' + + wa_domain + + wa_base_uri + + '/accounts' + + '/' + + this.account_id + + '/contacts'; + this.approve_uri = + 'https://' + + wa_domain + + wa_base_uri + + '/rpc' + + '/' + + this.account_id + + '/ApprovePendingMembership'; } - public fetch_pending_members( - success_callback: ( members: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again let fetch = (oauth_token: string) => { - request.get( { - url: this.contact_uri + "&$filter=Status eq PendingNew", - headers: { - Accept: 'application/json' + request.get( + { + url: this.contact_uri + '&$filter=Status eq PendingNew', + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, }, - auth: { - bearer: oauth_token - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - let parsed_users = JSON.parse( body ); - - let members = parsed_users.Contacts.map( (_) => { - return { - wild_apricot_id: _.Id - ,first_name: _.FirstName - ,last_name: _.LastName - ,is_active: _.MembershipEnabled - }; - }); - success_callback( members ); - } - else { - let err = new Error( "Error fetching WA pending members" - + ": " + body ); - error_callback( err ); - } - }); + (error, response, body) => { + if (!error && response.statusCode == 200) { + let parsed_users = JSON.parse(body); + + let members = parsed_users.Contacts.map(_ => { + return { + wild_apricot_id: _.Id, + first_name: _.FirstName, + last_name: _.LastName, + is_active: _.MembershipEnabled, + }; + }); + success_callback(members); + } else { + let err = new Error( + 'Error fetching WA pending members' + ': ' + body, + ); + error_callback(err); + } + }, + ); }; - this.fetch_oauth_token( - fetch - ,error_callback - ); + this.fetch_oauth_token(fetch, error_callback); } public fetch_member_answers( - member_id: string - ,success_callback: (answers: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + member_id: string, + success_callback: (answers: Array) => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again let fetch = (oauth_token: string) => { - request.get( { - url: this.account_uri + "/" + member_id, - headers: { - Accept: 'application/json' + request.get( + { + url: this.account_uri + '/' + member_id, + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, }, - auth: { - bearer: oauth_token - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - let parsed_users = JSON.parse( body ); - - let questions = parsed_users.FieldValues - .filter( (_) => { - return ( - (_['FieldName'] === "How long have you lived in Madison?") - || (_['FieldName'] === "What do you like to make?") - || (_['FieldName'] === "What would you like to learn?") - || (_['FieldName'] === "Are you able/willing to teach something?") - || (_['FieldName'] === "Other comments about yourself?") - ) ? true : false; - } ).map( (_) => { - + (error, response, body) => { + if (!error && response.statusCode == 200) { + let parsed_users = JSON.parse(body); + + let questions = parsed_users.FieldValues.filter(_ => { + return _['FieldName'] === + 'How long have you lived in Madison?' || + _['FieldName'] === + 'What do you like to make?' || + _['FieldName'] === + 'What would you like to learn?' || + _['FieldName'] === + 'Are you able/willing to teach something?' || + _['FieldName'] === + 'Other comments about yourself?' + ? true + : false; + }).map(_ => { return { - question: _['FieldName'] - ,answer: _['Value'] + question: _['FieldName'], + answer: _['Value'], }; - } ); - // Schwartian Transform below. With such an arbitrary sort - // criteria, this is one of the easist ways to bring it - // all together. - // - // TODO aleviate the need for such an arbitrary sort - // criteria. This is all stuck in the way the Bodgery - // does things right now, and could easily change. - questions = questions - .map( (_) => { - let sort_num = - (_['question'] === "How long have you lived in Madison?" ) ? 0 : - ( _['question'] === "What do you like to make?" ) ? 1 : - ( _['question'] === "What would you like to learn?" ) ? 2 : - ( _['question'] === "Are you able/willing to teach something?" ) ? 3 : - ( _['question'] === "Other comments about yourself?" ) ? 4 : - 5; - return [ _, sort_num ]; - }) - .sort( (a, b) => { - return a[1] > b[1] ? 1 : - a[1] < b[1] ? -1 : - 0; - }) - .map( (_) => _[0] ); - success_callback( questions ); - } - else { - let err = new Error( "Error fetching WA member questions: " - + body ); - error_callback( err ); - } - }); + }); + // Schwartian Transform below. With such an arbitrary sort + // criteria, this is one of the easist ways to bring it + // all together. + // + // TODO aleviate the need for such an arbitrary sort + // criteria. This is all stuck in the way the Bodgery + // does things right now, and could easily change. + questions = questions + .map(_ => { + let sort_num = + _['question'] === + 'How long have you lived in Madison?' + ? 0 + : _['question'] === + 'What do you like to make?' + ? 1 + : _['question'] === + 'What would you like to learn?' + ? 2 + : _['question'] === + 'Are you able/willing to teach something?' + ? 3 + : _['question'] === + 'Other comments about yourself?' + ? 4 + : 5; + return [_, sort_num]; + }) + .sort((a, b) => { + return a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0; + }) + .map(_ => _[0]); + success_callback(questions); + } else { + let err = new Error( + 'Error fetching WA member questions: ' + body, + ); + error_callback(err); + } + }, + ); }; - this.fetch_oauth_token( - fetch - ,error_callback - ); + this.fetch_oauth_token(fetch, error_callback); } public set_member_active( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again - let uri = this.approve_uri + "?contactId=" + member_id; + let uri = this.approve_uri + '?contactId=' + member_id; let fetch = (oauth_token: string) => { - request.post( { - url: uri, - headers: { - Accept: 'application/json' + request.post( + { + url: uri, + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, + }, + (error, response, body) => { + if (!error && response.statusCode == 200) { + success_callback(); + } + // There appears to be a bug in Wild Apricot's API, where the + // user is set as activated, but it sends us back a 400 status + // code. Work around this here. + else if (!error && response.statusCode == 400) { + success_callback(); + } else { + let err = new Error( + 'Error setting WA member to active' + + ' (status code: ' + + response.statusCode + + ') <' + + error + + '>: ' + + body, + ); + error_callback(err); + } }, - auth: { - bearer: oauth_token - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - success_callback(); - } - // There appears to be a bug in Wild Apricot's API, where the - // user is set as activated, but it sends us back a 400 status - // code. Work around this here. - else if(! error && response.statusCode == 400 ) { - success_callback(); - } - - else { - let err = new Error( "Error setting WA member to active" - + " (status code: " + response.statusCode - + ") <" + error + ">: " + body ); - error_callback( err ); - } - }); + ); }; - this.fetch_oauth_token( - fetch - ,error_callback - ); + this.fetch_oauth_token(fetch, error_callback); } public fetch_member_data( - wa_member_id: number - ,success_callback: (member: WAMember) => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + wa_member_id: number, + success_callback: (member: WAMember) => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again let fetch = (oauth_token: string) => { - request.get( { - url: this.account_uri + "/" + wa_member_id, - headers: { - Accept: 'application/json' + request.get( + { + url: this.account_uri + '/' + wa_member_id, + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, }, - auth: { - bearer: oauth_token - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - let parsed_users = JSON.parse( body ); - - let phone_field = parsed_users.FieldValues.filter( (_) => { - return _.FieldName === "Phone"; - }); - let phone = phone_field.length > 0 - ? phone_field[0].Value - : ""; - - let member_data = { - wild_apricot_id: wa_member_id - ,first_name: parsed_users['FirstName'] - ,last_name: parsed_users['LastName'] - ,phone: phone - ,email: parsed_users['Email'] - ,is_active: parsed_users['MembershipEnabled'] - }; - success_callback( member_data ); - } - else { - let err = new Error( "Error fetching WA contact info" - + " (status code: " + response.statusCode - + "): " + body ); - error_callback( err ); - } - }); + (error, response, body) => { + if (!error && response.statusCode == 200) { + let parsed_users = JSON.parse(body); + + let phone_field = parsed_users.FieldValues.filter(_ => { + return _.FieldName === 'Phone'; + }); + let phone = + phone_field.length > 0 ? phone_field[0].Value : ''; + + let member_data = { + wild_apricot_id: wa_member_id, + first_name: parsed_users['FirstName'], + last_name: parsed_users['LastName'], + phone: phone, + email: parsed_users['Email'], + is_active: parsed_users['MembershipEnabled'], + }; + success_callback(member_data); + } else { + let err = new Error( + 'Error fetching WA contact info' + + ' (status code: ' + + response.statusCode + + '): ' + + body, + ); + error_callback(err); + } + }, + ); }; - this.fetch_oauth_token( - fetch - ,error_callback - ); + this.fetch_oauth_token(fetch, error_callback); } public set_member_inactive( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again - let uri = this.account_uri + "/" + member_id; + let uri = this.account_uri + '/' + member_id; let fetch = (oauth_token: string) => { - request.put( { - url: uri, - headers: { - Accept: 'application/json' + request.put( + { + url: uri, + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, + json: { + MembershipEnabled: false, + FieldValues: [ + { + FieldName: 'Member', + Value: false, + SystemCode: 'IsMember', + }, + { + FieldName: 'Suspended member', + Value: true, + SystemCode: 'IsSuspendedMember', + }, + { + FieldName: 'Membership enabled', + Value: false, + SystemCode: 'MembershipEnabled', + }, + ], + }, }, - auth: { - bearer: oauth_token + (error, response, body) => { + if (!error && response.statusCode == 200) { + success_callback(); + } else { + let err = new Error( + 'Error setting WA member to inactive' + + ' (status code: ' + + response.statusCode + + ') <' + + error + + '>: ' + + body, + ); + error_callback(err); + } }, - json: { - "MembershipEnabled": false - ,"FieldValues": [ - { - "FieldName": "Member" - ,"Value": false - ,"SystemCode": "IsMember" - } - ,{ - "FieldName": "Suspended member", - "Value": true, - "SystemCode": "IsSuspendedMember" - } - ,{ - "FieldName": "Membership enabled", - "Value": false, - "SystemCode": "MembershipEnabled" - } - ] - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - success_callback(); - } - else { - let err = new Error( "Error setting WA member to inactive" - + " (status code: " + response.statusCode - + ") <" + error + ">: " + body ); - error_callback( err ); - } - }); + ); }; - // TODO Wild Apricot doesn't seem to let you deactive a member + // TODO Wild Apricot doesn't seem to let you deactive a member // through the API. If this can be resolved, reimplement this method. /* this.fetch_oauth_token( @@ -385,92 +402,99 @@ export class WildApricot } public fetch_all_members( - success_callback: (members: Array) => void - ,error_callback: ( err: Error ) => void - ): void - { - // TODO if we get an auth failure, force refetch of oauth token + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): void { + // TODO if we get an auth failure, force refetch of oauth token // and try again let fetch = (oauth_token: string) => { - request.get( { - url: this.account_uri + '?$async=false', - headers: { - Accept: 'application/json' + request.get( + { + url: this.account_uri + '?$async=false', + headers: { + Accept: 'application/json', + }, + auth: { + bearer: oauth_token, + }, }, - auth: { - bearer: oauth_token - } - }, (error, response, body) => { - if(! error && response.statusCode == 200 ) { - let parsed_users = JSON.parse( body ); - let member_data = parsed_users['Contacts'].map( (_) => { - const member = { - wild_apricot_id: _.Id - ,first_name: _.FirstName - ,last_name: _.LastName - ,phone: _.phone - ,email: _.Email - ,is_active: _.MembershipEnabled - }; - return member; - }); - success_callback( member_data ); - } - else { - let err = new Error( "Error fetching WA contact info" - + " (status code: " + response.statusCode - + "): " + body ); - error_callback( err ); - } - }); + (error, response, body) => { + if (!error && response.statusCode == 200) { + let parsed_users = JSON.parse(body); + let member_data = parsed_users['Contacts'].map(_ => { + const member = { + wild_apricot_id: _.Id, + first_name: _.FirstName, + last_name: _.LastName, + phone: _.phone, + email: _.Email, + is_active: _.MembershipEnabled, + }; + return member; + }); + success_callback(member_data); + } else { + let err = new Error( + 'Error fetching WA contact info' + + ' (status code: ' + + response.statusCode + + '): ' + + body, + ); + error_callback(err); + } + }, + ); }; - this.fetch_oauth_token( - fetch - ,error_callback - ); + this.fetch_oauth_token(fetch, error_callback); } - private fetch_oauth_token( - success_callback: ( token: string ) => void - ,error_callback: ( err: Error ) => void - ) - { + success_callback: (token: string) => void, + error_callback: (err: Error) => void, + ) { // TODO save oauth token in a general cache, such as memcached - if( this.oauth_token ) { - success_callback( this.oauth_token ); - } - else { - request.post({ - url: wa_oauth_uri, - auth: { - user: this.client_name - ,pass: this.client_secret - ,sendImmediately: true + if (this.oauth_token) { + success_callback(this.oauth_token); + } else { + request.post( + { + url: wa_oauth_uri, + auth: { + user: this.client_name, + pass: this.client_secret, + sendImmediately: true, + }, + form: { + grant_type: 'client_credentials', + scope: 'auto', + }, }, - form: { - grant_type: 'client_credentials' - ,scope: 'auto' - } - }, (error, response, body) => { - if( (! error) && (response.statusCode == 200) ) { - let parsed_response = JSON.parse( body ); - this.oauth_token = parsed_response.access_token; - success_callback( this.oauth_token ); - } - else { - if( response ) { - error_callback( new Error( "Error fetching OAuth token" - + " from Wild Apricot" - + " (HTTP status " + response.statusCode + ")" - + ": " + body ) ); - } - else { - error_callback( new Error( error ) ); + (error, response, body) => { + if (!error && response.statusCode == 200) { + let parsed_response = JSON.parse(body); + this.oauth_token = parsed_response.access_token; + success_callback(this.oauth_token); + } else { + if (response) { + error_callback( + new Error( + 'Error fetching OAuth token' + + ' from Wild Apricot' + + ' (HTTP status ' + + response.statusCode + + ')' + + ': ' + + body, + ), + ); + } else { + error_callback(new Error(error)); + } } - } - }); + }, + ); } } } diff --git a/src/wild_apricot_mock.ts b/src/wild_apricot_mock.ts index 39f596e..97e082b 100644 --- a/src/wild_apricot_mock.ts +++ b/src/wild_apricot_mock.ts @@ -1,105 +1,88 @@ -import * as wa_api from "./wild_apricot"; +import * as wa_api from './wild_apricot'; - -export interface MockWAMembers -{ +export interface MockWAMembers { is_active: boolean; } - -export class MockWA -{ +export class MockWA { private pending_members: Array; private active_members: Array; private member_answers: { - [ member_id: string ]: Array + [member_id: string]: Array; }; public members: { - [ member_id: string ]: MockWAMembers + [member_id: string]: MockWAMembers; }; - - constructor( args: { - pending?: Array - ,active?: Array - ,member_answers?: { - [ member_id: string ]: Array - } - ,members?: { - [ member_id: string ]: MockWAMembers - } - }) - { + constructor(args: { + pending?: Array; + active?: Array; + member_answers?: { + [member_id: string]: Array; + }; + members?: { + [member_id: string]: MockWAMembers; + }; + }) { this.pending_members = args.pending; this.active_members = args.active; this.member_answers = args.member_answers; this.members = args.members; } - public fetch_pending_members( - success_callback: ( members: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { - success_callback( this.pending_members ); + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): void { + success_callback(this.pending_members); } public fetch_member_answers( - member_id: string - ,success_callback: (answers: Array ) => void - ,error_callback: ( err: Error ) => void - ): void - { - success_callback( - this.member_answers[member_id] - ); + member_id: string, + success_callback: (answers: Array) => void, + error_callback: (err: Error) => void, + ): void { + success_callback(this.member_answers[member_id]); } public set_member_active( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { this.members[member_id].is_active = true; success_callback(); } public set_member_inactive( - member_id: string - ,success_callback: () => void - ,error_callback: ( err: Error ) => void - ): void - { + member_id: string, + success_callback: () => void, + error_callback: (err: Error) => void, + ): void { this.members[member_id].is_active = false; success_callback(); } public fetch_member_data( - wa_member_id: number - ,success_callback: (member: wa_api.WAMember) => void - ,error_callback: ( err: Error ) => void - ): void - { + wa_member_id: number, + success_callback: (member: wa_api.WAMember) => void, + error_callback: (err: Error) => void, + ): void { let member = this.members[wa_member_id]; success_callback({ - first_name: "Johnson" - ,last_name: "McHuman" - ,email: "foo@example.com" - ,phone: "555 555 1234" - ,wild_apricot_id: wa_member_id - ,is_active: member.is_active + first_name: 'Johnson', + last_name: 'McHuman', + email: 'foo@example.com', + phone: '555 555 1234', + wild_apricot_id: wa_member_id, + is_active: member.is_active, }); } public fetch_all_members( - success_callback: (members: Array) => void - ,error_callback: ( err: Error ) => void - ): void - { - success_callback( - this.pending_members - ); + success_callback: (members: Array) => void, + error_callback: (err: Error) => void, + ): void { + success_callback(this.pending_members); } } diff --git a/test/add-member.ts b/test/add-member.ts index 1670c4c..5ee8261 100644 --- a/test/add-member.ts +++ b/test/add-member.ts @@ -1,39 +1,38 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; - -describe( 'PUT /v1/member', function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('PUT /v1/member', function () { + before(() => { + process.env['TEST_RUN'] = '1'; let db = new mock_db.MockDB([], {}); - return server.start( db ); + return server.start(db); }); - it( 'Adds a member', function (done) { - request( server.SERVER ) - .put( '/api/v1/member' ) + it('Adds a member', function (done) { + request(server.SERVER) + .put('/api/v1/member') .send({ - rfid: "00000000" - ,firstName: "Abe" - ,lastName: "Foobar" - ,phone: "15551234" - ,email: "abe.foobar@example.com" + rfid: '00000000', + firstName: 'Abe', + lastName: 'Foobar', + phone: '15551234', + email: 'abe.foobar@example.com', }) - .expect( 201 ) - .expect( function(res) { + .expect(201) + .expect(function (res) { var data = res.body; - assert( data.id, "Returned a member ID" ); + assert(data.id, 'Returned a member ID'); }) - .end( function( err, res ) { - if( err ) done(err); + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/context.ts b/test/context.ts index 5983298..1423167 100644 --- a/test/context.ts +++ b/test/context.ts @@ -1,25 +1,26 @@ -import * as assert from "assert"; -import * as c from "../src/context"; -import * as shortid from "shortid"; +import * as assert from 'assert'; +import * as c from '../src/context'; +import * as shortid from 'shortid'; - -describe( 'Init context', function () { - it( 'Creates a new context', function (done) { +describe('Init context', function () { + it('Creates a new context', function (done) { let did_log: boolean = false; let logger = { - fatal: (...args) => { did_log = true; } - ,error: (...args) => {} - ,warn: (...args) => {} - ,info: (...args) => {} - ,debug: (...args) => {} + fatal: (...args) => { + did_log = true; + }, + error: (...args) => {}, + warn: (...args) => {}, + info: (...args) => {}, + debug: (...args) => {}, }; let conf = {}; let request_id = shortid.generate(); - let ctx = new c.Context( conf, logger, null, null ); + let ctx = new c.Context(conf, logger, null, null); - ctx.logger.fatal( "Log error" ); - assert( did_log, "Log happened" ); + ctx.logger.fatal('Log error'); + assert(did_log, 'Log happened'); done(); }); diff --git a/test/csrf.ts b/test/csrf.ts index d190668..0eee91b 100644 --- a/test/csrf.ts +++ b/test/csrf.ts @@ -1,18 +1,15 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; - -describe( - 'Checks that CSRF tokens are required on methods that change state', - function () { - before( () => { +describe('Checks that CSRF tokens are required on methods that change state', function () { + before(() => { let db = new mock_db.MockDB([], {}); - return server.start( db ); + return server.start(db); }); -/* + /* it( 'Adds a member', function (done) { request( server.SERVER ) .put( '/api/v1/member' ) @@ -32,7 +29,7 @@ describe( }); */ - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/email-group-new-member.ts b/test/email-group-new-member.ts index 8213f85..f17f7f3 100644 --- a/test/email-group-new-member.ts +++ b/test/email-group-new-member.ts @@ -1,82 +1,82 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; -import * as wa_api from "../src/wild_apricot_mock"; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; +import * as wa_api from '../src/wild_apricot_mock'; -const PHOTO_DIR = "test_data/photos/"; -const TEST_PHOTO = "test_data/bodgery_logo.jpg"; +const PHOTO_DIR = 'test_data/photos/'; +const TEST_PHOTO = 'test_data/bodgery_logo.jpg'; - -describe( 'POST /v1/member/:member_id/send_group_signup_email', function () { +describe('POST /v1/member/:member_id/send_group_signup_email', function () { let test_email; - before( () => { + before(() => { test_email = process.env['TEST_EMAIL']; let members = { - "01": { + '01': { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: test_email - } - ,photo: TEST_PHOTO - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: test_email, + }, + photo: TEST_PHOTO, + }, }; - let db = new mock_db.MockDB( members, {} ); + let db = new mock_db.MockDB(members, {}); let conf = server.default_conf(); conf['photo_dir'] = PHOTO_DIR; let wa_mock = new wa_api.MockWA({ member_answers: { - "01": [ + '01': [ + { + question: 'foo', + answer: '1', + }, + { + question: 'foo', + answer: '2', + }, { - question: "foo" - ,answer: "1" - } - ,{ - question: "foo" - ,answer: "2" - } - ,{ - question: "foo" - ,answer: "3" - } - ,{ - question: "foo" - ,answer: "4" - } - ,{ - question: "foo" - ,answer: "5" - } - ] - } + question: 'foo', + answer: '3', + }, + { + question: 'foo', + answer: '4', + }, + { + question: 'foo', + answer: '5', + }, + ], + }, }); - return server.start( db, conf, wa_mock ); + return server.start(db, conf, wa_mock); }); - it( 'Sends the new member signup email for the group', function (done) { - if( test_email ) { - request( server.SERVER ) - .post( '/api/v1/member/01/send_group_signup_email' ) - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + it('Sends the new member signup email for the group', function (done) { + if (test_email) { + request(server.SERVER) + .post('/api/v1/member/01/send_group_signup_email') + .expect(200) + .end(function (err, res) { + if (err) done(err); else done(); }); - } - else { - console.log( "Set TEST_EMAIL env var with an email address" - + " to run this test" ); + } else { + console.log( + 'Set TEST_EMAIL env var with an email address' + + ' to run this test', + ); done(); } }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/email-new-member.ts b/test/email-new-member.ts index 035952d..11cef63 100644 --- a/test/email-new-member.ts +++ b/test/email-new-member.ts @@ -1,47 +1,47 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; - -describe( 'POST /v1/member/:member_id/send_signup_email', function () { +describe('POST /v1/member/:member_id/send_signup_email', function () { let test_email; - before( () => { + before(() => { test_email = process.env['TEST_EMAIL']; let members = { - "01": { + '01': { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: test_email - ,photo: "https://example.com/" - } - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: test_email, + photo: 'https://example.com/', + }, + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Sends the new member signup email', function (done) { - if( test_email ) { - request( server.SERVER ) - .post( '/api/v1/member/01/send_signup_email' ) - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + it('Sends the new member signup email', function (done) { + if (test_email) { + request(server.SERVER) + .post('/api/v1/member/01/send_signup_email') + .expect(200) + .end(function (err, res) { + if (err) done(err); else done(); }); - } - else { - console.log( "Set TEST_EMAIL env var with an email address" - + " to run this test" ); + } else { + console.log( + 'Set TEST_EMAIL env var with an email address' + + ' to run this test', + ); done(); } }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/get-member-address.ts b/test/get-member-address.ts index 2cae2b4..0ef9d12 100644 --- a/test/get-member-address.ts +++ b/test/get-member-address.ts @@ -1,55 +1,57 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; - -describe( 'GET /v1/member/:member_id/address', function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('GET /v1/member/:member_id/address', function () { + before(() => { + process.env['TEST_RUN'] = '1'; let members = {}; - members[uuid] = { + members[uuid] = { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: "foo.bar@example.com" - ,photo: "https://example.com/" - } - ,address: { - name: "Foo Bar" - ,address1: "123 Main St" - ,city: "Madison" - ,state: "WI" - ,zip: "53704" - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: 'foo.bar@example.com', + photo: 'https://example.com/', + }, + address: { + name: 'Foo Bar', + address1: '123 Main St', + city: 'Madison', + state: 'WI', + zip: '53704', + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Gets a member address', function (done) { - request( server.SERVER ) - .get( '/api/v1/member/' + uuid + '/address' ) + it('Gets a member address', function (done) { + request(server.SERVER) + .get('/api/v1/member/' + uuid + '/address') .send() - .expect( 200 ) - .expect( function(res) { + .expect(200) + .expect(function (res) { var data = res.body; - assert.strictEqual( data.name, "Foo Bar", - "Returned correct user" ); + assert.strictEqual( + data.name, + 'Foo Bar', + 'Returned correct user', + ); }) - .end( function( err, res ) { - if( err ) done(err); + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/get-member.ts b/test/get-member.ts index 7d8ebbc..590f66d 100644 --- a/test/get-member.ts +++ b/test/get-member.ts @@ -1,50 +1,55 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; +describe('GET /v1/member', function () { + before(() => { + process.env['TEST_RUN'] = '1'; -describe( 'GET /v1/member', function () { - before( () => { - process.env['TEST_RUN'] = "1"; - - let members = {} + let members = {}; members[uuid] = { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: "foo.bar@example.com" - ,photo: "https://example.com/" - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: 'foo.bar@example.com', + photo: 'https://example.com/', + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Fetches a member', function (done) { - request( server.SERVER ) - .get( '/api/v1/member/' + uuid ) + it('Fetches a member', function (done) { + request(server.SERVER) + .get('/api/v1/member/' + uuid) .send() - .expect( 200 ) - .expect( function(res) { + .expect(200) + .expect(function (res) { var data = res.body; - assert.strictEqual( data.firstName, "Foo", - "Returned correct user" ); - assert.strictEqual( data.photo, "https://example.com/", - "Returned correct photo URL" ); + assert.strictEqual( + data.firstName, + 'Foo', + 'Returned correct user', + ); + assert.strictEqual( + data.photo, + 'https://example.com/', + 'Returned correct photo URL', + ); }) - .end( function( err, res ) { - if( err ) done(err); + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/get-members.ts b/test/get-members.ts index fb6e9f5..83b05fc 100644 --- a/test/get-members.ts +++ b/test/get-members.ts @@ -1,8 +1,7 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; - +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; // TODO /* diff --git a/test/get-pending-members-real.ts b/test/get-pending-members-real.ts index b2fece7..7cef26a 100644 --- a/test/get-pending-members-real.ts +++ b/test/get-pending-members-real.ts @@ -1,36 +1,35 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; -import * as wa_api from "../src/wild_apricot_mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; +import * as wa_api from '../src/wild_apricot_mock'; - -describe( 'GET /v1/members/pending', function() { - before( () => { - process.env['TEST_RUN'] = "1" - let db = new mock_db.MockDB( null, null ); - return server.start( db ); +describe('GET /v1/members/pending', function () { + before(() => { + process.env['TEST_RUN'] = '1'; + let db = new mock_db.MockDB(null, null); + return server.start(db); }); - it( 'Gets all pending members on actual Wild Apricot', function(done) { - request( server.SERVER ) - .get( '/api/v1/members/pending' ) + it('Gets all pending members on actual Wild Apricot', function (done) { + request(server.SERVER) + .get('/api/v1/members/pending') .send() - .expect( 200 ) - .expect( 'Content-Type', /json/ ) - .expect( function(res) { + .expect(200) + .expect('Content-Type', /json/) + .expect(function (res) { let data = res.body; - if(! Array.isArray( data ) ) - throw new Error( "Didn't return array" ); + if (!Array.isArray(data)) + throw new Error("Didn't return array"); }) - .end( function( err, res ) { - if( err ) return done(err); + .end(function (err, res) { + if (err) return done(err); done(); - }) + }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/get-pending-members.ts b/test/get-pending-members.ts index 3e4dbcd..4569f70 100644 --- a/test/get-pending-members.ts +++ b/test/get-pending-members.ts @@ -1,87 +1,86 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; -import * as wa_api from "../src/wild_apricot_mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; +import * as wa_api from '../src/wild_apricot_mock'; - -describe( 'GET /v1/members/pending', function() { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('GET /v1/members/pending', function () { + before(() => { + process.env['TEST_RUN'] = '1'; let wa_mock = new wa_api.MockWA({ // TODO fill in pending and existing members pending: [ { - wild_apricot_id: 1 - ,first_name: "One" - ,last_name: "Number" - ,phone: "555 555 1234" - ,email: "one@example.com" - ,is_active: false - } - ,{ - wild_apricot_id: 2 - ,first_name: "Two" - ,last_name: "Number" - ,phone: "555 555 1234" - ,email: "one@example.com" - ,is_active: false - } - ,{ - wild_apricot_id: 3 - ,first_name: "Three" - ,last_name: "Number" - ,phone: "555 555 1234" - ,email: "one@example.com" - ,is_active: false - } - ] - ,active: [ + wild_apricot_id: 1, + first_name: 'One', + last_name: 'Number', + phone: '555 555 1234', + email: 'one@example.com', + is_active: false, + }, + { + wild_apricot_id: 2, + first_name: 'Two', + last_name: 'Number', + phone: '555 555 1234', + email: 'one@example.com', + is_active: false, + }, + { + wild_apricot_id: 3, + first_name: 'Three', + last_name: 'Number', + phone: '555 555 1234', + email: 'one@example.com', + is_active: false, + }, + ], + active: [ { - wild_apricot_id: 4 - ,first_name: "Four" - ,last_name: "Number" - ,phone: "555 555 1234" - ,email: "one@example.com" - ,is_active: true - } - ,{ - wild_apricot_id: 5 - ,first_name: "Five" - ,last_name: "Number" - ,phone: "555 555 1234" - ,email: "one@example.com" - ,is_active: true - } - ] + wild_apricot_id: 4, + first_name: 'Four', + last_name: 'Number', + phone: '555 555 1234', + email: 'one@example.com', + is_active: true, + }, + { + wild_apricot_id: 5, + first_name: 'Five', + last_name: 'Number', + phone: '555 555 1234', + email: 'one@example.com', + is_active: true, + }, + ], }); - let db = new mock_db.MockDB( null, null ); - return server.start( db, null, wa_mock ); + let db = new mock_db.MockDB(null, null); + return server.start(db, null, wa_mock); }); - it( 'Gets all pending members', function(done) { - request( server.SERVER ) - .get( '/api/v1/members/pending' ) + it('Gets all pending members', function (done) { + request(server.SERVER) + .get('/api/v1/members/pending') .send() - .expect( 200 ) - .expect( 'Content-Type', /json/ ) - .expect( function(res) { + .expect(200) + .expect('Content-Type', /json/) + .expect(function (res) { let data = res.body; - if(! Array.isArray( data ) ) - throw new Error( "Didn't return array" ); - assert.strictEqual( data.length, 3 ); + if (!Array.isArray(data)) + throw new Error("Didn't return array"); + assert.strictEqual(data.length, 3); - assert.strictEqual( data[0].wild_apricot_id, 1 ); - assert.strictEqual( data[0].is_active, false ); + assert.strictEqual(data[0].wild_apricot_id, 1); + assert.strictEqual(data[0].is_active, false); }) - .end( function( err, res ) { - if( err ) return done(err); + .end(function (err, res) { + if (err) return done(err); done(); - }) + }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/google-group-signup.ts b/test/google-group-signup.ts index 6f0b5b0..fcd403a 100644 --- a/test/google-group-signup.ts +++ b/test/google-group-signup.ts @@ -1,47 +1,47 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; - -describe( 'PUT /v1/member/:member_id/google_group_signup', function () { +describe('PUT /v1/member/:member_id/google_group_signup', function () { let test_email; - before( () => { + before(() => { test_email = process.env['TEST_EMAIL']; let members = { - "01": { + '01': { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: test_email - ,photo: "https://example.com/" - } - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: test_email, + photo: 'https://example.com/', + }, + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Adds member to the Google Group list', function (done) { - if( test_email ) { - request( server.SERVER ) - .put( '/api/v1/member/01/google_group_signup' ) - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + it('Adds member to the Google Group list', function (done) { + if (test_email) { + request(server.SERVER) + .put('/api/v1/member/01/google_group_signup') + .expect(200) + .end(function (err, res) { + if (err) done(err); else done(); }); - } - else { - console.log( "Set TEST_EMAIL env var with an email address" - + " to run this test" ); + } else { + console.log( + 'Set TEST_EMAIL env var with an email address' + + ' to run this test', + ); done(); } }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/google-oauth-callback.ts b/test/google-oauth-callback.ts index 5e54cb6..b214d52 100644 --- a/test/google-oauth-callback.ts +++ b/test/google-oauth-callback.ts @@ -1,15 +1,14 @@ -import * as assert from "assert"; -import * as fs from "fs"; -import * as request from "supertest"; -import * as server from "../app"; +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as request from 'supertest'; +import * as server from '../app'; - -describe( 'GET /v1/google_oauth', function () { +describe('GET /v1/google_oauth', function () { let token_file = 'tmp-google-token'; - before( () => { + before(() => { let conf = server.default_conf(); conf['google_oauth_token_path'] = token_file; - return server.start( null, conf ); + return server.start(null, conf); }); // Disabiling this test, as the key is being fetched by another method @@ -40,18 +39,15 @@ describe( 'GET /v1/google_oauth', function () { }); */ - after( () => { + after(() => { let stop_promise = server.stop(); - let unlink_promise = new Promise( (resolve, reject) => { - fs.unlink( token_file, (err) => { + let unlink_promise = new Promise((resolve, reject) => { + fs.unlink(token_file, err => { // Ignore any error, we're just finished resolve(); }); }); - return Promise.all([ - stop_promise - ,unlink_promise - ]); + return Promise.all([stop_promise, unlink_promise]); }); }); diff --git a/test/member-is-active.ts b/test/member-is-active.ts index 99134bd..145d51e 100644 --- a/test/member-is-active.ts +++ b/test/member-is-active.ts @@ -1,85 +1,80 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; -import * as wa_api from "../src/wild_apricot_mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; +import * as wa_api from '../src/wild_apricot_mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; - -describe( '/v1/member/:member_id/is_active', function () { +describe('/v1/member/:member_id/is_active', function () { let wa_mock: wa_api.MockWA; - before( () => { - process.env['TEST_RUN'] = "1"; + before(() => { + process.env['TEST_RUN'] = '1'; let members = {}; - members[uuid] = { - wild_apricot_id: uuid - ,is_active: false + members[uuid] = { + wild_apricot_id: uuid, + is_active: false, }; - let db = new mock_db.MockDB( members, {} ); + let db = new mock_db.MockDB(members, {}); let wa_members = {}; wa_members[uuid] = { - is_active: false + is_active: false, }; wa_mock = new wa_api.MockWA({ - members: wa_members + members: wa_members, }); - return server.start( db, null, wa_mock ); + return server.start(db, null, wa_mock); }); - it( 'Sets member status', function (done) { - let fetch_status = ( - callback: ( res ) => void - ) => { - request( server.SERVER ) - .get( '/api/v1/member/' + uuid + '/is_active' ) + it('Sets member status', function (done) { + let fetch_status = (callback: (res) => void) => { + request(server.SERVER) + .get('/api/v1/member/' + uuid + '/is_active') .send() - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(200) + .end(function (err, res) { + if (err) done(err); else { - callback( res ); + callback(res); } }); }; - let check_is_active = ( res ) => { - assert( res.body, "Returned true" ); - assert( wa_mock.members[uuid].is_active, - "Set is_active on WA" ); + let check_is_active = res => { + assert(res.body, 'Returned true'); + assert(wa_mock.members[uuid].is_active, 'Set is_active on WA'); }; - let check_is_not_active = ( res ) => { - assert(! res.body, "Returned false" ); - assert(! wa_mock.members[uuid].is_active, - "Set is_active on WA to false" ); + let check_is_not_active = res => { + assert(!res.body, 'Returned false'); + assert( + !wa_mock.members[uuid].is_active, + 'Set is_active on WA to false', + ); }; - let set_status = ( - status: boolean - ,callback: ( res ) => void - ) => { - request( server.SERVER ) - .put( '/api/v1/member/' + uuid + '/is_active' ) - .send({ is_active: status }) - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); - else callback( res ); + let set_status = (status: boolean, callback: (res) => void) => { + request(server.SERVER) + .put('/api/v1/member/' + uuid + '/is_active') + .send({is_active: status}) + .expect(200) + .end(function (err, res) { + if (err) done(err); + else callback(res); }); }; - set_status( true, (res) => { - fetch_status( (res) => { - check_is_active( res ); + set_status(true, res => { + fetch_status(res => { + check_is_active(res); - set_status( false, (res) => { - fetch_status( (res) => { - check_is_not_active( res ); + set_status(false, res => { + fetch_status(res => { + check_is_not_active(res); done(); }); }); @@ -87,7 +82,7 @@ describe( '/v1/member/:member_id/is_active', function () { }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/member-log-rfid.ts b/test/member-log-rfid.ts index 393ed08..900715b 100644 --- a/test/member-log-rfid.ts +++ b/test/member-log-rfid.ts @@ -1,38 +1,43 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; - -describe( 'Log RFID', function () { +describe('Log RFID', function () { let db; - before( () => { - process.env['TEST_RUN'] = "1"; + before(() => { + process.env['TEST_RUN'] = '1'; - db = new mock_db.MockDB( {}, {} ); - return server.start( db ); + db = new mock_db.MockDB({}, {}); + return server.start(db); }); - it( 'Logs a successful RFID entry', function (done) { - request( server.SERVER ) - .post( '/api/v1/rfid/log_entry/000123/true' ) + it('Logs a successful RFID entry', function (done) { + request(server.SERVER) + .post('/api/v1/rfid/log_entry/000123/true') .send() - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(200) + .end(function (err, res) { + if (err) done(err); else { - assert.strictEqual( db.rfid_log[0][0], "000123", - "Logged RFID" ); - assert.strictEqual( db.rfid_log[0][1], true, - "Was allowed in" ); + assert.strictEqual( + db.rfid_log[0][0], + '000123', + 'Logged RFID', + ); + assert.strictEqual( + db.rfid_log[0][1], + true, + 'Was allowed in', + ); done(); } }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/member-rfid.ts b/test/member-rfid.ts index ad75528..04fd3ee 100644 --- a/test/member-rfid.ts +++ b/test/member-rfid.ts @@ -1,80 +1,78 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid1 = "0662df8c-e43a-4e90-8b03-3849afbb533e"; -const uuid2 = "c28ec74e-2459-488e-9aec-f6068e8a08a7"; +const uuid1 = '0662df8c-e43a-4e90-8b03-3849afbb533e'; +const uuid2 = 'c28ec74e-2459-488e-9aec-f6068e8a08a7'; +describe('RFID management', function () { + let good_rfid = '0001234567'; + let invalid_rfid = '0007654321'; + let inactive_rfid = '1234567000'; -describe( 'RFID management', function () { - let good_rfid = "0001234567"; - let invalid_rfid = "0007654321"; - let inactive_rfid = "1234567000"; - - - before( () => { + before(() => { let members = {}; members[uuid1] = { - is_active: true - ,rfid: null + is_active: true, + rfid: null, }; members[uuid2] = { - is_active: false - ,rfid: inactive_rfid + is_active: false, + rfid: inactive_rfid, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Sets an RFID on a valid member', function (done) { + it('Sets an RFID on a valid member', function (done) { let fetch_status = () => { - request( server.SERVER ) - .get( '/api/v1/rfid/' + good_rfid ) + request(server.SERVER) + .get('/api/v1/rfid/' + good_rfid) .send() - .expect( 200 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(200) + .end(function (err, res) { + if (err) done(err); else done(); }); }; - process.env['TEST_RUN'] = "1"; - request( server.SERVER ) - .put( '/api/v1/member/' + uuid1 + '/rfid' ) - .send({ rfid: good_rfid }) - .expect( 200 ) - .end( function( err, res ) { - process.env['TEST_RUN'] = "0"; - if( err ) done(err); + process.env['TEST_RUN'] = '1'; + request(server.SERVER) + .put('/api/v1/member/' + uuid1 + '/rfid') + .send({rfid: good_rfid}) + .expect(200) + .end(function (err, res) { + process.env['TEST_RUN'] = '0'; + if (err) done(err); else fetch_status(); }); }); - it( 'Tries to fetch a member that doesn\'t exist', function (done) { - request( server.SERVER ) - .get( '/api/v1/rfid/' + invalid_rfid ) + it("Tries to fetch a member that doesn't exist", function (done) { + request(server.SERVER) + .get('/api/v1/rfid/' + invalid_rfid) .send() - .expect( 404 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(404) + .end(function (err, res) { + if (err) done(err); else done(); }); }); - it( 'Tries to fetch an inactive member', function (done) { - request( server.SERVER ) - .get( '/api/v1/rfid/' + inactive_rfid ) + it('Tries to fetch an inactive member', function (done) { + request(server.SERVER) + .get('/api/v1/rfid/' + inactive_rfid) .send() - .expect( 403 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(403) + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/not-found-error.ts b/test/not-found-error.ts index bd290c5..0fa5b8e 100644 --- a/test/not-found-error.ts +++ b/test/not-found-error.ts @@ -1,24 +1,23 @@ -import * as request from "supertest"; -import * as server from "../app"; +import * as request from 'supertest'; +import * as server from '../app'; - -describe( "Not found error", function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('Not found error', function () { + before(() => { + process.env['TEST_RUN'] = '1'; }); - it( "Checks for not found error", function (done) { - request( server.SERVER ) - .get( '/not/found' ) - .expect( 404 ) - .expect( 'content-type', /html/ ) - .end( (err, res) => { - if(err) throw err; + it('Checks for not found error', function (done) { + request(server.SERVER) + .get('/not/found') + .expect(404) + .expect('content-type', /html/) + .end((err, res) => { + if (err) throw err; done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; }); }); diff --git a/test/password-add-new.ts b/test/password-add-new.ts index 6a266f8..f9657a6 100644 --- a/test/password-add-new.ts +++ b/test/password-add-new.ts @@ -1,38 +1,39 @@ -import * as assert from "assert"; -import * as plaintext from "../src/password/plaintext"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as plaintext from '../src/password/plaintext'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Add new user", function () { +describe('Add new user', function () { let checker: passwd.Checker; - let user = "test@example.com"; - let pass = "foobar123"; - let checker_str = "terribadplaintext"; + let user = 'test@example.com'; + let pass = 'foobar123'; + let checker_str = 'terribadplaintext'; - before( (done) => { - let db = new mock_db.MockDB( null, {} ); - checker = new passwd.Checker( checker_str, db ); + before(done => { + let db = new mock_db.MockDB(null, {}); + checker = new passwd.Checker(checker_str, db); done(); }); - it( "adds a new user and checks for successful match", function (done) { - checker.addNewUser( user, pass - ,() => { + it('adds a new user and checks for successful match', function (done) { + checker.addNewUser( + user, + pass, + () => { checker.isMatch({ - username: user - ,passwd: pass - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: user, + passwd: pass, + is_match_callback: () => { + assert(true, 'Password matched'); done(); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); - } - ,(err) => done( err ) + }, + err => done(err), ); }); }); diff --git a/test/password-argon2.ts b/test/password-argon2.ts index 4a353f3..510e554 100644 --- a/test/password-argon2.ts +++ b/test/password-argon2.ts @@ -1,58 +1,55 @@ -import * as assert from "assert"; -import * as argon2 from "../src/password/argon2"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as argon2 from '../src/password/argon2'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Check a password encrypted with argon2", function () { +describe('Check a password encrypted with argon2', function () { let checker: passwd.Checker; - let good_password = "foobar123"; - let bad_password = "barfoo123"; - let checker_str = "argon2_32_3_4096_1"; + let good_password = 'foobar123'; + let bad_password = 'barfoo123'; + let checker_str = 'argon2_32_3_4096_1'; - before( (done) => { - let crypter = new argon2.Argon2( [ "32", "3", "4096", "1" ] ); + before(done => { + let crypter = new argon2.Argon2(['32', '3', '4096', '1']); - crypter.crypt( good_password, Buffer.from('') - ,(crypted_good_passwd) => { - let db = new mock_db.MockDB( null, { - "test@example.com": { - password: crypted_good_passwd - ,crypt_type: checker_str - } - }); - checker = new passwd.Checker( checker_str, db ); - done(); - } - ); + crypter.crypt(good_password, Buffer.from(''), crypted_good_passwd => { + let db = new mock_db.MockDB(null, { + 'test@example.com': { + password: crypted_good_passwd, + crypt_type: checker_str, + }, + }); + checker = new passwd.Checker(checker_str, db); + done(); + }); }); - it( "Checks good password with argon2", function (done) { + it('Checks good password with argon2', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert(true, 'Password matched'); done(); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); }); - it( "Checks bad password with argon2", function (done) { + it('Checks bad password with argon2', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: bad_password - ,is_match_callback: () => { - assert( false, "Password not matched" ); + username: 'test@example.com', + passwd: bad_password, + is_match_callback: () => { + assert(false, 'Password not matched'); done(); - } - ,is_not_match_callback: () => { - assert( true, "Password not matched" ); + }, + is_not_match_callback: () => { + assert(true, 'Password not matched'); done(); - } + }, }); }); }); diff --git a/test/password-bcrypt.ts b/test/password-bcrypt.ts index 211e0f5..0952887 100644 --- a/test/password-bcrypt.ts +++ b/test/password-bcrypt.ts @@ -1,57 +1,54 @@ -import * as assert from "assert"; -import * as bcrypt from "../src/password/bcrypt"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as bcrypt from '../src/password/bcrypt'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Check a password encrypted with bcrypt", function () { +describe('Check a password encrypted with bcrypt', function () { let checker: passwd.Checker; - let good_password = "foobar123"; - let bad_password = "barfoo123"; - let checker_str = "bcrypt_10"; + let good_password = 'foobar123'; + let bad_password = 'barfoo123'; + let checker_str = 'bcrypt_10'; - before( (done) => { - let crypter = new bcrypt.BCrypt( ["10"] ); - crypter.crypt( good_password, Buffer.from('') - ,(crypted_good_passwd) => { - let db = new mock_db.MockDB( null, { - "test@example.com": { - password: crypted_good_passwd - ,crypt_type: checker_str - } - }); - checker = new passwd.Checker( checker_str, db ); - done(); - } - ); + before(done => { + let crypter = new bcrypt.BCrypt(['10']); + crypter.crypt(good_password, Buffer.from(''), crypted_good_passwd => { + let db = new mock_db.MockDB(null, { + 'test@example.com': { + password: crypted_good_passwd, + crypt_type: checker_str, + }, + }); + checker = new passwd.Checker(checker_str, db); + done(); + }); }); - it( "Checks good password with bcrypt", function (done) { + it('Checks good password with bcrypt', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert(true, 'Password matched'); done(); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); }); - it( "Checks bad password with bcrypt", function (done) { + it('Checks bad password with bcrypt', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: bad_password - ,is_match_callback: () => { - assert( false, "Password not matched" ); + username: 'test@example.com', + passwd: bad_password, + is_match_callback: () => { + assert(false, 'Password not matched'); done(); - } - ,is_not_match_callback: () => { - assert( true, "Password not matched" ); + }, + is_not_match_callback: () => { + assert(true, 'Password not matched'); done(); - } + }, }); }); }); diff --git a/test/password-change-type.ts b/test/password-change-type.ts index 8ec782f..a7a525b 100644 --- a/test/password-change-type.ts +++ b/test/password-change-type.ts @@ -1,78 +1,85 @@ -import * as assert from "assert"; -import * as scrypt from "../src/password/scrypt"; -import * as db from "../src/db"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as scrypt from '../src/password/scrypt'; +import * as db from '../src/db'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Password crypt type changes on the fly", function () { +describe('Password crypt type changes on the fly', function () { let checker: passwd.Checker; - let good_password = "foobar123"; - let checker_str = "bcrypt_10"; - let stored_checker_str = "scrypt_16384_8_1"; + let good_password = 'foobar123'; + let checker_str = 'bcrypt_10'; + let stored_checker_str = 'scrypt_16384_8_1'; let db: db.DB; - before( (done) => { - let crypter = new scrypt.SCrypt( [ "16384", "8", "1" ] ); + before(done => { + let crypter = new scrypt.SCrypt(['16384', '8', '1']); let salt = passwd.make_salt(); - let crypted_good_passwd = crypter.crypt( good_password, salt - ,(crypted_good_passwd) => { - db = new mock_db.MockDB( null, { - "test@example.com": { - password: crypted_good_passwd - ,crypt_type: stored_checker_str - ,salt: salt.toString( 'hex' ) - } + let crypted_good_passwd = crypter.crypt( + good_password, + salt, + crypted_good_passwd => { + db = new mock_db.MockDB(null, { + 'test@example.com': { + password: crypted_good_passwd, + crypt_type: stored_checker_str, + salt: salt.toString('hex'), + }, }); - checker = new passwd.Checker( checker_str, db ); + checker = new passwd.Checker(checker_str, db); done(); - } + }, ); }); - it( "Checks password with scrypt, rencrypts with bcrypt", function (done) { + it('Checks password with scrypt, rencrypts with bcrypt', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert(true, 'Password matched'); - db.get_password_data_for_user( "test@example.com" - ,( stored_data ) => { - assert.strictEqual( stored_data.crypt_type - ,checker_str - ,"Crypt type was correctly changed" + db.get_password_data_for_user( + 'test@example.com', + stored_data => { + assert.strictEqual( + stored_data.crypt_type, + checker_str, + 'Crypt type was correctly changed', ); checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, - "Password still matched after change" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert( + true, + 'Password still matched after change', + ); done(); - } - ,is_not_match_callback: () => { - assert( false, - "Password did not match after change" ); + }, + is_not_match_callback: () => { + assert( + false, + 'Password did not match after change', + ); done(); - } + }, }); - } - ,() => { - assert( false, "Somehow, user wasn't found?" ); + }, + () => { + assert(false, "Somehow, user wasn't found?"); done(); - } - ,(err) => { + }, + err => { throw err; done(); - } + }, ); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); }); }); diff --git a/test/password-plaintext.ts b/test/password-plaintext.ts index 81b1c3f..4fbb645 100644 --- a/test/password-plaintext.ts +++ b/test/password-plaintext.ts @@ -1,57 +1,54 @@ -import * as assert from "assert"; -import * as plaintext from "../src/password/plaintext"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as plaintext from '../src/password/plaintext'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Check a password in plaintext", function () { +describe('Check a password in plaintext', function () { let checker: passwd.Checker; - let good_password = "foobar123"; - let bad_password = "barfoo123"; - let checker_str = "terribadplaintext"; + let good_password = 'foobar123'; + let bad_password = 'barfoo123'; + let checker_str = 'terribadplaintext'; - before( (done) => { - let crypter = new plaintext.Plaintext( [] ); - crypter.crypt( good_password, Buffer.from('') - ,(crypted_good_passwd) => { - let db = new mock_db.MockDB( null, { - "test@example.com": { - password: crypted_good_passwd - ,crypt_type: checker_str - } - }); - checker = new passwd.Checker( checker_str, db ); - done(); - } - ); + before(done => { + let crypter = new plaintext.Plaintext([]); + crypter.crypt(good_password, Buffer.from(''), crypted_good_passwd => { + let db = new mock_db.MockDB(null, { + 'test@example.com': { + password: crypted_good_passwd, + crypt_type: checker_str, + }, + }); + checker = new passwd.Checker(checker_str, db); + done(); + }); }); - it( "Checks good password with plaintext", function (done) { + it('Checks good password with plaintext', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert(true, 'Password matched'); done(); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); }); - it( "Checks bad password with plaintext", function (done) { + it('Checks bad password with plaintext', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: bad_password - ,is_match_callback: () => { - assert( false, "Password not matched" ); + username: 'test@example.com', + passwd: bad_password, + is_match_callback: () => { + assert(false, 'Password not matched'); done(); - } - ,is_not_match_callback: () => { - assert( true, "Password not matched" ); + }, + is_not_match_callback: () => { + assert(true, 'Password not matched'); done(); - } + }, }); }); }); diff --git a/test/password-scrypt.ts b/test/password-scrypt.ts index 475f65e..a428652 100644 --- a/test/password-scrypt.ts +++ b/test/password-scrypt.ts @@ -1,60 +1,57 @@ -import * as assert from "assert"; -import * as scrypt from "../src/password/scrypt"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as scrypt from '../src/password/scrypt'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "Check a password encrypted with scrypt", function () { +describe('Check a password encrypted with scrypt', function () { let checker: passwd.Checker; - let good_password = "foobar123"; - let bad_password = "barfoo123"; - let checker_str = "scrypt_16384_8_1"; + let good_password = 'foobar123'; + let bad_password = 'barfoo123'; + let checker_str = 'scrypt_16384_8_1'; - before( (done) => { - let crypter = new scrypt.SCrypt( [ "16384", "8", "1" ] ); + before(done => { + let crypter = new scrypt.SCrypt(['16384', '8', '1']); let salt = passwd.make_salt(); - crypter.crypt( good_password, salt - ,(crypted_good_passwd) => { - let db = new mock_db.MockDB( null, { - "test@example.com": { - password: crypted_good_passwd - ,crypt_type: checker_str - ,salt: salt.toString( 'hex' ) - } - }); - checker = new passwd.Checker( checker_str, db ); - done(); - } - ); + crypter.crypt(good_password, salt, crypted_good_passwd => { + let db = new mock_db.MockDB(null, { + 'test@example.com': { + password: crypted_good_passwd, + crypt_type: checker_str, + salt: salt.toString('hex'), + }, + }); + checker = new passwd.Checker(checker_str, db); + done(); + }); }); - it( "Checks good password with scrypt", function (done) { + it('Checks good password with scrypt', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: good_password - ,is_match_callback: () => { - assert( true, "Password matched" ); + username: 'test@example.com', + passwd: good_password, + is_match_callback: () => { + assert(true, 'Password matched'); done(); - } - ,is_not_match_callback: () => { - assert( false, "Password matched" ); + }, + is_not_match_callback: () => { + assert(false, 'Password matched'); done(); - } + }, }); }); - it( "Checks bad password with scrypt", function (done) { + it('Checks bad password with scrypt', function (done) { checker.isMatch({ - username: "test@example.com" - ,passwd: bad_password - ,is_match_callback: () => { - assert( false, "Password not matched" ); + username: 'test@example.com', + passwd: bad_password, + is_match_callback: () => { + assert(false, 'Password not matched'); done(); - } - ,is_not_match_callback: () => { - assert( true, "Password not matched" ); + }, + is_not_match_callback: () => { + assert(true, 'Password not matched'); done(); - } + }, }); }); }); diff --git a/test/pg-add-address.ts b/test/pg-add-address.ts index 452bd3e..7ab5c49 100644 --- a/test/pg-add-address.ts +++ b/test/pg-add-address.ts @@ -1,56 +1,50 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Create address in PostgreSQL', function () { +describe('Create address in PostgreSQL', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Creates address, sets on user', function (done) { - let fetch_address = (member_id) => { + it('Creates address, sets on user', function (done) { + let fetch_address = member_id => { db.get_member_address( - member_id - ,(addr) => { - assert.strictEqual( addr.state, "WI", - "Fetched member address" ); + member_id, + addr => { + assert.strictEqual( + addr.state, + 'WI', + 'Fetched member address', + ); done(); - } - ,error_handler - ,error_handler + }, + error_handler, + error_handler, ); }; - let set_address = (member_id) => { + let set_address = member_id => { db.put_member_address( - member_id - ,{ - address1: "123 Main St" - ,city: "Madison" - ,state: "WI" - ,zip: "53711" - } - ,() => fetch_address( member_id ) - ,error_handler - ,error_handler + member_id, + { + address1: '123 Main St', + city: 'Madison', + state: 'WI', + zip: '53711', + }, + () => fetch_address(member_id), + error_handler, + error_handler, ); }; - db.add_member( - test_member_data() - ,set_address - ,error_handler - ); + db.add_member(test_member_data(), set_address, error_handler); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-add-member.ts b/test/pg-add-member.ts index 148284f..ae6a4f2 100644 --- a/test/pg-add-member.ts +++ b/test/pg-add-member.ts @@ -1,40 +1,35 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Create member in PostgreSQL', function () { +describe('Create member in PostgreSQL', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Adds a member to database', function (done) { - let fetch_member = (member_id) => { - db.get_member( member_id - ,(member) => { - assert.strictEqual( member.firstName, "Foo", - "Fetched member" ); + it('Adds a member to database', function (done) { + let fetch_member = member_id => { + db.get_member( + member_id, + member => { + assert.strictEqual( + member.firstName, + 'Foo', + 'Fetched member', + ); done(); - } - ,error_handler - ,error_handler + }, + error_handler, + error_handler, ); }; - db.add_member( - test_member_data() - ,fetch_member - ,error_handler - ); + db.add_member(test_member_data(), fetch_member, error_handler); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-add-token.ts b/test/pg-add-token.ts index 9fd034e..ff7edca 100644 --- a/test/pg-add-token.ts +++ b/test/pg-add-token.ts @@ -1,78 +1,80 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; import { - error_handler - ,get_pg_connection - ,test_member_data - ,make_secure_token -} from "../src/util"; + error_handler, + get_pg_connection, + test_member_data, + make_secure_token, +} from '../src/util'; - -describe( 'Create token in PostgreSQL', function () { +describe('Create token in PostgreSQL', function () { let db: pg.PG; let token = make_secure_token(); let username = shortid.generate(); - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Adds a token to database', function (done) { + it('Adds a token to database', function (done) { let check_token = () => { - db.is_token_allowed( token - ,() => { - assert( true, "Token is allowed through" ); + db.is_token_allowed( + token, + () => { + assert(true, 'Token is allowed through'); done(); - } - ,() => { - done( new Error( "token was not allowed" ) ); - } - ,error_handler + }, + () => { + done(new Error('token was not allowed')); + }, + error_handler, ); }; let create_token = () => { - db.add_token( username - ,token - ,"" - ,"" - ,() => { - assert( true, "Token created" ); + db.add_token( + username, + token, + '', + '', + () => { + assert(true, 'Token created'); check_token(); - } - ,() => { - done( new Error( "User " + username + " was not found" ) ); - } - ,error_handler + }, + () => { + done(new Error('User ' + username + ' was not found')); + }, + error_handler, ); }; let create_user = () => { db.add_user( - username - ,"Foobar123" - ,"1234" - ,"plaintext-test" - ,create_token - ,error_handler + username, + 'Foobar123', + '1234', + 'plaintext-test', + create_token, + error_handler, ); }; - db.is_token_allowed( token - ,() => { - assert( false, "Token was allowed through, but shouldn't" ); + db.is_token_allowed( + token, + () => { + assert(false, "Token was allowed through, but shouldn't"); done(); - } - ,() => { - assert( true, "Token was not allowed, correctly" ); + }, + () => { + assert(true, 'Token was not allowed, correctly'); create_user(); - } - ,error_handler + }, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-add-wild-apricot.ts b/test/pg-add-wild-apricot.ts index d2c38f8..8994249 100644 --- a/test/pg-add-wild-apricot.ts +++ b/test/pg-add-wild-apricot.ts @@ -1,54 +1,48 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Set Wild Apricot ID in PostgreSQL', function () { +describe('Set Wild Apricot ID in PostgreSQL', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Sets Wild Apricot ID on user', function (done) { + it('Sets Wild Apricot ID on user', function (done) { let id = shortid.generate(); - let fetch_wa = (member_id) => { + let fetch_wa = member_id => { db.get_member_wild_apricot( - member_id - ,(wild_apricot_id) => { - assert.strictEqual( wild_apricot_id, id, - "Fetched member wild apricot ID" ); + member_id, + wild_apricot_id => { + assert.strictEqual( + wild_apricot_id, + id, + 'Fetched member wild apricot ID', + ); done(); - } - ,() => error_handler( new Error( "No member found" ) ) - ,error_handler + }, + () => error_handler(new Error('No member found')), + error_handler, ); }; - let set_wa = (member_id) => { + let set_wa = member_id => { db.put_member_wild_apricot( - member_id - ,id - ,() => fetch_wa( member_id ) - ,() => error_handler( new Error( "No member found" ) ) - ,error_handler + member_id, + id, + () => fetch_wa(member_id), + () => error_handler(new Error('No member found')), + error_handler, ); }; - db.add_member( - test_member_data() - ,set_wa - ,error_handler - ); + db.add_member(test_member_data(), set_wa, error_handler); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-dump-rfid.ts b/test/pg-dump-rfid.ts index 5f8529c..613d532 100644 --- a/test/pg-dump-rfid.ts +++ b/test/pg-dump-rfid.ts @@ -1,52 +1,46 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Dumps all RFIDs', function () { +describe('Dumps all RFIDs', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'dumps the RFID database', function (done) { + it('dumps the RFID database', function (done) { let start_rfid = shortid.generate(); let check_rfid_dump = () => { - db.rfid_dump( - ( dump ) => { - assert( dump[start_rfid], "RFID found" - + " (" + start_rfid + ")" ); - done(); - } - ,error_handler - ); + db.rfid_dump(dump => { + assert( + dump[start_rfid], + 'RFID found' + ' (' + start_rfid + ')', + ); + done(); + }, error_handler); }; - let activate_member = (member_id) => { + let activate_member = member_id => { db.set_member_is_active( - member_id - ,true - ,() => check_rfid_dump() - ,error_handler - ,error_handler + member_id, + true, + () => check_rfid_dump(), + error_handler, + error_handler, ); }; db.add_member( - test_member_data( start_rfid ) - ,activate_member - ,error_handler + test_member_data(start_rfid), + activate_member, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-get-members.ts b/test/pg-get-members.ts index 9e90d77..0a8d90e 100644 --- a/test/pg-get-members.ts +++ b/test/pg-get-members.ts @@ -1,46 +1,40 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Fetch all members', function () { +describe('Fetch all members', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'fetches members', function (done) { + it('fetches members', function (done) { let start_rfid = shortid.generate(); - let run_get_members = (member_id) => { + let run_get_members = member_id => { db.get_members( - 0 - ,10 - ,( members ) => { - assert( members.length > 0, "Fetched members" ); - assert( members.length <= 10, - "Didn't get too many members" ); + 0, + 10, + members => { + assert(members.length > 0, 'Fetched members'); + assert(members.length <= 10, "Didn't get too many members"); done(); - } - ,error_handler + }, + error_handler, ); }; // If this is a new run, ensure there is at least one member in there db.add_member( - test_member_data( start_rfid ) - ,run_get_members - ,error_handler + test_member_data(start_rfid), + run_get_members, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-log-rfid.ts b/test/pg-log-rfid.ts index 1e1e1a3..b5cd247 100644 --- a/test/pg-log-rfid.ts +++ b/test/pg-log-rfid.ts @@ -1,54 +1,49 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Logs an RFID entry', function () { +describe('Logs an RFID entry', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Logs an RFID entry', function (done) { + it('Logs an RFID entry', function (done) { let rfid = shortid.generate(); db.add_member( - test_member_data( rfid ) - ,(member_id) => { + test_member_data(rfid), + member_id => { db.log_rfid_entry( - rfid - ,true - ,() => { - assert( true, "Logged entry" ); + rfid, + true, + () => { + assert(true, 'Logged entry'); done(); - } - ,error_handler + }, + error_handler, ); - - } - ,error_handler + }, + error_handler, ); - }); - it( 'Fetches RFID logs', function (done) { - db.get_rfid_log( 0, 10 - ,(logs) => { - assert( logs.length, "Fetched RFID log" ); - assert( logs.length <= 10, "Didn't get too many" ); + it('Fetches RFID logs', function (done) { + db.get_rfid_log( + 0, + 10, + logs => { + assert(logs.length, 'Fetched RFID log'); + assert(logs.length <= 10, "Didn't get too many"); done(); - } - ,error_handler + }, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-set-active.ts b/test/pg-set-active.ts index 5311de4..73ca0e5 100644 --- a/test/pg-set-active.ts +++ b/test/pg-set-active.ts @@ -1,87 +1,78 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Changes member status setting', function () { +describe('Changes member status setting', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Flips member from active to inactive and back again', function (done) { + it('Flips member from active to inactive and back again', function (done) { // We could shorten the change_status_active()/change_status_inactive() // etc. pairs by going deeper into abstract functions, but I think it's // easier to read and follow if we break it out this way. - let final_check_status_inactive = (member_id) => { + let final_check_status_inactive = member_id => { db.get_member_is_active( - member_id - ,(is_active) => { - assert(! is_active, "Member flipped back to inactive" ); + member_id, + is_active => { + assert(!is_active, 'Member flipped back to inactive'); done(); - } - ,error_handler - ,error_handler + }, + error_handler, + error_handler, ); }; - let change_status_inactive = (member_id) => { + let change_status_inactive = member_id => { db.set_member_is_active( - member_id - ,false - ,() => final_check_status_inactive(member_id) - ,error_handler - ,error_handler + member_id, + false, + () => final_check_status_inactive(member_id), + error_handler, + error_handler, ); }; - let check_status_active = (member_id) => { + let check_status_active = member_id => { db.get_member_is_active( - member_id - ,(is_active) => { - assert( is_active, "Member changed to active" ); - change_status_inactive( member_id ); - } - ,error_handler - ,error_handler + member_id, + is_active => { + assert(is_active, 'Member changed to active'); + change_status_inactive(member_id); + }, + error_handler, + error_handler, ); }; - let change_status_active = (member_id) => { + let change_status_active = member_id => { db.set_member_is_active( - member_id - ,true - ,() => check_status_active(member_id) - ,error_handler - ,error_handler + member_id, + true, + () => check_status_active(member_id), + error_handler, + error_handler, ); }; - let check_status_inactive = (member_id) => { + let check_status_inactive = member_id => { db.get_member_is_active( - member_id - ,(is_active) => { - assert(! is_active, "Member starts as inactive" ); - change_status_active( member_id ); - } - ,error_handler - ,error_handler + member_id, + is_active => { + assert(!is_active, 'Member starts as inactive'); + change_status_active(member_id); + }, + error_handler, + error_handler, ); }; - db.add_member( - test_member_data() - ,check_status_inactive - ,error_handler - ); + db.add_member(test_member_data(), check_status_inactive, error_handler); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-set-password.ts b/test/pg-set-password.ts index 4d975ca..3f872e7 100644 --- a/test/pg-set-password.ts +++ b/test/pg-set-password.ts @@ -1,90 +1,98 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Changes password data', function () { +describe('Changes password data', function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Adds user, checks password, changes password', function (done) { + it('Adds user, checks password, changes password', function (done) { let username = shortid.generate(); - let start_password = "foo123"; - let finish_password = "bar321"; - let salt = "1234"; - let crypt_type = "plaintext-test"; + let start_password = 'foo123'; + let finish_password = 'bar321'; + let salt = '1234'; + let crypt_type = 'plaintext-test'; let check_user_finish = () => { db.get_password_data_for_user( - username - ,(data) => { - assert.strictEqual( data.password, finish_password, - "Password changed" ); - assert.strictEqual( data.salt, salt, - "Salt set" ); - assert.strictEqual( data.crypt_type, crypt_type, - "Crypt type set" ); + username, + data => { + assert.strictEqual( + data.password, + finish_password, + 'Password changed', + ); + assert.strictEqual(data.salt, salt, 'Salt set'); + assert.strictEqual( + data.crypt_type, + crypt_type, + 'Crypt type set', + ); done(); - } - ,() => error_handler( new Error( - "No user found when we should have" - ) ) - ,error_handler + }, + () => + error_handler( + new Error('No user found when we should have'), + ), + error_handler, ); }; let change_user_password = () => { db.set_password_data_for_user( - username - ,finish_password - ,crypt_type - ,salt - ,check_user_finish - ,() => error_handler( new Error( - "No user found when we should have" - ) ) - ,error_handler + username, + finish_password, + crypt_type, + salt, + check_user_finish, + () => + error_handler( + new Error('No user found when we should have'), + ), + error_handler, ); }; let check_user_start = () => { db.get_password_data_for_user( - username - ,(data) => { - assert.strictEqual( data.password, start_password, - "Password set" ); - assert.strictEqual( data.salt, salt, - "Salt set" ); - assert.strictEqual( data.crypt_type, crypt_type, - "Crypt type set" ); + username, + data => { + assert.strictEqual( + data.password, + start_password, + 'Password set', + ); + assert.strictEqual(data.salt, salt, 'Salt set'); + assert.strictEqual( + data.crypt_type, + crypt_type, + 'Crypt type set', + ); change_user_password(); - } - ,() => error_handler( new Error( - "No user found when we should have" - ) ) - ,error_handler + }, + () => + error_handler( + new Error('No user found when we should have'), + ), + error_handler, ); }; db.add_user( - username - ,start_password - ,salt - ,crypt_type - ,check_user_start - ,error_handler + username, + start_password, + salt, + crypt_type, + check_user_start, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-set-photo.ts b/test/pg-set-photo.ts index 1fde523..518bddd 100644 --- a/test/pg-set-photo.ts +++ b/test/pg-set-photo.ts @@ -1,60 +1,52 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; +const PHOTO_PATH = 'foobar'; -const PHOTO_PATH = "foobar"; - - -describe( 'Changes a member\'s photo', function () { +describe("Changes a member's photo", function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Adds member, sets photo, checks photo', function (done) { - let check_photo_finish = (member_id) => { + it('Adds member, sets photo, checks photo', function (done) { + let check_photo_finish = member_id => { db.get_member_photo( - member_id - ,(path) => { - assert.strictEqual( path, PHOTO_PATH, "Photo path set" ); + member_id, + path => { + assert.strictEqual(path, PHOTO_PATH, 'Photo path set'); done(); - } - ,() => error_handler( - new Error( "Could not find member ID: " + member_id ) - ) - ,error_handler + }, + () => + error_handler( + new Error('Could not find member ID: ' + member_id), + ), + error_handler, ); }; - let set_new_photo = (member_id) => { + let set_new_photo = member_id => { db.set_member_photo( - member_id - ,PHOTO_PATH - ,() => { - check_photo_finish( member_id ); - } - ,() => error_handler( - new Error( "Could not find member ID: " + member_id ) - ) - ,error_handler + member_id, + PHOTO_PATH, + () => { + check_photo_finish(member_id); + }, + () => + error_handler( + new Error('Could not find member ID: ' + member_id), + ), + error_handler, ); }; - db.add_member( - test_member_data() - ,set_new_photo - ,error_handler - ); + db.add_member(test_member_data(), set_new_photo, error_handler); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/pg-set-rfid.ts b/test/pg-set-rfid.ts index 4688df2..032e195 100644 --- a/test/pg-set-rfid.ts +++ b/test/pg-set-rfid.ts @@ -1,101 +1,97 @@ -import * as assert from "assert"; -import * as pg from "../src/db-pg"; -import * as shortid from "shortid"; -import { - error_handler - ,get_pg_connection - ,test_member_data -} from "../src/util"; +import * as assert from 'assert'; +import * as pg from '../src/db-pg'; +import * as shortid from 'shortid'; +import {error_handler, get_pg_connection, test_member_data} from '../src/util'; - -describe( 'Changes a member\'s RFID', function () { +describe("Changes a member's RFID", function () { let db: pg.PG; - before( () => { + before(() => { db = get_pg_connection(); }); - it( 'Adds member, checks RFID, changes RFID', function (done) { + it('Adds member, checks RFID, changes RFID', function (done) { let start_rfid = shortid.generate(); let change_rfid = shortid.generate(); - let check_old_rfid = (member_id) => { + let check_old_rfid = member_id => { db.get_member_rfid( - start_rfid - ,() => { - assert( false, "Old RFID should no longer exist" ); + start_rfid, + () => { + assert(false, 'Old RFID should no longer exist'); done(); - } - ,() => { - assert( false, "Old RFID should no longer exist" ); + }, + () => { + assert(false, 'Old RFID should no longer exist'); done(); - } - ,() => { - assert( true, "Old RFID should no longer exist" ); + }, + () => { + assert(true, 'Old RFID should no longer exist'); done(); - } - ,error_handler + }, + error_handler, ); }; - let check_rfid_finish = (member_id) => { + let check_rfid_finish = member_id => { db.get_member_rfid( - change_rfid - ,() => { - throw new Error( "RFID active, when it shouldn't be" ); - check_old_rfid( member_id ); - } - ,() => { - assert( true, "RFID was changed" ); - } - ,() => { - throw new Error( "RFID was not found, when it should be" ) - } - ,error_handler + change_rfid, + () => { + throw new Error("RFID active, when it shouldn't be"); + check_old_rfid(member_id); + }, + () => { + assert(true, 'RFID was changed'); + }, + () => { + throw new Error('RFID was not found, when it should be'); + }, + error_handler, ); }; - let set_new_rfid = (member_id) => { + let set_new_rfid = member_id => { db.set_member_rfid( - member_id - ,change_rfid - ,() => { - check_rfid_finish( member_id ); - } - ,() => error_handler( - new Error( "Could not find member ID: " + member_id ) - ) - ,error_handler + member_id, + change_rfid, + () => { + check_rfid_finish(member_id); + }, + () => + error_handler( + new Error('Could not find member ID: ' + member_id), + ), + error_handler, ); }; - let check_rfid_start = (member_id) => { + let check_rfid_start = member_id => { db.get_member_rfid( - start_rfid - ,() => { - throw new Error( "RFID " + start_rfid + " was active" ); - set_new_rfid( member_id ); - } - ,() => { - assert( true, "RFID is inactive to start with" ); + start_rfid, + () => { + throw new Error('RFID ' + start_rfid + ' was active'); + set_new_rfid(member_id); + }, + () => { + assert(true, 'RFID is inactive to start with'); done(); - } - ,() => { - throw new Error( "RFID " + start_rfid + " was not found" ); + }, + () => { + throw new Error('RFID ' + start_rfid + ' was not found'); done(); - } - ,error_handler + }, + error_handler, ); }; db.add_member( - test_member_data( start_rfid ) - ,check_rfid_start - ,error_handler + test_member_data(start_rfid), + check_rfid_start, + error_handler, ); }); - after( () => { + after(() => { db.end(); }); }); diff --git a/test/rfid-dump.ts b/test/rfid-dump.ts index 27dac34..d2a8070 100644 --- a/test/rfid-dump.ts +++ b/test/rfid-dump.ts @@ -1,59 +1,58 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; +describe('GET /v1/rfids', function () { + before(() => { + process.env['TEST_RUN'] = '1'; -describe( 'GET /v1/rfids', function () { - before( () => { - process.env['TEST_RUN'] = "1"; - - let members = {} - members["01"] = { + let members = {}; + members['01'] = { simple_data: { - rfid: "rfid01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: "foo.bar@example.com" - ,photo: "https://example.com/" - } + rfid: 'rfid01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: 'foo.bar@example.com', + photo: 'https://example.com/', + }, }; - members["02"] = { + members['02'] = { simple_data: { - rfid: "rfid02" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: "foo.bar@example.com" - ,photo: "https://example.com/" - } + rfid: 'rfid02', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: 'foo.bar@example.com', + photo: 'https://example.com/', + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Fetches the RFID dump', function (done) { - request( server.SERVER ) - .get( '/api/v1/rfids' ) + it('Fetches the RFID dump', function (done) { + request(server.SERVER) + .get('/api/v1/rfids') .send() - .expect( 200 ) - .expect( function(res) { + .expect(200) + .expect(function (res) { var data = res.body; - assert( data["rfid01"], "First user is there" ); - assert( data["rfid02"], "Second user is there" ); + assert(data['rfid01'], 'First user is there'); + assert(data['rfid02'], 'Second user is there'); }) - .end( function( err, res ) { - if( err ) done(err); + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/set-member-address.ts b/test/set-member-address.ts index e870f81..b5b6941 100644 --- a/test/set-member-address.ts +++ b/test/set-member-address.ts @@ -1,47 +1,46 @@ -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; - -describe( 'PUT /v1/member/:member_id/address', function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('PUT /v1/member/:member_id/address', function () { + before(() => { + process.env['TEST_RUN'] = '1'; let members = {}; members[uuid] = { simple_data: { - rfid: "01" - ,firstName: "Foo" - ,lastName: "Bar" - ,phone: "15555551234" - ,email: "foo.bar@example.com" - ,photo: "https://example.com/" - } + rfid: '01', + firstName: 'Foo', + lastName: 'Bar', + phone: '15555551234', + email: 'foo.bar@example.com', + photo: 'https://example.com/', + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Sets a member address', function (done) { - request( server.SERVER ) - .put( '/api/v1/member/' + uuid + '/address' ) + it('Sets a member address', function (done) { + request(server.SERVER) + .put('/api/v1/member/' + uuid + '/address') .send({ - name: "Foo Bar" - ,address1: "123 Main St" - ,city: "Madison" - ,state: "WI" - ,zip: "53704" + name: 'Foo Bar', + address1: '123 Main St', + city: 'Madison', + state: 'WI', + zip: '53704', }) - .expect( 204 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(204) + .end(function (err, res) { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/set-member-photos.ts b/test/set-member-photos.ts index e0a2cb6..b4265c9 100644 --- a/test/set-member-photos.ts +++ b/test/set-member-photos.ts @@ -1,66 +1,67 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as fs from "fs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as fs from 'fs'; +import * as mock_db from '../src/db-mock'; -const PHOTO_DIR = "test_data/photos/"; -const TEST_PHOTO = "test_data/bodgery_logo.jpg"; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const PHOTO_DIR = 'test_data/photos/'; +const TEST_PHOTO = 'test_data/bodgery_logo.jpg'; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; - -describe( 'PUT /v1/member/:member_id/photo', function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('PUT /v1/member/:member_id/photo', function () { + before(() => { + process.env['TEST_RUN'] = '1'; let members = {}; members[uuid] = { - photo: null + photo: null, }; let conf = server.default_conf(); conf['photo_dir'] = PHOTO_DIR; - let db = new mock_db.MockDB( [], members ); - return server.start( db, conf ); + let db = new mock_db.MockDB([], members); + return server.start(db, conf); }); - it( 'Sets a member photo', function (done) { + it('Sets a member photo', function (done) { let expected_length = 0; let check_photo = () => { - request( server.SERVER ) - .get( "/api/v1/member/" + uuid + "/photo" ) + request(server.SERVER) + .get('/api/v1/member/' + uuid + '/photo') .send() - .expect( 200 ) - .expect( function( res ) { + .expect(200) + .expect(function (res) { let data = res.body; - assert( data, "Got something back for photo" ); - assert.strictEqual( data.length, expected_length, - "Came back in expected length" ); + assert(data, 'Got something back for photo'); + assert.strictEqual( + data.length, + expected_length, + 'Came back in expected length', + ); }) - .end( function( err, res ) { - if( err ) done( err ); + .end(function (err, res) { + if (err) done(err); else done(); }); }; - fs.readFile( TEST_PHOTO, (err, data) => { - if( err ) done(err); + fs.readFile(TEST_PHOTO, (err, data) => { + if (err) done(err); else { expected_length = data.length; - let encoded_data = data.toString( 'base64' ); + let encoded_data = data.toString('base64'); - request( server.SERVER ) - .put( '/api/v1/member/' + uuid + '/photo' ) - .set( 'Content-Type', 'image/jpeg' ) - .send( encoded_data ) - .expect( 204 ) - .end( function( err, res ) { - if( err ) { + request(server.SERVER) + .put('/api/v1/member/' + uuid + '/photo') + .set('Content-Type', 'image/jpeg') + .send(encoded_data) + .expect(204) + .end(function (err, res) { + if (err) { done(err); - } - else { + } else { check_photo(); } }); @@ -68,34 +69,32 @@ describe( 'PUT /v1/member/:member_id/photo', function () { }); }); - after( () => { + after(() => { let server_promise = server.stop(); delete process.env['TEST_RUN']; // Just delete everything in the test photo dir - let cleanup_promise = new Promise( (resolve, reject) => { - fs.readdir( PHOTO_DIR, (err, files) => { - let promises = files.map( (_) => new Promise( - (resolve, reject) => { - if( _.match( /^\./ ) ) { - // Ignore files beginning with a dot - resolve(); - } - else { - fs.unlink( PHOTO_DIR + "/" + _, (err) => { - if( err ) reject( err ); - else resolve(); - }); - } - }) ); + let cleanup_promise = new Promise((resolve, reject) => { + fs.readdir(PHOTO_DIR, (err, files) => { + let promises = files.map( + _ => + new Promise((resolve, reject) => { + if (_.match(/^\./)) { + // Ignore files beginning with a dot + resolve(); + } else { + fs.unlink(PHOTO_DIR + '/' + _, err => { + if (err) reject(err); + else resolve(); + }); + } + }), + ); - Promise.all( promises ).then( () => resolve() ); + Promise.all(promises).then(() => resolve()); }); }); - return Promise.all([ - server_promise - ,cleanup_promise - ]); + return Promise.all([server_promise, cleanup_promise]); }); }); diff --git a/test/set-member-wild-apricot.ts b/test/set-member-wild-apricot.ts index dd7cbab..8850a1b 100644 --- a/test/set-member-wild-apricot.ts +++ b/test/set-member-wild-apricot.ts @@ -1,45 +1,45 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as funcs from "../src/request_funcs"; -import * as mock_db from "../src/db-mock"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as funcs from '../src/request_funcs'; +import * as mock_db from '../src/db-mock'; -const uuid = "0662df8c-e43a-4e90-8b03-3849afbb533e"; +const uuid = '0662df8c-e43a-4e90-8b03-3849afbb533e'; - -describe( 'PUT /v1/member/:member_id/wildapricot', function () { +describe('PUT /v1/member/:member_id/wildapricot', function () { let members; - before( () => { - process.env['TEST_RUN'] = "1"; + before(() => { + process.env['TEST_RUN'] = '1'; members = {}; members[uuid] = { full_data: { - wild_apricot_id: null - } + wild_apricot_id: null, + }, }; - let db = new mock_db.MockDB( members, {} ); - return server.start( db ); + let db = new mock_db.MockDB(members, {}); + return server.start(db); }); - it( 'Sets a member wild apricot ID', function (done) { - request( server.SERVER ) - .put( '/api/v1/member/' + uuid + '/wildapricot' ) + it('Sets a member wild apricot ID', function (done) { + request(server.SERVER) + .put('/api/v1/member/' + uuid + '/wildapricot') .send({ - wild_apricot_id: "567" + wild_apricot_id: '567', }) - .expect( 204 ) - .end( function( err, res ) { - if( err ) done(err); + .expect(204) + .end(function (err, res) { + if (err) done(err); else { assert.strictEqual( - members[uuid]["full_data"]["wild_apricot_id"], - "567" ); + members[uuid]['full_data']['wild_apricot_id'], + '567', + ); done(); } }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/test/template-preloader.ts b/test/template-preloader.ts index 209b67c..38239d8 100644 --- a/test/template-preloader.ts +++ b/test/template-preloader.ts @@ -1,31 +1,33 @@ -import * as assert from "assert"; -import * as Handlebars from "../src/handlebars-preloader"; +import * as assert from 'assert'; +import * as Handlebars from '../src/handlebars-preloader'; -describe( 'Load templates', () => { - it( 'Loads a template', (done) => { - let tmpl = new Handlebars.handlebars( './test_data/tmpl' ); +describe('Load templates', () => { + it('Loads a template', done => { + let tmpl = new Handlebars.handlebars('./test_data/tmpl'); - tmpl.load( () => { - let text = tmpl.execute( 'foo', { - foo: 1 + tmpl.load(() => { + let text = tmpl.execute('foo', { + foo: 1, }); - assert( text.match( /got 1 for foo/ ), "Set value in template" ); + assert(text.match(/got 1 for foo/), 'Set value in template'); done(); }); }); - it( 'Loads a template, with partials', (done) => { - let tmpl = new Handlebars.handlebars( './test_data/tmpl' ); + it('Loads a template, with partials', done => { + let tmpl = new Handlebars.handlebars('./test_data/tmpl'); - tmpl.load( () => { - let text = tmpl.execute( 'bar', { - foo: 1 - ,bar: 2 + tmpl.load(() => { + let text = tmpl.execute('bar', { + foo: 1, + bar: 2, }); - assert( text.match( /got 1 for foo/ ), "Set value in template" ); - assert( text.match( /got 2 for bar in partial/ ), - "Set value in template in partial" ); + assert(text.match(/got 1 for foo/), 'Set value in template'); + assert( + text.match(/got 2 for bar in partial/), + 'Set value in template in partial', + ); done(); }); }); diff --git a/test/user-authorization-oauth2.ts b/test/user-authorization-oauth2.ts index f4afe1b..1baae7f 100644 --- a/test/user-authorization-oauth2.ts +++ b/test/user-authorization-oauth2.ts @@ -1,36 +1,33 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "User authorization with OAuth2", function () { +describe('User authorization with OAuth2', function () { let db: mock_db.MockDB; - let token = "foobarbaz"; - + let token = 'foobarbaz'; - before( () => { + before(() => { let tokens = {}; tokens[token] = true; - db = new mock_db.MockDB( {}, {}, null, tokens ); + db = new mock_db.MockDB({}, {}, null, tokens); - return server.start( db ); + return server.start(db); }); - - it( 'Sends an OAuth2 token to a secure page', (done) => { - request( server.SERVER ) - .get( '/members/pending' ) - .set( 'Authorization', 'Bearer ' + token ) - .expect( 200 ) - .end( (err, res) => { - if(err) done(err); + it('Sends an OAuth2 token to a secure page', done => { + request(server.SERVER) + .get('/members/pending') + .set('Authorization', 'Bearer ' + token) + .expect(200) + .end((err, res) => { + if (err) done(err); else done(); }); }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/user-authorization.ts b/test/user-authorization.ts index 469bb97..e9addd9 100644 --- a/test/user-authorization.ts +++ b/test/user-authorization.ts @@ -1,96 +1,92 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; - -describe( "User authorization", function () { +describe('User authorization', function () { let db: mock_db.MockDB; - let username = "test@example.com"; - let password = "foobar123"; - let checker_str = "terribadplaintext"; + let username = 'test@example.com'; + let password = 'foobar123'; + let checker_str = 'terribadplaintext'; // Since session cookie is HTTPS-only, need to put this header in to make // server think we're coming from the frontend proxy let trust_header_name = 'X-Forwarded-Proto'; let trust_header_value = 'https'; - - before( () => { + before(() => { let conf = server.default_conf(); conf['preferred_password_crypt_method'] = checker_str; let user_data: any = {}; user_data[username] = { - password: password - ,crypt_type: checker_str + password: password, + crypt_type: checker_str, }; - db = new mock_db.MockDB( null, user_data ); + db = new mock_db.MockDB(null, user_data); - return server.start( db, conf ); + return server.start(db, conf); }); - - it( 'Tries to access a secure page without logging in', (done) => { - request( server.SERVER ) - .get( '/members/pending' ) - .set( trust_header_name, trust_header_value ) - .expect( 401 ) - .end( (err, res) => { - if(err) done(err); + it('Tries to access a secure page without logging in', done => { + request(server.SERVER) + .get('/members/pending') + .set(trust_header_name, trust_header_value) + .expect(401) + .end((err, res) => { + if (err) done(err); else done(); }); }); - it( 'Gets to login page, logs in, then tries to access a secure page', (done) => { + it('Gets to login page, logs in, then tries to access a secure page', done => { let login; let access_pending; let cookie; let start = () => { - request( server.SERVER ) - .get( '/' ) - .set( trust_header_name, trust_header_value ) + request(server.SERVER) + .get('/') + .set(trust_header_name, trust_header_value) .send({ - username: username - ,password: password + username: username, + password: password, }) - .expect( 200 ) - .expect( 'set-cookie', /=/ ) - .end( (err, res) => { - if(err) throw err; - login() + .expect(200) + .expect('set-cookie', /=/) + .end((err, res) => { + if (err) throw err; + login(); }); - }; login = () => { - request( server.SERVER ) - .post( '/user/login' ) - .set( trust_header_name, trust_header_value ) + request(server.SERVER) + .post('/user/login') + .set(trust_header_name, trust_header_value) .send({ - username: username - ,password: password + username: username, + password: password, }) - .expect( 200 ) - .expect( 'set-cookie', /=/ ) - .end( (err, res) => { - if(err) throw err; + .expect(200) + .expect('set-cookie', /=/) + .end((err, res) => { + if (err) throw err; cookie = res.header['set-cookie']; - access_pending() + access_pending(); }); }; access_pending = () => { - request( server.SERVER ) - .get( '/members/pending' ) - .set( trust_header_name, trust_header_value ) - .set( 'Cookie', cookie ) - .expect( 200 ) - .end( (err, res) => { - if(err) done(err); + request(server.SERVER) + .get('/members/pending') + .set(trust_header_name, trust_header_value) + .set('Cookie', cookie) + .expect(200) + .end((err, res) => { + if (err) done(err); else done(); }); }; @@ -98,29 +94,29 @@ describe( "User authorization", function () { start(); }); - it( 'Checks that we can access static css files without logging in', (done) => { - request( server.SERVER ) - .get( '/css/basic.css' ) - .set( trust_header_name, trust_header_value ) - .expect( 200 ) - .end( (err, res) => { - if(err) throw err; + it('Checks that we can access static css files without logging in', done => { + request(server.SERVER) + .get('/css/basic.css') + .set(trust_header_name, trust_header_value) + .expect(200) + .end((err, res) => { + if (err) throw err; else done(); }); }); - it( 'Checks that we can access static js files without logging in', (done) => { - request( server.SERVER ) - .get( '/js/jquery-3.4.1.min.js' ) - .set( trust_header_name, trust_header_value ) - .expect( 200 ) - .end( (err, res) => { - if(err) throw err; + it('Checks that we can access static js files without logging in', done => { + request(server.SERVER) + .get('/js/jquery-3.4.1.min.js') + .set(trust_header_name, trust_header_value) + .expect(200) + .end((err, res) => { + if (err) throw err; else done(); }); }); - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/user-login.ts b/test/user-login.ts index a6073b3..6a790ac 100644 --- a/test/user-login.ts +++ b/test/user-login.ts @@ -1,109 +1,110 @@ -import * as assert from "assert"; -import * as request from "supertest"; -import * as server from "../app"; -import * as bcrypt from "../src/password/bcrypt"; -import * as mock_db from "../src/db-mock"; -import * as passwd from "../src/password"; - - -describe( "User login", function () { +import * as assert from 'assert'; +import * as request from 'supertest'; +import * as server from '../app'; +import * as bcrypt from '../src/password/bcrypt'; +import * as mock_db from '../src/db-mock'; +import * as passwd from '../src/password'; + +describe('User login', function () { let db: mock_db.MockDB; - let good_username = "test@example.com"; - let good_password = "foobar123"; - let bad_username = "foo@example.com"; - let bad_password = "barfoo123"; - let checker_str = "terribadplaintext"; + let good_username = 'test@example.com'; + let good_password = 'foobar123'; + let bad_username = 'foo@example.com'; + let bad_password = 'barfoo123'; + let checker_str = 'terribadplaintext'; // Since session cookie is HTTPS-only, need to put this header in to make // server think we're coming from the frontend proxy let trust_header_name = 'X-Forwarded-Proto'; let trust_header_value = 'https'; - - before( () => { + before(() => { let conf = server.default_conf(); conf['preferred_password_crypt_method'] = checker_str; let user_data: any = {}; user_data[good_username] = { - password: good_password - ,crypt_type: checker_str + password: good_password, + crypt_type: checker_str, }; - db = new mock_db.MockDB( null, user_data ); + db = new mock_db.MockDB(null, user_data); - return server.start( db, conf ); + return server.start(db, conf); }); - it( "Logs a user in", function (done) { + it('Logs a user in', function (done) { let check_final_logged_out, logout, check_is_logged_in, login; let cookie; let start = () => { - request( server.SERVER ) - .get( '/user/is-logged-in' ) - .set( trust_header_name, trust_header_value ) - .expect( 403 ) - .end( (err, res) => { - if(err) throw err; + request(server.SERVER) + .get('/user/is-logged-in') + .set(trust_header_name, trust_header_value) + .expect(403) + .end((err, res) => { + if (err) throw err; login(); }); }; login = () => { - request( server.SERVER ) - .post( '/user/login' ) - .set( trust_header_name, trust_header_value ) + request(server.SERVER) + .post('/user/login') + .set(trust_header_name, trust_header_value) .send({ - username: good_username - ,password: good_password + username: good_username, + password: good_password, }) - .expect( 200 ) - .expect( 'set-cookie', /=/ ) - .end( (err, res) => { - if(err) throw err; + .expect(200) + .expect('set-cookie', /=/) + .end((err, res) => { + if (err) throw err; cookie = res.header['set-cookie']; check_is_logged_in(); }); }; check_is_logged_in = () => { - let req = request( server.SERVER ) - .get( '/user/is-logged-in' ) - .set( trust_header_name, trust_header_value ) - .set( 'Cookie', cookie ) + let req = request(server.SERVER) + .get('/user/is-logged-in') + .set(trust_header_name, trust_header_value) + .set('Cookie', cookie) .send() - .expect( 200 ) - .end( (err, res) => { - if(err) throw err; - assert.strictEqual( res.body.username, good_username - ,"Returned username" ); + .expect(200) + .end((err, res) => { + if (err) throw err; + assert.strictEqual( + res.body.username, + good_username, + 'Returned username', + ); logout(); }); }; logout = () => { - let req = request( server.SERVER ) - .post( '/user/logout' ) - .set( trust_header_name, trust_header_value ) - .set( 'Cookie', cookie ) + let req = request(server.SERVER) + .post('/user/logout') + .set(trust_header_name, trust_header_value) + .set('Cookie', cookie) .send() - .expect( 200 ) - .end( (err, res) => { - if(err) throw err; + .expect(200) + .end((err, res) => { + if (err) throw err; check_final_logged_out(); }); }; check_final_logged_out = () => { - let req = request( server.SERVER ) - .get( '/user/is-logged-in' ) - .set( trust_header_name, trust_header_value ) - .set( 'Cookie', cookie ) + let req = request(server.SERVER) + .get('/user/is-logged-in') + .set(trust_header_name, trust_header_value) + .set('Cookie', cookie) .send() - .expect( 403 ) - .end( (err, res) => { - if(err) throw err; + .expect(403) + .end((err, res) => { + if (err) throw err; done(); }); }; @@ -111,38 +112,37 @@ describe( "User login", function () { start(); }); - it( "Logs in with bad user", function (done) { - request( server.SERVER ) - .post( '/user/login' ) - .set( trust_header_name, trust_header_value ) + it('Logs in with bad user', function (done) { + request(server.SERVER) + .post('/user/login') + .set(trust_header_name, trust_header_value) .send({ - username: bad_username - ,password: good_password + username: bad_username, + password: good_password, }) - .expect( 403 ) - .end( (err, res) => { - if(err) throw err; + .expect(403) + .end((err, res) => { + if (err) throw err; done(); }); }); - it( "Logs in with bad password", function (done) { - request( server.SERVER ) - .post( '/user/login' ) - .set( trust_header_name, trust_header_value ) + it('Logs in with bad password', function (done) { + request(server.SERVER) + .post('/user/login') + .set(trust_header_name, trust_header_value) .send({ - username: good_username - ,password: bad_password + username: good_username, + password: bad_password, }) - .expect( 403 ) - .end( (err, res) => { - if(err) throw err; + .expect(403) + .end((err, res) => { + if (err) throw err; done(); }); }); - - after( () => { + after(() => { return server.stop(); }); }); diff --git a/test/validate-address.ts b/test/validate-address.ts index 2effb84..f58190f 100644 --- a/test/validate-address.ts +++ b/test/validate-address.ts @@ -1,55 +1,50 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate US address', function () { - it( 'is US address', function (done) { +describe('Validate US address', function () { + it('is US address', function (done) { var error; let address = { - address1: "4444 Robertson Rd" - ,address2: "" - ,city: "Madison" - ,state: "WI" - ,zip: "53714" - ,county: "Dane" - ,country: "United States" + address1: '4444 Robertson Rd', + address2: '', + city: 'Madison', + state: 'WI', + zip: '53714', + county: 'Dane', + country: 'United States', }; try { - validation.validate( address, [ - validation.isUSAddress(), - ]); - } - catch(err) { + validation.validate(address, [validation.isUSAddress()]); + } catch (err) { error = err; } - - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not US address', function (done) { + it('is not US address', function (done) { var error; let address = { - address1: "..." - ,address2: "" - ,city: "Madison" - ,state: "WI" - ,zip: "53714" - ,county: "Dane" - ,country: "United States" + address1: '...', + address2: '', + city: 'Madison', + state: 'WI', + zip: '53714', + county: 'Dane', + country: 'United States', }; try { - validation.validate( address, [ - validation.isUSAddress(), - ]); - } - catch (err) { + validation.validate(address, [validation.isUSAddress()]); + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for non-US address" ) ); + if (error) done(); + else + done( + new Error('Validation was supposed to fail for non-US address'), + ); }); }); diff --git a/test/validate-boolean.ts b/test/validate-boolean.ts index 2ac50a1..647283b 100644 --- a/test/validate-boolean.ts +++ b/test/validate-boolean.ts @@ -1,56 +1,50 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate booleans', function () { - it( 'is booleans', function (done) { +describe('Validate booleans', function () { + it('is booleans', function (done) { var error; try { - validation.validate( { value: true }, [ - validation.isBoolean( 'value' ), - ]); - } - catch(err) { + validation.validate({value: true}, [validation.isBoolean('value')]); + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not booleans', function (done) { + it('is not booleans', function (done) { var error; try { - validation.validate( { value: "foo 'bar' baz" }, [ - validation.isBoolean( 'value' ), + validation.validate({value: "foo 'bar' baz"}, [ + validation.isBoolean('value'), ]); - } - catch(err) { + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for booleans" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for booleans')); }); - it( 'is text booleans', function (done) { + it('is text booleans', function (done) { var error; try { - validation.validate( { - value: "true" - ,value2: "false" - }, [ - validation.isBoolean( 'value' ) - ,validation.isBoolean( 'value2' ) - ]); - } - catch(err) { + validation.validate( + { + value: 'true', + value2: 'false', + }, + [validation.isBoolean('value'), validation.isBoolean('value2')], + ); + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); }); diff --git a/test/validate-byte-length.ts b/test/validate-byte-length.ts index c9cef49..6ea6383 100644 --- a/test/validate-byte-length.ts +++ b/test/validate-byte-length.ts @@ -1,27 +1,20 @@ -import * as assert from "assert"; -import * as validation from "../src/validation"; +import * as assert from 'assert'; +import * as validation from '../src/validation'; - -describe( 'Validate byte length', () => { - - it( 'allows limited byte lengths', () => { - validation.validate( "1234", [ - validation.byteLengthLimit( 8 ) - ]); +describe('Validate byte length', () => { + it('allows limited byte lengths', () => { + validation.validate('1234', [validation.byteLengthLimit(8)]); }); - it( 'disallows oversized byte length', () => { + it('disallows oversized byte length', () => { let error = false; try { - validation.validate( "123456789", [ - validation.byteLengthLimit( 8 ) - ]); - } - catch(err) { + validation.validate('123456789', [validation.byteLengthLimit(8)]); + } catch (err) { error = true; } - assert( error, "Threw error when size was too big" ); + assert(error, 'Threw error when size was too big'); }); }); diff --git a/test/validate-email.ts b/test/validate-email.ts index 27aef10..d432560 100644 --- a/test/validate-email.ts +++ b/test/validate-email.ts @@ -1,52 +1,48 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate Email', function () { - it( 'is email', function (done) { +describe('Validate Email', function () { + it('is email', function (done) { var errors = []; [ - "foobar@example.com" - ,"foo.bar@example.com" - ,"foo+bar@example.com" - ].forEach( (val) => { + 'foobar@example.com', + 'foo.bar@example.com', + 'foo+bar@example.com', + ].forEach(val => { try { - validation.validate( { value: val }, [ - validation.isPublicEmail( 'value' ), + validation.validate({value: val}, [ + validation.isPublicEmail('value'), ]); - } - catch(err) { - errors.push( err.toString() ); + } catch (err) { + errors.push(err.toString()); } }); - if( errors.length > 0 ) done( new Error( - errors.map( (val) => "<<" + val + ">>" ).join( " " ) - )); + if (errors.length > 0) + done(new Error(errors.map(val => '<<' + val + '>>').join(' '))); else done(); }); - it( 'is not email', function (done) { + it('is not email', function (done) { let errors = []; let fails = [ - "foobar" - ,"foobar@example" - ,"example.com" - ,"foobar @exaple.com" + 'foobar', + 'foobar@example', + 'example.com', + 'foobar @exaple.com', ]; - fails.forEach( (val) => { + fails.forEach(val => { try { - validation.validate( { value: val }, [ - validation.isPublicEmail( 'value' ), + validation.validate({value: val}, [ + validation.isPublicEmail('value'), ]); - } - catch(err) { - errors.push( err ); + } catch (err) { + errors.push(err); } }); - if( errors.length == fails.length) done(); - else done( new Error( "Validation was supposed to fail for email" )); + if (errors.length == fails.length) done(); + else done(new Error('Validation was supposed to fail for email')); }); }); diff --git a/test/validate-int.ts b/test/validate-int.ts index 63ca315..7b65650 100644 --- a/test/validate-int.ts +++ b/test/validate-int.ts @@ -1,37 +1,31 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate numbers', function () { - it( 'is integer', function (done) { +describe('Validate numbers', function () { + it('is integer', function (done) { var error; try { - validation.validate( { value: 1234 }, [ - validation.isInteger( 'value' ), - ]); - } - catch(err) { + validation.validate({value: 1234}, [validation.isInteger('value')]); + } catch (err) { error = err; } - - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not integer', function (done) { + it('is not integer', function (done) { var error; try { - validation.validate( { value: "foobar" }, [ - validation.isInteger( 'value' ), + validation.validate({value: 'foobar'}, [ + validation.isInteger('value'), ]); - } - catch (err) { + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for integer" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for integer')); }); }); diff --git a/test/validate-name.ts b/test/validate-name.ts index 2f49549..894873c 100644 --- a/test/validate-name.ts +++ b/test/validate-name.ts @@ -1,36 +1,29 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate name', function () { - it( 'is a name', function (done) { +describe('Validate name', function () { + it('is a name', function (done) { var error; try { - validation.validate( { value: "foo1" }, [ - validation.isName( 'value' ), - ]); - } - catch(err) { + validation.validate({value: 'foo1'}, [validation.isName('value')]); + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not a name', function (done) { + it('is not a name', function (done) { var error; try { - validation.validate( { value: "*&^&" }, [ - validation.isName( 'value' ), - ]); - } - catch(err) { + validation.validate({value: '*&^&'}, [validation.isName('value')]); + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for name" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for name')); }); }); diff --git a/test/validate-phone.ts b/test/validate-phone.ts index 688a47c..ee4be4e 100644 --- a/test/validate-phone.ts +++ b/test/validate-phone.ts @@ -1,57 +1,49 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate US phone', function () { - it( 'is US phone', function (done) { +describe('Validate US phone', function () { + it('is US phone', function (done) { var errors = []; [ - "15555552222" - ,"5552222" - ,"5555552222" - ,"1-555-555-2222" - ,"555-2222" - ,"555-555-2222" - ,"1 555 555 2222" - ,"555 2222" - ,"555 555 2222" - ].forEach( (val) => { + '15555552222', + '5552222', + '5555552222', + '1-555-555-2222', + '555-2222', + '555-555-2222', + '1 555 555 2222', + '555 2222', + '555 555 2222', + ].forEach(val => { try { - validation.validate( { value: val }, [ - validation.isUSPhone( 'value' ), + validation.validate({value: val}, [ + validation.isUSPhone('value'), ]); - } - catch(err) { - errors.push( err.toString() ); + } catch (err) { + errors.push(err.toString()); } }); - if( errors.length > 0 ) done( new Error( - errors.map( (val) => "<<" + val + ">>" ).join( " " ) - )); + if (errors.length > 0) + done(new Error(errors.map(val => '<<' + val + '>>').join(' '))); else done(); }); - it( 'is not US phone', function (done) { + it('is not US phone', function (done) { var errors = []; - var fails = [ - "25552222" - ,"foo bar" - ,"155555522221" - ]; + var fails = ['25552222', 'foo bar', '155555522221']; - fails.forEach( (val) => { + fails.forEach(val => { try { - validation.validate( { value: val }, [ - validation.isUSPhone( 'value' ), + validation.validate({value: val}, [ + validation.isUSPhone('value'), ]); - } - catch(err) { - errors.push( err ); + } catch (err) { + errors.push(err); } }); - if( errors.length == fails.length) done(); - else done( new Error( "Validation was supposed to fail for US phone" )); + if (errors.length == fails.length) done(); + else done(new Error('Validation was supposed to fail for US phone')); }); }); diff --git a/test/validate-url.ts b/test/validate-url.ts index 75f8d43..ce4d8c6 100644 --- a/test/validate-url.ts +++ b/test/validate-url.ts @@ -1,36 +1,33 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate URL', function () { - it( 'is URL', function (done) { +describe('Validate URL', function () { + it('is URL', function (done) { var error; try { - validation.validate( { value: "http://example.com" }, [ - validation.isUrl( 'value' ), + validation.validate({value: 'http://example.com'}, [ + validation.isUrl('value'), ]); - } - catch(err) { + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not URL', function (done) { + it('is not URL', function (done) { var error; try { - validation.validate( { value: "foo 'bar' baz" }, [ - validation.isUrl( 'value' ), + validation.validate({value: "foo 'bar' baz"}, [ + validation.isUrl('value'), ]); - } - catch(err) { + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for url" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for url')); }); }); diff --git a/test/validate-uuid.ts b/test/validate-uuid.ts index 98e17f3..f58429f 100644 --- a/test/validate-uuid.ts +++ b/test/validate-uuid.ts @@ -1,36 +1,32 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate UUID', function () { - it( 'is a uuid', function (done) { +describe('Validate UUID', function () { + it('is a uuid', function (done) { var error; try { - validation.validate( { value: "c56a4180-65aa-42ec-a945-5fd21dec0538" }, [ - validation.isUUID( 'value' ), - ]); - } - catch(err) { + validation.validate( + {value: 'c56a4180-65aa-42ec-a945-5fd21dec0538'}, + [validation.isUUID('value')], + ); + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not a uuid', function (done) { + it('is not a uuid', function (done) { var error; try { - validation.validate( { value: "*&^&" }, [ - validation.isUUID( 'value' ), - ]); - } - catch(err) { + validation.validate({value: '*&^&'}, [validation.isUUID('value')]); + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for uuid" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for uuid')); }); }); diff --git a/test/validate-words.ts b/test/validate-words.ts index 46e4c76..7124741 100644 --- a/test/validate-words.ts +++ b/test/validate-words.ts @@ -1,36 +1,33 @@ -var validation = require( '../src/validation.ts' ); +var validation = require('../src/validation.ts'); - -describe( 'Validate words', function () { - it( 'is words', function (done) { +describe('Validate words', function () { + it('is words', function (done) { var error; try { - validation.validate( { value: "foo bar 123" }, [ - validation.isWords( 'value' ), + validation.validate({value: 'foo bar 123'}, [ + validation.isWords('value'), ]); - } - catch(err) { + } catch (err) { error = err; } - if( error ) done( error ); + if (error) done(error); else done(); }); - it( 'is not words', function (done) { + it('is not words', function (done) { var error; try { - validation.validate( { value: "foo 'bar' baz" }, [ - validation.isWords( 'value' ), + validation.validate({value: "foo 'bar' baz"}, [ + validation.isWords('value'), ]); - } - catch(err) { + } catch (err) { error = err; } - if( error ) done(); - else done( new Error( "Validation was supposed to fail for words" ) ); + if (error) done(); + else done(new Error('Validation was supposed to fail for words')); }); }); diff --git a/test/versions.ts b/test/versions.ts index 77d3b47..dab79db 100644 --- a/test/versions.ts +++ b/test/versions.ts @@ -1,31 +1,30 @@ -import * as request from "supertest"; -import * as server from "../app"; +import * as request from 'supertest'; +import * as server from '../app'; - -describe( 'Returns version list', function () { - before( () => { - process.env['TEST_RUN'] = "1"; +describe('Returns version list', function () { + before(() => { + process.env['TEST_RUN'] = '1'; return server.start(); }); - it( 'Gets versions', function (done) { - request( server.SERVER ) - .get( '/api/' ) - .expect( 200 ) - .expect( 'Content-Type', /json/ ) - .expect( function(res) { + it('Gets versions', function (done) { + request(server.SERVER) + .get('/api/') + .expect(200) + .expect('Content-Type', /json/) + .expect(function (res) { var data = res.body; - if(! Array.isArray( data ) ) - throw new Error( "Didn't return array" ); - if( "/v1" != data[0] ) throw new Error( "Doesn't list v1" ); + if (!Array.isArray(data)) + throw new Error("Didn't return array"); + if ('/v1' != data[0]) throw new Error("Doesn't list v1"); }) - .end( function( err, res ) { - if( err ) return done(err); + .end(function (err, res) { + if (err) return done(err); done(); }); }); - after( () => { + after(() => { delete process.env['TEST_RUN']; return server.stop(); }); diff --git a/util/add_user.ts b/util/add_user.ts index 58d006b..201d867 100644 --- a/util/add_user.ts +++ b/util/add_user.ts @@ -1,43 +1,43 @@ -import * as app from "../app"; -import * as db_impl from "../src/db"; -import * as fs from "fs"; -import config from "../src/config"; -import * as password from "../src/password"; -import * as pg from "../src/db-pg"; -import * as prompt from "password-prompt"; -import * as readline from "readline"; -import * as yaml from "js-yaml"; - +import * as app from '../app'; +import * as db_impl from '../src/db'; +import * as fs from 'fs'; +import config from '../src/config'; +import * as password from '../src/password'; +import * as pg from '../src/db-pg'; +import * as prompt from 'password-prompt'; +import * as readline from 'readline'; +import * as yaml from 'js-yaml'; const conf = config(); const ui = readline.createInterface({ - input: process.stdin - ,output: process.stdout + input: process.stdin, + output: process.stdout, }); const db: db_impl.DB = new pg.PG( - conf.db_host - ,conf.db_port - ,conf.db_name - ,conf.db_user - ,conf.db_password + conf.db_host, + conf.db_port, + conf.db_name, + conf.db_user, + conf.db_password, ); const password_handler = new password.Checker( - conf['preferred_password_crypt_method'] - ,db + conf['preferred_password_crypt_method'], + db, ); - -ui.question( "Username: ", (user) => { +ui.question('Username: ', user => { ui.close(); - prompt( "Password: ", { - method: "hide" - }).then( (pass) => password_handler.addNewUser( - user - ,pass - ,() => {} - ,(err) => { - throw err; - } - ) ); + prompt('Password: ', { + method: 'hide', + }).then(pass => + password_handler.addNewUser( + user, + pass, + () => {}, + err => { + throw err; + }, + ), + ); }); diff --git a/util/dump_wa_member.ts b/util/dump_wa_member.ts index 2fd37d1..a5e8d27 100644 --- a/util/dump_wa_member.ts +++ b/util/dump_wa_member.ts @@ -1,27 +1,26 @@ -import * as fs from "fs"; -import config from "../src/config"; +import * as fs from 'fs'; +import config from '../src/config'; import * as WA from '../src/wild_apricot'; -import * as yaml from "js-yaml"; - +import * as yaml from 'js-yaml'; const WA_ID = process.argv[2]; -if(! WA_ID ) { - throw new Error( "Need to pass Wild Apricot member ID to lookup" ); +if (!WA_ID) { + throw new Error('Need to pass Wild Apricot member ID to lookup'); } - let conf = config(); let wa = new WA.WildApricot( - conf['wa_api_client'] - ,conf['wa_api_secret'] - ,conf['wa_account_id'] + conf['wa_api_client'], + conf['wa_api_secret'], + conf['wa_account_id'], ); -wa.fetch_member_data( parseInt( WA_ID ) - ,( member_data ) => { - console.log( JSON.stringify( member_data, null, 2 ) ); - } - ,( err ) => { +wa.fetch_member_data( + parseInt(WA_ID), + member_data => { + console.log(JSON.stringify(member_data, null, 2)); + }, + err => { throw err; - } + }, ); diff --git a/util/reconciliation_report.ts b/util/reconciliation_report.ts index 6f37584..5d05ab5 100644 --- a/util/reconciliation_report.ts +++ b/util/reconciliation_report.ts @@ -1,7 +1,7 @@ import * as App from '../src/request_funcs'; import * as Email from '../src/email_sender'; import * as fs from 'fs'; -import config from "../src/config"; +import config from '../src/config'; import * as PG from '../src/db-pg'; import * as WA from '../src/wild_apricot'; import * as Yaml from 'js-yaml'; @@ -9,91 +9,85 @@ import * as Yaml from 'js-yaml'; //const TO_EMAIL = 'board@thebodgery.org'; const TO_EMAIL = 'tmurray@wumpus-cave.net'; - const conf = config(); const db = new PG.PG( - conf.db_host - ,conf.db_port - ,conf.db_name - ,conf.db_user - ,conf.db_password + conf.db_host, + conf.db_port, + conf.db_name, + conf.db_user, + conf.db_password, ); const wa = new WA.WildApricot( - conf.wa_api_client - ,conf.wa_api_secret - ,conf.wa_account_id + conf.wa_api_client, + conf.wa_api_secret, + conf.wa_account_id, ); - -function get_members_db( db ): Promise -{ - const promise = new Promise( (resolve, reject) => { +function get_members_db(db): Promise { + const promise = new Promise((resolve, reject) => { db.get_members( - 0 - ,null - ,(members) => { + 0, + null, + members => { const formatted_members = {}; - members.forEach( (_) => { + members.forEach(_ => { const member = { - wa_id: _.wildapricot_id - ,status: _.status - ,first_name: _.first_name - ,last_name: _.last_name - ,email: _.email + wa_id: _.wildapricot_id, + status: _.status, + first_name: _.first_name, + last_name: _.last_name, + email: _.email, }; - formatted_members[ member.wa_id ] = member; + formatted_members[member.wa_id] = member; }); - resolve( formatted_members ); - } - ,(err) => { - reject( err ); - } + resolve(formatted_members); + }, + err => { + reject(err); + }, ); }); return promise; } -function get_members_wa( wa ): Promise -{ - const promise = new Promise( (resolve, reject) => { +function get_members_wa(wa): Promise { + const promise = new Promise((resolve, reject) => { wa.fetch_all_members( - (wa_members) => { + wa_members => { const formatted_members = {}; - wa_members.forEach( (_) => { + wa_members.forEach(_ => { const member = { - wa_id: _.wild_apricot_id - ,status: _.is_active - ,first_name: _.first_name - ,last_name: _.last_name - ,email: _.email + wa_id: _.wild_apricot_id, + status: _.is_active, + first_name: _.first_name, + last_name: _.last_name, + email: _.email, }; formatted_members[member.wa_id] = member; }); - resolve( formatted_members ); - } - ,(err) => { - reject( err ); - } + resolve(formatted_members); + }, + err => { + reject(err); + }, ); }); return promise; } -function compare( members1, members2 ) -{ +function compare(members1, members2) { let mismatch_results = {}; - Object.values( members1 ).forEach( (_) => { + Object.values(members1).forEach(_ => { let wa_id = _['wa_id']; - if(! members2[wa_id]) { + if (!members2[wa_id]) { mismatch_results[wa_id] = _; - } - else if( _['status'] && (! members2[wa_id]['status']) ) { + } else if (_['status'] && !members2[wa_id]['status']) { mismatch_results[wa_id] = _; } }); @@ -101,53 +95,46 @@ function compare( members1, members2 ) return mismatch_results; } -function total_active_members( members ): number -{ - let active_members = Object.values( members ).filter( (_) => { +function total_active_members(members): number { + let active_members = Object.values(members).filter(_ => { return _['status']; }); return active_members.length; } -function send_email( args: { - active_in_local_not_wa: Array - ,active_in_wa_not_local: Array - ,total_active_members: number -}): Promise -{ - const promise = new Promise( (resolve, reject) => { +function send_email(args: { + active_in_local_not_wa: Array; + active_in_wa_not_local: Array; + total_active_members: number; +}): Promise { + const promise = new Promise((resolve, reject) => { // TODO fetch_google_auth() and fetch_google_email_scopes() - // are private to src/request_funcs. Make them more generally + // are private to src/request_funcs. Make them more generally // accessible. // TODO create sender.send_reconciliation() - App.fetch_google_auth( - conf - ,App.fetch_google_email_scopes() - ,( client ) => { - const sender = new Email.Email({ - auth: client - }); - sender.init( () => { - sender.send_reconciliation({ - to_name: TO_EMAIL - ,to_email: TO_EMAIL - ,from_name: conf['email_new_member_signup_from_name'] - ,from_email: conf['email_new_member_signup_from_email'] - ,active_in_local_not_wa: args.active_in_local_not_wa - ,active_in_wa_not_local: args.active_in_wa_not_local - ,total_active_members: args.total_active_members - ,success_callback: () => { - resolve(); - } - ,error_callback: ( err: Error ) => { - console.log( "Error sending email: " - + err.toString() ); - reject( err ); - } - }); + App.fetch_google_auth(conf, App.fetch_google_email_scopes(), client => { + const sender = new Email.Email({ + auth: client, + }); + sender.init(() => { + sender.send_reconciliation({ + to_name: TO_EMAIL, + to_email: TO_EMAIL, + from_name: conf['email_new_member_signup_from_name'], + from_email: conf['email_new_member_signup_from_email'], + active_in_local_not_wa: args.active_in_local_not_wa, + active_in_wa_not_local: args.active_in_wa_not_local, + total_active_members: args.total_active_members, + success_callback: () => { + resolve(); + }, + error_callback: (err: Error) => { + console.log('Error sending email: ' + err.toString()); + reject(err); + }, }); - } - ); + }); + }); resolve(); }); @@ -155,22 +142,20 @@ function send_email( args: { return promise; } - -Promise.all([ - get_members_db( db ) - ,get_members_wa( wa ) -]).then( (values) => { - const db_members = values[0]; - const wa_members = values[1]; - - const active_in_local_not_wa = compare( db_members, wa_members ); - const active_in_wa_not_local = compare( wa_members, db_members ); - const total = total_active_members( wa_members ); - - const email_promise = send_email({ - active_in_local_not_wa: Object.values( active_in_local_not_wa ) - ,active_in_wa_not_local: Object.values( active_in_wa_not_local ) - ,"total_active_members": total - }); - return email_promise; -}).then( () => {}); +Promise.all([get_members_db(db), get_members_wa(wa)]) + .then(values => { + const db_members = values[0]; + const wa_members = values[1]; + + const active_in_local_not_wa = compare(db_members, wa_members); + const active_in_wa_not_local = compare(wa_members, db_members); + const total = total_active_members(wa_members); + + const email_promise = send_email({ + active_in_local_not_wa: Object.values(active_in_local_not_wa), + active_in_wa_not_local: Object.values(active_in_wa_not_local), + total_active_members: total, + }); + return email_promise; + }) + .then(() => {});