This commit is contained in:
Martin Donnelly 2016-03-15 14:49:39 +00:00
commit 2b60bc78cf
18 changed files with 1682 additions and 0 deletions

32
.editorconfig Normal file
View File

@ -0,0 +1,32 @@
; http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.txt]
insert_final_newline = false
trim_trailing_whitespace = false
[*.py]
indent_size = 4
[*.m]
indent_size = 4
[Makefile]
indent_style = tab
indent_size = 8
[*.{js,json}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

177
.gitignore vendored Normal file
View File

@ -0,0 +1,177 @@
# Created by .ignore support plugin (hsz.mobi)
### Archives template
# It's better to unpack these files and commit the raw source because
# git has its own built in compression methods.
*.7z
*.jar
*.rar
*.zip
*.gz
*.bzip
*.bz2
*.xz
*.lzma
*.cab
#packing-only formats
*.iso
*.tar
#package management formats
*.dmg
*.xpi
*.gem
*.egg
*.deb
*.rpm
*.msi
*.msm
*.msp
### Windows template
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Node template
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
### VisualStudioCode template
.settings
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate

32
.jshintrc Normal file
View File

@ -0,0 +1,32 @@
{
"predef": [
"Promise"
],
"node":true,
"browser": false,
"boss": true,
"curly": true,
"debug": false,
"devel": true,
"eqeqeq": true,
"evil": true,
"forin": false,
"immed": false,
"laxbreak": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": false,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"undef": true,
"sub": true,
"strict": false,
"white": false,
"eqnull": true,
"esnext": true,
"unused": true,
"supernew":true
}

1
.pgpass Normal file
View File

@ -0,0 +1 @@
localhost:5432:oBrand:obrand:obrand

29
connect.js Normal file
View File

@ -0,0 +1,29 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-09
* Time: 11:44
*
*/
'use strict';
var pg = require('pg');
var conString = 'postgres://postgres:MPReoa43@localhost/oBrand';
pg.connect(conString, function(err, client, done) {
if(err) {
return console.error('error fetching client from pool',err);
}
client.query('select $1::int as number',[1], function(err,result) {
done();
if (err) {
return console.error('error running query', err);
}
console.log(result.rows[0].number);
})
});

262
md-validator.js Normal file
View File

@ -0,0 +1,262 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-09
* Time: 14:26
*
*/
var VALIDATE = new function() {
this.dateBuilder = function(d, m, y) {
return new Date(Date.UTC(y, m, d,0,0,0));
};
/**
* Check to see if a date is actually a valid date (e.g. FF browser converts 31 Feb to an invalid date)
* @param {number} d
* @param {number} m
* @param {number} y
* @returns {boolean}
*/
this.isDateValid = function(d, m, y) {
var enteredDate = new Date(y, m, d);
if (enteredDate.getFullYear() == y && enteredDate.getMonth() == m && enteredDate.getDate() == d) {
return true;
}
return false;
};
/**
* Validates emails
* @return {boolean}
*/
this.Email = function(email) {
var flag = false, b;
if (/^\w+([\+\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
flag = true;
}
else
flag = false;
b = email.split("@");
if (b.length > 2) flag = false;
if (b[0].length == 0) flag = false;
if (email.charAt(0) == '.' || email.charAt(email.length - 1) == '.') flag = false;
return flag;
};
/**
*
* @param inval
* @returns {boolean}
*/
this.time = function(inval) {
"use strict";
var rtrn = false, exp = /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/;
if (exp.test(inval)) {
rtrn = true;
}
return rtrn;
};
/**
*
* @param inval
* @returns {boolean}
*/
this.money = function(inval) {
"use strict";
var rtrn = '', exp = /^\xA3?\d{1,3}?([,]\d{3}|\d)*?([.]\d{1,2})?$/;
if (exp.test(inval)) {
rtrn = exp.exec(inval);
}
return rtrn[0];
};
/**
* Validates UK postcodes
*/
this.checkPostCode = function(toCheck) {
// Permitted letters depend upon their position in the postcode.
var alpha1 = '[abcdefghijklmnoprstuwyz]'; // Character 1
var alpha2 = '[abcdefghklmnopqrstuvwxy]'; // Character 2
var alpha3 = '[abcdefghjkpmnrstuvwxy]'; // Character 3
var alpha4 = '[abehmnprvwxy]'; // Character 4
var alpha5 = '[abdefghjlnpqrstuwxyz]'; // Character 5
var BFPOa5 = '[abdefghjlnpqrst]'; // BFPO alpha5
var BFPOa6 = '[abdefghjlnpqrstuwzyz]'; // BFPO alpha6
var invalidW1 = /^(W1)([eilmnopqrvwxyz]{1})(\s*)([0-9]{1}[abdefghjlnpqrstuwxyz]{2})$/i;
// Array holds the regular expressions for the valid postcodes
var pcexp = [];
// BFPO postcodes
pcexp.push(new RegExp('^(bf1)(\\s*)([0-6]{1}' + BFPOa5 + '{1}' + BFPOa6 + '{1})$',
'i'));
// Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA
pcexp.push(new RegExp('^(' + alpha1 + '{1}' + alpha2 + '?[0-9]{1,2})(\\s*)([0-9]{1}' + alpha5 + '{2})$',
'i'));
// Expression for postcodes: ANA NAA
pcexp.push(new RegExp('^(' + alpha1 + '{1}[0-9]{1}' + alpha3 + '{1})(\\s*)([0-9]{1}' + alpha5 + '{2})$',
'i'));
// Expression for postcodes: AANA NAA
pcexp.push(new RegExp('^(' + alpha1 + '{1}' + alpha2 + '{1}' + '?[0-9]{1}' + alpha4 + '{1})(\\s*)([0-9]{1}' + alpha5 + '{2})$',
'i'));
// Exception for the special postcode GIR 0AA
pcexp.push(/^(GIR)(\s*)(0AA)$/i);
// Standard BFPO numbers
pcexp.push(/^(bfpo)(\s*)([0-9]{1,4})$/i);
// c/o BFPO numbers
pcexp.push(/^(bfpo)(\s*)(c\/o\s*[0-9]{1,3})$/i);
// Overseas Territories
pcexp.push(/^([A-Z]{4})(\s*)(1ZZ)$/i);
// Anguilla
pcexp.push(/^(ai-2640)$/i);
// Load up the string to check
var postCode = toCheck;
// Assume we're not going to find a valid postcode
var valid = false;
// Check the string against the types of post codes
for (var i = 0; i < pcexp.length; i++) {
if (pcexp[i].test(postCode)) {
// The post code is valid - split the post code into component parts
pcexp[i].exec(postCode);
// Copy it back into the original string, converting it to uppercase
// and inserting a space between the inward and outward codes
postCode = RegExp.$1.toUpperCase() + ' ' + RegExp.$3.toUpperCase();
// If it is a BFPO c/o type postcode, tidy up the "c/o" part
postCode = postCode.replace(/C\/O\s*/, 'c/o ');
// If it is the Anguilla overseas territory postcode, we need to
// treat it specially
if (toCheck.toUpperCase() == 'AI-2640') {postCode = 'AI-2640'}
// Load new postcode back into the form element
valid = true;
// Remember that we have found that the code is valid and break
// from loop
break;
}
}
if (invalidW1.test(postCode)) {
valid = false;
}
// Return with either the reformatted valid postcode or the original
// invalid postcode
//if (valid) {return postCode;} else return false;
if (valid) {return postCode;}
else return '';
};
/**
* Validates UK Telephone numbers
* @param {string} telephoneNumber
* @returns {*}
*/
this.checkUKTelephone = function(telephoneNumber) {
// Convert into a string and check that we were provided with something
var telNumberErrorNo, telnum = telephoneNumber + ' ';
if (telnum.length == 1) {
// telNumberErrorNo = 1;
return false;
}
telnum = (telnum).trim();
// Don't allow country codes to be included (assumes a leading "+")
var exp = /^(\+)[\s]*(.*)$/;
if (exp.test(telnum) == true) {
//telNumberErrorNo = 2;
return false;
}
// Remove spaces from the telephone number to help validation
while (telnum.indexOf(' ') != -1) {
telnum = telnum.slice(0,
telnum.indexOf(' ')) + telnum.slice(telnum.indexOf(' ') + 1);
}
// Remove hyphens from the telephone number to help validation
while (telnum.indexOf('-') != -1) {
telnum = telnum.slice(0,
telnum.indexOf('-')) + telnum.slice(telnum.indexOf('-') + 1);
}
// Now check that all the characters are digits
exp = /^[0-9]{10,11}$/;
if (exp.test(telnum) != true) {
// telNumberErrorNo = 3;
return false;
}
// Now check that the first digit is 0
exp = /^0[0-9]{9,10}$/;
if (exp.test(telnum) != true) {
// telNumberErrorNo = 4;
return false;
}
// Disallow numbers allocated for dramas.
// Array holds the regular expressions for the drama telephone numbers
var tnexp = [];
tnexp.push(/^(0113|0114|0115|0116|0117|0118|0121|0131|0141|0151|0161)(4960)[0-9]{3}$/);
tnexp.push(/^02079460[0-9]{3}$/);
tnexp.push(/^01914980[0-9]{3}$/);
tnexp.push(/^02890180[0-9]{3}$/);
tnexp.push(/^02920180[0-9]{3}$/);
tnexp.push(/^01632960[0-9]{3}$/);
tnexp.push(/^07700900[0-9]{3}$/);
tnexp.push(/^08081570[0-9]{3}$/);
tnexp.push(/^09098790[0-9]{3}$/);
tnexp.push(/^03069990[0-9]{3}$/);
for (var i = 0; i < tnexp.length; i++) {
if (tnexp[i].test(telnum)) {
telNumberErrorNo = 5;
return false;
}
}
// Finally check that the telephone number is appropriate.
exp = (/^(01|02|03|05|070|071|072|073|074|075|07624|077|078|079)[0-9]+$/);
if (exp.test(telnum) != true) {
// telNumberErrorNo = 5;
return false;
}
// Telephone number seems to be valid - return the stripped telehone number
return telnum;
};
};
module.exports = VALIDATE;

38
mock.js Normal file
View File

@ -0,0 +1,38 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-09
* Time: 15:18
*
*/
var dbAccounts = require('units/db-accounts');
var log4js = require('log4js');
var logger = log4js.getLogger();
var dbAccount = dbAccounts;
var profileData = {
forename:'Tim',
surname:'Timmington',
gender:0,
dob:'2000-01-01',
bio:'He is forbidden from walking through cemetaries, because of that one incident where he raised the dead'
};
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
profileData.uid = data.uid;
return dbAccount.addInsertProfile(profileData)
.then(function(sqlResponse){
logger.debug(sqlResponse);
});
})
.catch(function(err) {
console.log(err);
//err.should.not.be.ok();
});

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "dbwork",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha --recursive --reporter spec --bail --check-leaks --timeout 3000"
},
"author": "",
"license": "ISC",
"devDependencies": {
"after": "^0.8.1",
"assert": "^1.3.0",
"bcrypt-as-promised": "^1.1.0",
"chai": "^3.5.0",
"exec": "^0.2.1",
"expect": "^1.15.1",
"log4js": "^0.6.33",
"mocha": "^2.4.5",
"mocha-jshint": "^2.3.1",
"moment": "^2.12.0",
"node-validator": "http://gitlab.silvrtree.co.uk/martind2000/node-validator.git",
"pg-promise": "^3.3.0",
"should": "^8.2.2",
"superagent": "^1.8.0-beta.2",
"supertest": "^1.2.0",
"uuid-pure": "^1.0.10"
},
"dependencies": {
"bcrypt": "^0.8.5",
"pg": "^4.5.1"
}
}

