Skip to content

Commit 28dc78a

Browse files
authored
Merge branch 'master' into snyk-upgrade-0c25a2832ede9d647c8ebc0765f128cc
2 parents f4fd1d1 + 4e1ac73 commit 28dc78a

File tree

10 files changed

+202
-166
lines changed

10 files changed

+202
-166
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Build Status](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive.svg?branch=master)](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive) [![codecov](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive/branch/master/graph/badge.svg)](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive) [![Open Source Love svg1](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)
1+
[![Build Status](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive.svg?branch=master)](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive) [![codecov](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive/branch/master/graph/badge.svg)](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/CodeForBaltimore/Bmore-Responsive.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/CodeForBaltimore/Bmore-Responsive/context:javascript) [![Known Vulnerabilities](https://snyk.io/test/github/CodeForBaltimore/Bmore-Responsive/badge.svg)](https://snyk.io/test/github/CodeForBaltimore/Bmore-Responsive)
22

33
# Bmore Responsive
44
A simple, flexible API to support emergency response coordination. Sample use cases include:

package-lock.json

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bmore-responsive",
3-
"version": "1.3.1",
3+
"version": "1.3.2",
44
"description": "An API-driven CRM (Civic Relationship Management) system.",
55
"main": "src/index.js",
66
"directories": {
@@ -33,8 +33,8 @@
3333
},
3434
"homepage": "https://github.com/CodeForBaltimore/Bmore-Responsive#readme",
3535
"dependencies": {
36-
"@babel/core": "7.10.2",
37-
"@babel/node": "7.10.1",
36+
"@babel/core": "7.10.3",
37+
"@babel/node": "7.10.3",
3838
"casbin": "4.7.2",
3939
"casbin-sequelize-adapter": "2.1.0",
4040
"chai": "4.2.0",
@@ -56,7 +56,7 @@
5656
"nunjucks": "^3.2.1",
5757
"pg": "7.18.2",
5858
"random-words": "1.1.1",
59-
"sequelize": "5.21.12",
59+
"sequelize": "5.21.13",
6060
"snyk": "^1.337.0",
6161
"supertest": "4.0.2",
6262
"swagger-ui-express": "4.1.4",

publiccode.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ publiccodeYmlVersion: "0.2"
33
name: Bmore-Responsive
44
url: "https://github.com/CodeForBaltimore/Bmore-Responsive.git"
55
landingUrl: "https://github.com/CodeForBaltimore/Bmore-Responsive"
6-
softwareVersion: "1.3.1"
6+
softwareVersion: "1.3.2"
77
releaseDate: "2020-04-06"
88
platforms:
99
- web

sequelize/data/user-role.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
"path": "/entity",
2626
"method": "GET"
2727
},
28+
{
29+
"role": "user",
30+
"path": "/entity/*",
31+
"method": "GET"
32+
},
2833
{
2934
"role": "user",
3035
"path": "/entity",
@@ -40,6 +45,11 @@
4045
"path": "/contact",
4146
"method": "GET"
4247
},
48+
{
49+
"role": "user",
50+
"path": "/contact/*",
51+
"method": "GET"
52+
},
4353
{
4454
"role": "user",
4555
"path": "/contact",

src/models/user.js

Lines changed: 105 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,40 @@ import jwt from 'jsonwebtoken'
33
import utils from '../utils'
44

55
const user = (sequelize, DataTypes) => {
6-
// Defining our user table and setting User object.
7-
const User = sequelize.define('User', {
8-
id: {
9-
type: DataTypes.UUID,
10-
primaryKey: true,
11-
defaultValue: DataTypes.UUIDV4,
12-
allowNull: false,
13-
autoIncrement: false,
14-
},
15-
email: {
16-
type: DataTypes.STRING,
17-
unique: true,
18-
required: true
19-
},
20-
password: {
21-
type: DataTypes.STRING,
22-
required: true
23-
},
24-
salt: {
25-
type: DataTypes.STRING
26-
},
27-
displayName: {
28-
type: DataTypes.STRING
29-
},
30-
phone: {
31-
type: DataTypes.STRING
32-
},
33-
attributes: {
34-
type: DataTypes.JSON,
35-
}
36-
},
37-
{
38-
schema: process.env.DATABASE_SCHEMA
39-
})
6+
// Defining our user table and setting User object.
7+
const User = sequelize.define('User', {
8+
id: {
9+
type: DataTypes.UUID,
10+
primaryKey: true,
11+
defaultValue: DataTypes.UUIDV4,
12+
allowNull: false,
13+
autoIncrement: false,
14+
},
15+
email: {
16+
type: DataTypes.STRING,
17+
unique: true,
18+
required: true
19+
},
20+
password: {
21+
type: DataTypes.STRING,
22+
required: true
23+
},
24+
salt: {
25+
type: DataTypes.STRING
26+
},
27+
displayName: {
28+
type: DataTypes.STRING
29+
},
30+
phone: {
31+
type: DataTypes.STRING
32+
},
33+
attributes: {
34+
type: DataTypes.JSON,
35+
}
36+
},
37+
{
38+
schema: process.env.DATABASE_SCHEMA
39+
})
4040

4141
/**
4242
* Looks up and validates a user by email and password.
@@ -46,40 +46,44 @@ const user = (sequelize, DataTypes) => {
4646
*
4747
* @return {String} returns either the valid login token or an error message.
4848
*/
49-
User.findByLogin = async (email, password) => {
50-
const user = await User.findOne({
51-
where: {email}
52-
})
53-
if (user) {
54-
const pw = User.encryptPassword(password, user.salt)
55-
if (pw === user.password) {
56-
return await User.getToken(user.id, user.email)
57-
}
58-
}
59-
}
60-
61-
User.decodeToken = async token => {
62-
return jwt.verify(token, process.env.JWT_KEY)
63-
}
64-
65-
/** @todo deprecate this */
66-
User.getToken = async (userId, email, expiresIn = '1d') => {
67-
const token = jwt.sign(
68-
{userId, email, type: 'user'},
69-
process.env.JWT_KEY,
70-
{expiresIn}
71-
)
72-
return token
73-
}
49+
User.findByLogin = async (email, password) => {
50+
const user = await User.findOne({
51+
where: { email }
52+
})
53+
if (user) {
54+
const pw = User.encryptPassword(password, user.salt)
55+
if (pw === user.password) {
56+
57+
const e = await utils.loadCasbin()
58+
const roles = await e.getRolesForUser(user.email)
59+
60+
return await User.getToken(user.id, user.email, roles[0])
61+
}
62+
}
63+
}
64+
65+
User.decodeToken = async token => {
66+
return jwt.verify(token, process.env.JWT_KEY)
67+
}
68+
69+
/** @todo deprecate this */
70+
User.getToken = async (userId, email, type, expiresIn = '1d') => {
71+
const token = jwt.sign(
72+
{ userId, email, type },
73+
process.env.JWT_KEY,
74+
{ expiresIn }
75+
)
76+
return token
77+
}
7478

7579
/**
7680
* Generates a random salt for password security.
7781
*
7882
* @return {String} The password salt.
7983
*/
80-
User.generateSalt = () => {
81-
return crypto.randomBytes(16).toString('base64')
82-
}
84+
User.generateSalt = () => {
85+
return crypto.randomBytes(16).toString('base64')
86+
}
8387

8488
/**
8589
* Salts and hashes a password.
@@ -89,45 +93,45 @@ const user = (sequelize, DataTypes) => {
8993
*
9094
* @return {String} The secured password.
9195
*/
92-
User.encryptPassword = (plainText, salt) => {
93-
return crypto
94-
.createHash('RSA-SHA256')
95-
.update(plainText)
96-
.update(salt)
97-
.digest('hex')
98-
}
99-
100-
// Setters
101-
const setSaltAndPassword = user => {
102-
if (user.changed('password')) {
103-
user.salt = User.generateSalt()
104-
// User.password = User.encryptPassword(user.password, user.salt)
105-
user.password = utils.encryptPassword(user.password, user.salt)
106-
}
107-
}
108-
109-
// Other Helpers
110-
// const validateContactInfo = user => {
111-
// let valid = true
112-
113-
// if (!validator.isEmail(validator.normalizeEmail(user.email))) {
114-
// valid = false
115-
// }
116-
117-
// /** @todo Add more validations for all contact info. */
118-
119-
// return valid
120-
// }
121-
122-
// Create prep actions
123-
// User.beforeCreate(validateContactInfo)
124-
User.beforeCreate(setSaltAndPassword)
125-
126-
// Update prep actions
127-
// User.beforeUpdate(validateContactInfo)
128-
User.beforeUpdate(setSaltAndPassword)
129-
130-
return User
96+
User.encryptPassword = (plainText, salt) => {
97+
return crypto
98+
.createHash('RSA-SHA256')
99+
.update(plainText)
100+
.update(salt)
101+
.digest('hex')
102+
}
103+
104+
// Setters
105+
const setSaltAndPassword = user => {
106+
if (user.changed('password')) {
107+
user.salt = User.generateSalt()
108+
// User.password = User.encryptPassword(user.password, user.salt)
109+
user.password = utils.encryptPassword(user.password, user.salt)
110+
}
111+
}
112+
113+
// Other Helpers
114+
// const validateContactInfo = user => {
115+
// let valid = true
116+
117+
// if (!validator.isEmail(validator.normalizeEmail(user.email))) {
118+
// valid = false
119+
// }
120+
121+
// /** @todo Add more validations for all contact info. */
122+
123+
// return valid
124+
// }
125+
126+
// Create prep actions
127+
// User.beforeCreate(validateContactInfo)
128+
User.beforeCreate(setSaltAndPassword)
129+
130+
// Update prep actions
131+
// User.beforeUpdate(validateContactInfo)
132+
User.beforeUpdate(setSaltAndPassword)
133+
134+
return User
131135
}
132136

133137
export default user

src/routes/entity.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ router.put('/', async (req, res) => {
119119
const response = new utils.Response()
120120
try {
121121
if (validator.isUUID(req.body.id)) {
122-
let { id, name, type, address, phone, email, checkIn, contacts } = req.body
122+
let { id, name, type, address, phone, email, checkIn, contacts, attributes } = req.body
123123

124124
/** @todo validate emails */
125125
// Validating emails
@@ -140,7 +140,8 @@ router.put('/', async (req, res) => {
140140
entity.type = (type) ? type : entity.type
141141
entity.address = (address) ? address : entity.address
142142
entity.phone = (phone) ? phone : entity.phone
143-
entity.email = (email) ? email : entity.email
143+
entity.email = (email) ? email : entity.email
144+
entity.attributes = (attributes) ? attributes : entity.attributes
144145
/** @todo validate checkIn JSON */
145146
if (entity.checkIn === null && checkIn) {
146147
const checkIns = {

src/routes/user.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import utils from '../utils'
55
import email from '../email'
66

77
const router = new Router()
8-
const max = (process.env.NODE_ENV !== 'production') ? 50000 : 5
8+
const max = (process.env.NODE_ENV !== 'production') ? 50000 : 50
99
const loginLimiter = rateLimit({
1010
windowMs: 60 * 60 * 1000,
1111
max,

src/tests/entity.routes.spec.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ const { expect } = chai
99
const entity = {
1010
name: randomWords(),
1111
type: 'Test',
12-
contacts: []
12+
contacts: [],
13+
attributes: {
14+
notes: 'test'
15+
}
1316
}
1417
const contact = {
1518
name: randomWords(),

0 commit comments

Comments
 (0)