127
rebuild.sql Normal file
View File

@ -0,0 +1,127 @@
ALTER TABLE "profile" DROP CONSTRAINT IF EXISTS "profile_fk0";
ALTER TABLE "profile" DROP CONSTRAINT IF EXISTS "profile_fk1";
ALTER TABLE "venue" DROP CONSTRAINT IF EXISTS "venue_fk0";
ALTER TABLE "billing" DROP CONSTRAINT IF EXISTS "billing_fk0";
DROP TABLE IF EXISTS "logins";
DROP TABLE IF EXISTS "profile";
DROP TABLE IF EXISTS "company";
DROP TABLE IF EXISTS "venue";
DROP TABLE IF EXISTS "billing";
DROP TABLE IF EXISTS "master_beacons";
CREATE TABLE "logins" (
"id" serial NOT NULL,
"username" varchar(100) NOT NULL UNIQUE,
"email" varchar(150) NOT NULL UNIQUE,
"password_hash" varchar(78) NOT NULL,
"password_reset_token" varchar(128) UNIQUE,
"uid" varchar(22) UNIQUE,
CONSTRAINT logins_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "profile" (
"id" serial NOT NULL,
"uid" varchar(22) NOT NULL,
"forename" varchar(75) NOT NULL,
"surname" varchar(75) NOT NULL,
"gender" int NOT NULL,
"dob" DATE NOT NULL,
"bio" TEXT NOT NULL,
"member_of" int,
CONSTRAINT profile_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "company" (
"id" serial NOT NULL,
"company_name" varchar(100) NOT NULL,
"address1" varchar(150) NOT NULL,
"address2" varchar(150) NOT NULL,
"address3" varchar(150) NOT NULL,
"town" varchar(150) NOT NULL,
"county" varchar(150) NOT NULL,
"postcode" varchar(12) NOT NULL,
"country" int NOT NULL,
"pcontact" varchar(20) NOT NULL,
"ocontact" varchar(20) NOT NULL,
"mobile" varchar(20) NOT NULL,
"email" varchar(150) NOT NULL,
CONSTRAINT company_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "venue" (
"id" serial NOT NULL,
"venue_name" varchar(100) NOT NULL,
"address1" varchar(150) NOT NULL,
"address2" varchar(150) NOT NULL,
"address3" varchar(150) NOT NULL,
"town" varchar(150) NOT NULL,
"county" varchar(150) NOT NULL,
"postcode" varchar(12) NOT NULL,
"country" int NOT NULL,
"pcontact" varchar(20) NOT NULL,
"ocontact" varchar(20) NOT NULL,
"mobile" varchar(20) NOT NULL,
"email" varchar(150) NOT NULL,
"company_id" int NOT NULL,
CONSTRAINT venue_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "billing" (
"id" serial NOT NULL,
"company_id" int NOT NULL,
CONSTRAINT billing_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "master_beacons" (
"id" bigint NOT NULL,
"uid" uuid NOT NULL,
CONSTRAINT master_beacons_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
ALTER TABLE "profile" ADD CONSTRAINT "profile_fk0" FOREIGN KEY ("user_id") REFERENCES "logins"("id");
ALTER TABLE "profile" ADD CONSTRAINT "profile_fk1" FOREIGN KEY ("member_of") REFERENCES "company"("id");
ALTER TABLE "venue" ADD CONSTRAINT "venue_fk0" FOREIGN KEY ("company_id") REFERENCES "company"("id");
ALTER TABLE "billing" ADD CONSTRAINT "billing_fk0" FOREIGN KEY ("company_id") REFERENCES "company"("id");
grant connect on database "oBrand" to obrand;
GRANT SELECT, UPDATE, INSERT, DELETE, TRIGGER ON TABLE public.logins TO obrand;
grant select, update on logins_id_seq to obrand;
grant select, update on profile_id_seq to obrand;

321
test/db-account.js Normal file
View File

@ -0,0 +1,321 @@
"use strict";
var should = require('should');
var assert = require('assert');
var db = require('../units/db-connector').dbConnection;
var dbAccount = require('../units/db-accounts')(db);
var exec = require('child_process').exec;
function prepare_db(next) {
exec('psql -Upostgres -d oBrand -f ./rebuild.sql', function(err) {
if (err !== null) {
console.log('exec error: ' + err);
}
});
}
describe('Accounts DB', function() {
before(function() {
console.log('Prepare database');
prepare_db(function(err) {
if (err) {
console.log('Problem setting up database');
}
});
});
it('should connect to Postgres using promises', function() {
return dbAccount.connectPGP().then(function(data) {
assert.equal(data[0].number, 1);
});
});
it('should not add user with no data', function() {
return dbAccount.addNewAccount({}).then(function() {
})
.catch(function(err) {
assert.notEqual(err, null);
});
});
it('should not add user with no details', function() {
return dbAccount.addNewAccount({
username: '', password: '', email: ''
}).then(function(data) {
})
.catch(function(err) {
assert.notEqual(err, null);
err.should.have.property('code', 1000);
});
});
it('should not add an empty name', function() {
return dbAccount.addNewAccount({
username: '', password: 'b0b5p455w0rd', email: 'bob@tim.com'
}).then(function(data) {
})
.catch(function(err) {
err.should.have.property('code', 1000);
});
});
it('should not add user with missing password', function() {
return dbAccount.addNewAccount({
username: 'bob', password: '', email: 'bob@tim.com'
}).then(function(data) {
})
.catch(function(err) {
err.should.have.property('code', 1000);
});
});
it('should not add user with missing email', function() {
return dbAccount.addNewAccount({
username: 'bob', password: 'b0b5p455w0rd', email: ''
}).then(function(data) {
})
.catch(function(err) {
err.should.have.property('code', 1000);
});
});
it('should not add user with invalid email', function() {
return dbAccount.addNewAccount({
username: 'bob', password: 'b0b5p455w0rd', email: 'tim'
}).then(function(data) {
})
.catch(function(err) {
err.should.have.property('code', 1001);
});
});
it('should add a new user', function() {
return dbAccount.addNewAccount({
username: 'bob',
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
should(data.reply).equal('user added');
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
it('should not add a duplicate user', function() {
return dbAccount.addNewAccount({
username: 'bob',
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
should(data.reply).equal('user added');
})
.catch(function(err) {
console.log(err);
err.should.have.property('detail',
'Key (username)=(bob) already exists.');
});
});
it('should find a valid account', function() {
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
data.should.have.property('username','bob');
})
.catch(function(err) {
console.log(err);
err.should.be.ok();
});
});
it('should not allow login with incorrect password', function() {
return dbAccount.findAccount({password: 'bobspassword', email: 'bob@tim.com'})
.then(function(data) {
data.should.have.property('username','bob');
})
.catch(function(err) {
err.should.have.property('code', 1004);
});
});
it('should not allow login with incorrect email', function() {
return dbAccount.findAccount({password: 'b0b5p455w0rd', email: 'tim@bob.com'})
.then(function(data) {
data.should.have.property('username','bob');
})
.catch(function(err) {
err.should.have.property('code', 1004);
});
});
it('should return account details for a valid account', function() {
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
return dbAccount.sqlGetAccountDetails(data.uid)
.then(function(wantedData){
console.log(wantedData);
wantedData.should.have.property('username','bob');
});
})
.catch(function(err) {
console.log(err);
err.should.be.ok();
});
});
it('should return account details for a valid account', function() {
return dbAccount.sqlGetAccountDetails('DEADBEEFDEADBEEF')
.then(function(wantedData){
wantedData.should.have.property('username','bob');
}).catch(function(err) {
console.log(err);
err.should.be.ok();
});
});
it('should insert profile details', function() {
let profileData = {
forename:'Bob',
surname:'Bobbington',
gender:0,
dob:'1974-10-24',
bio:'Sharks have a week dedicated to him'
};
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
profileData.uid = data.uid;
return dbAccount.addInsertProfile(profileData)
.then(function(sqlResponse){
sqlResponse.should.be.ok();
});
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
it('should insert update details', function() {
let profileData = {
forename:'Tim',
surname:'Timmington',
gender:0,
dob:'2000-01-01',
bio:'He is forbidden from walking through cemetaries, because of that one incident where he raised the dead'
};
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
profileData.uid = data.uid;
return dbAccount.addInsertProfile(profileData)
.then(function(sqlResponse){
sqlResponse.should.be.ok();
});
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
it('should return profile details', function() {
return dbAccount.findAccount({
password: 'b0b5p455w0rd',
email: 'bob@tim.com'
})
.then(function(data) {
return dbAccount.sqlGetProfile(data.uid)
.then(function(sqlResponse){
console.log(sqlResponse);
sqlResponse.should.have.property('forename','Tim');
});
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
it('should add Martin', function() {
return dbAccount.addNewAccount({
username: 'Martin ',
password: 'MPReoa43',
email: 'martind2000@gmail.com'
})
.then(function(data) {
should(data.reply).equal('user added');
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
it('should add Default', function() {
return dbAccount.addNewAccount({
username: 'Default',
password: 'password',
email: 'm@g.com'
})
.then(function(data) {
should(data.reply).equal('user added');
})
.catch(function(err) {
console.log(err);
err.should.not.be.ok();
});
});
// TEST END HERE
});

27
test/db-company.js Normal file
View File

@ -0,0 +1,27 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-15
* Time: 14:26
*
*/
"use strict";
var should = require('should');
var assert = require('assert');
var db = require('../units/db-connector').dbConnection;
var dbCompany = require('../units/db-company')(db);
describe('abc Setup DB', function() {
it('should not add user with no data', function() {
return dbCompany.addNewCompany({}).then(function() {
})
.catch(function(err) {
assert.notEqual(err, null);
});
});
});

8
test/jshint.spec.js Normal file
View File

@ -0,0 +1,8 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-15
* Time: 13:42
*
*/
require('mocha-jshint')({paths:['units/']});

341
test/md-validator.js Normal file
View File

@ -0,0 +1,341 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-09
* Time: 14:37
*
*/
"use strict";
var mdValidate = require('node-validator');
var should = require('should');
var assert = require('assert');
var expect = require('expect');
var phone = [
'A',
'AA',
'AAA',
'AAAA',
'AAAAA',
'AAAAAA',
'0',
'01',
'012',
'0123',
'01234',
'012345',
'0123456',
'01234567',
'012345678',
'01134960000',
'01134960500',
'01134960999',
'01144960000',
'01144960500',
'01144960999',
'01154960000',
'01154960500',
'01154960999',
'01164960000',
'01164960500',
'01164960999',
'01174960000',
'01174960500',
'01174960999',
'01184960000',
'01184960500',
'01184960999',
'01214960000',
'01214960500',
'01214960999',
'01314960000',
'01314960500',
'01314960999',
'01414960000',
'01414960500',
'01414960999',
'01514960000',
'01514960500',
'01514960999',
'01614960000',
'01614960500',
'01614960999',
'02079460000',
'02079460500',
'02079460999',
'01914980000',
'01914980500',
'01914980999',
'02890180000',
'02890180500',
'02890180999',
'02920180000',
'02920180500',
'02920180999',
'01632960000',
'01632960500',
'01632960999',
'07700900000',
'07700900500',
'07700900999',
'08081570000',
'08081570555',
'08081570999',
'09098790000',
'09098790500',
'09098790999',
'03069990000',
'03069990500',
'03069990999',
'08002323636',
'09002323636',
'06002323636',
"00254745856",
"+254745856"
];
var validPhone = ['01389703002', '07944577934', '01412807000', '02071539996'];
var postcodes = [
'A',
'AA',
'AAA',
'AAAA',
'AAAAA',
'AAAAAA',
'Q1 1AA',
'V1 1AA',
'X1 1AA',
'M1 CAA',
'M1 IAA',
'M1 KAA',
'M1 MAA',
'M1 OAA',
'M1 VAA',
'Q60 1NW',
'V60 1NW',
'X60 1NW',
'M60 1CW',
'M60 1IW',
'M60 1KW',
'M60 1MW',
'M60 1OW',
'M60 1VW',
'M60 1NC',
'M60 1NI',
'M60 1NK',
'M60 1NM',
'M60 1NO',
'M60 1NV',
'QR2 6XH',
'VR2 6XH',
'XR2 6XH',
'CI2 6XH',
'CJ2 6XH',
'CZ2 6XH',
'CR2 6CH',
'CR2 6IH',
'CR2 6KH',
'CR2 6MH',
'CR2 6OH',
'CR2 6VH',
'CR2 6XC',
'CR2 6XI',
'CR2 6XK',
'CR2 6XM',
'CR2 6XO',
'CR2 6XV',
'QN55 1PT',
'VN55 1PT',
'XN55 1PT',
'DI55 1PT',
'DJ55 1PT',
'DZ55 1PT',
'DN55 1CT',
'DN55 1IT',
'DN55 1KT',
'DN55 1MT',
'DN55 1OT',
'DN55 1VT',
'DN55 1PC',
'DN55 1PI',
'DN55 1PK',
'DN55 1PM',
'DN55 1PO',
'DN55 1PV',
'Q1A 1HQ',
'V1A 1HQ',
'X1A 1HQ',
'W1I 1HQ',
'W1L 1HQ',
'W1M 1HQ',
'W1N 1HQ',
'W1O 1HQ',
'W1P 1HQ',
'W1Q 1HQ',
'W1R 1HQ',
'W1V 1HQ',
'W1X 1HQ',
'W1Y 1HQ',
'W1Z 1HQ',
'W1A 1CQ',
'W1A 1IQ',
'W1A 1KQ',
'W1A 1MQ',
'W1A 1OQ',
'W1A 1VQ',
'W1A 1HC',
'W1A 1HI',
'W1A 1HK',
'W1A 1HM',
'W1A 1HO',
'W1A 1HV',
'QC1A 1BB',
'VC1A 1BB',
'XC1A 1BB',
'EI1A 1BB',
'EJ1A 1BB',
'EZ1A 1BB',
'EC1C 1BB',
'EC1D 1BB',
'EC1F 1BB',
'EC1G 1BB',
'EC1I 1BB',
'EC1J 1BB',
'EC1K 1BB',
'EC1L 1BB',
'EC1O 1BB',
'EC1Q 1BB',
'EC1S 1BB',
'EC1T 1BB',
'EC1U 1BB',
'EC1Z 1BB',
'EC1A 1IB',
'EC1A 1MB',
'EC1A 1OB',
'EC1A 1VB',
'EC1A 1BC',
'EC1A 1BI',
'EC1A 1BK',
'EC1A 1BM',
'EC1A 1BO',
'EC1A 1BV'
];
var validPostcodes = [
'M1 1AA',
'M60 1NW',
'CR2 6XH',
'DN55 1PT',
'W1A 1HQ',
'EC1A 1BB',
'BT9 7JL',
'GIR 0AA'
];
// taken from http://blogs.msdn.com/b/testing123/archive/2009/02/05/email-address-test-cases.aspx
// having difficulty invalidating /*'あいうえお@domain.com',*/
// Several test cases for the email address have been removed as they should really be fixed by the mail system
// and they would be costly to fix in code at the moment
var invalidEmail = [
'plainaddress',
'#@%^%#$@#$@#.com',
'@domain.com',
'Joe Smith <email@domain.com>',
'email.domain.com',
'email@domain@domain.com',
'.email@domain.com',
'email.@domain.com',
'email..email@domain.com',
'email@domain.com (Joe Smith)',
'email@domain',
'email@-domain.com',
/*'email@domain.web',*/
'email@111.222.333.44444',
'email@domain..com'
];
var validEmail = [
'email@domain.com',
'firstname.lastname@domain.com',
'email@subdomain.domain.com',
'firstname+lastname@domain.com',
'email@123.123.123.123',
/*'email@[123.123.123.123]',*/
/*'"email"@domain.com',*/
'1234567890@domain.com',
'email@domain-one.com',
'_______@domain.com',
/*'email@domain.name',*/
'email@domain.co.uk',
'firstname-lastname@domain.com'
];
var emailOne = ['m@g.com', 'm@g.co.uk', 'bob@g.com'];
var emailTwo = ['m@g.co.uk', 'bob@g.com', 'm@g.com'];
describe('MD-Validator', function() {
it('should not validate an incorrect email address', function(done) {
for (var i in invalidEmail) {
mdValidate.Email(invalidEmail[i]).should.not.be.ok();
}
done();
});
it('should validate a correct email address', function(done) {
for (var i in validEmail) {
mdValidate.Email(validEmail[i]).should.be.ok();
}
done();
});
it('should not validate an incorrect phone number', function(done) {
for (var i in phone) {
mdValidate.checkUKTelephone(phone[i]).should.not.be.ok();
}
done();
});
it('should validate a correct phone number', function(done) {
for (var i in validPhone) {
mdValidate.checkUKTelephone(validPhone[i]).should.be.ok();
}
done();
});
it('should not validate an incorrect postcode', function(done) {
for (var i in postcodes) {
mdValidate.checkPostCode(postcodes[i]).should.not.be.ok();
}
done();
});
it('should validate a correct postcode', function(done) {
for (var i in validPostcodes) {
mdValidate.checkPostCode(validPostcodes[i]).should.be.ok();
}
done();
});
});

4
test/mocha.opts Normal file
View File

@ -0,0 +1,4 @@
--require should
--slow 200
--growl
--sort

173
units/db-accounts.js Normal file
View File

@ -0,0 +1,173 @@
'use strict';
//var logger = require('log4js').getLogger();
var mdValidator = require('node-validator'), mdErrors = require('./md-errors');
var bcrypt = require('bcrypt-as-promised');
var newId = require('uuid-pure').newId;
//var db = require('./db-connector').dbConnection;
module.exports = function(db) {
var module = {};
module.connectPGP= function() {
return new Promise(function(resolve, reject) {
db.query('select $1::int as number', [1])
.then((data)=>{
console.log(data);
resolve(data);
})
.catch((error)=>{
reject(error);
});
});
};
module.sqlInsertAccount= function(data) {
let _data = data;
_data.uid = newId();
return new Promise(function(resolve, reject) {
db.func('insert_user',[_data.username, _data.email, _data.hash, _data.uid])
.then(()=> {
return resolve('ok');
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetAccount= function(email) {
return new Promise(function(resolve, reject) {
db.oneOrNone("select * from logins where email=$1;",[email])
.then(function(d) {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetAccountDetails= function(uid) {
return new Promise(function(resolve, reject) {
db.one("select * from logins where uid=$1;",[uid])
.then(function(d) {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlUpsertProfile= function(data) {
var propArray=[data.uid ,data.forename, data.surname, data.gender, data.dob, data.bio];
return new Promise(function(resolve, reject) {
db.func('upsert_profile',propArray)
.then(()=> {
return resolve(true);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetProfile= function(uid) {
return new Promise(function(resolve, reject) {
db.oneOrNone("select * from profile where uid=$1;",[uid])
.then(function(d) {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.addNewAccount= function(data) {
var self = this;
return new Promise((resolve, reject) => {
let _data = {};
_data.username = data.username.trim();
_data.password = data.password.trim();
_data.email = data.email.trim();
if (Object.keys(data).length === 3) {
if (_data.username.length === 0 || _data.password.length === 0 || _data.email.length === 0)
{
return reject(mdErrors.error(1000));
}
if (mdValidator.Email(data.email) === false)
{
return reject(mdErrors.error(1001));
} else
{
// It should be possible to insert the user now.
bcrypt.hash(data.password,10).then((d) => {
_data.hash = d;
self.sqlInsertAccount(_data)
.then(()=>{
return resolve({reply:'user added'});
})
.catch((err)=>{
return reject(err);
});
});
}
} else
{
// error - required details missing
return reject(mdErrors.error(1002));
}
});
};
module.findAccount= function(data) {
var _data = data;
return new Promise((resolve, reject) => {
this.sqlGetAccount(_data.email)
.then((row) => {
if (row === null) {
return reject(mdErrors.error(1004));
}
// check password against hash held in db
bcrypt.compare(_data.password, row.password_hash)
.then(function() {
let loginDetails = {
id: row.id,
username: row.username,
email: row.email,
uid: row.uid
};
return resolve(loginDetails);
})
// failure, reject
.catch(function() {
return reject(mdErrors.error(1004));
});
})
.catch(function(err){
return reject(err);
});
});
};
module.addInsertProfile= function(data) {
return new Promise((resolve, reject) => {
this.sqlUpsertProfile(data)
.then((d)=>{
return resolve(d);
})
.catch((err)=>{
return reject(err);
});
});
};
return module;
};

17
units/db-company.js Normal file
View File

@ -0,0 +1,17 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-15
* Time: 14:04
*
*/
'use strict';
var mdValidator = require('node-validator'), mdErrors = require('./md-errors');
var newId = require('uuid-pure').newId;
module.exports = function(db) {
var module = {};
return module;
};

28
units/db-connector.js Normal file
View File

@ -0,0 +1,28 @@
'uses strict';
/**
*
* User: Martin Donnelly
* Date: 2016-03-11
* Time: 10:22
*
*/
var pgp = require('pg-promise')();
var monitor = require('pg-monitor');
var options = {};
monitor.attach(options);
var cn = {
host:'localhost',
port: 5432,
database: 'oBrand',
user:'obrand',
password:'obrand'
};
//exports pgp(cn);
exports.dbConnection = pgp(cn);

32
units/md-errors.js Normal file
View File

@ -0,0 +1,32 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-10
* Time: 11:31
*
*/
var logger = require('log4js').getLogger();
var MDERRORS = new function() {
"use strict";
var errors = {
1000: {name:'Account error', title:'Signup data missing'},
1001: {name:'Account error', title:'Email address is not in the correct format'},
1002: {name:'Account error', title:'Required details missing'},
1003: {name:'Account error', title:'Email does not exist in login table'},
1004: {name:'Account error', title:'Email address or password are incorrect'}
};
this.error = function(code)
{
var estring = '';
estring = errors[code].name + ': ' + errors[code].title + '\nCode: ' + code + '\n';
logger.error(estring);
return({code:code, name:errors[code].name, title:errors[code].title, string:estring});
};
}();
module.exports = MDERRORS;