Skip to content

Commit

Permalink
Merge pull request #434 from nmarklund10/nmarklund10/431-implement-ge…
Browse files Browse the repository at this point in the history
…t-all-users-v2

Nmarklund10/431 implement get all users v2
  • Loading branch information
blakenan-bellese authored Jun 23, 2022
2 parents 36629db + e277cd3 commit 68293e8
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 91 deletions.
65 changes: 33 additions & 32 deletions sequelize/config.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
require('dotenv').config();
const fs = require('fs');
const rdsCa = fs.readFileSync('./rds-combined-ca-bundle.pem');
require('dotenv').config()
const tls = require('tls')
const fs = require('fs')
const rdsCa = fs.readFileSync('./rds-combined-ca-bundle.pem')

module.exports = {
development: {
database: process.env.DATABASE_NAME,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
port: process.env.DATABASE_PORT,
host: process.env.DATABASE_HOST,
dialect: 'postgres',
},
production: {
database: process.env.DATABASE_NAME,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
port: process.env.DATABASE_PORT,
host: process.env.DATABASE_HOST,
dialect: 'postgres',
dialectOptions: {
ssl: {
rejectUnauthorized: true,
ca: [rdsCa],
checkServerIdentity: (host, cert) => {
const error = tls.checkServerIdentity(host, cert);
if (error && !cert.subject.CN.endsWith('.rds.amazonaws.com')) {
return error;
}
}
}
}
},
};
development: {
database: process.env.DATABASE_NAME,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
port: process.env.DATABASE_PORT,
host: process.env.DATABASE_HOST,
dialect: 'postgres',
},
production: {
database: process.env.DATABASE_NAME,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
port: process.env.DATABASE_PORT,
host: process.env.DATABASE_HOST,
dialect: 'postgres',
dialectOptions: {
ssl: {
rejectUnauthorized: true,
ca: [rdsCa],
checkServerIdentity: (host, cert) => {
const error = tls.checkServerIdentity(host, cert)
if (error && !cert.subject.CN.endsWith('.rds.amazonaws.com')) {
return error
}
}
}
}
},
}
10 changes: 8 additions & 2 deletions sequelize/data/user.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
[
{
"email": "[email protected]",
"displayName": "Homer Simpson",
"password": "donuts",
"roles": ["admin"]
"roles": [
"admin"
]
},
{
"email": "[email protected]",
"displayName": "Test User",
"password": "test",
"roles": ["user"]
"roles": [
"user"
]
}
]
94 changes: 47 additions & 47 deletions sequelize/migrations/01-create-demo-user.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
type: Sequelize.UUID,
primaryKey: true,
allowNull: false,
autoIncrement: false,
},
email: {
allowNull: false,
unique: true,
type: Sequelize.STRING
},
password: {
allowNull: false,
type: Sequelize.STRING
},
salt: {
type: Sequelize.STRING
},
token: {
type: Sequelize.STRING
},
displayName: {
type: Sequelize.STRING
},
phone: {
type: Sequelize.STRING
},
attributes: {
type: Sequelize.JSON,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: queryInterface => {
return queryInterface.dropTable('Users');
}
};
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
type: Sequelize.UUID,
primaryKey: true,
allowNull: false,
autoIncrement: false,
},
email: {
allowNull: false,
unique: true,
type: Sequelize.STRING
},
password: {
allowNull: false,
type: Sequelize.STRING
},
salt: {
type: Sequelize.STRING
},
token: {
type: Sequelize.STRING
},
displayName: {
type: Sequelize.STRING
},
phone: {
type: Sequelize.STRING
},
attributes: {
type: Sequelize.JSON,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
},
down: queryInterface => {
return queryInterface.dropTable('Users')
}
}
6 changes: 1 addition & 5 deletions src/api-docs/v2/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1229,8 +1229,7 @@
"get": {
"tags": [
"users",
"read-only",
"unimplemented"
"read-only"
],
"summary": "Retrieves all users.",
"description": "Retrieves all defined users in the application.",
Expand All @@ -1248,9 +1247,6 @@
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
Expand Down
4 changes: 3 additions & 1 deletion src/routes/v2/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import health from './health'
import security from './security'
import users from './users'
// Exports object of routes we import above. Add to this if you're adding new routes.

const routeExports = {
health,
security
security,
users
}

module.exports = routeExports
9 changes: 8 additions & 1 deletion src/routes/v2/security.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Router } from 'express'
import rateLimit from 'express-rate-limit'
import validator from 'validator'
import jwt from 'jsonwebtoken'
import { ErrorResponse } from '../../utils/v2'

const router = new Router()
const max = (process.env.NODE_ENV !== 'production') ? 50000 : 50
const loginLimiter = rateLimit({
windowMs: 60 * 60 * 1000,
max,
message: 'Too many login attempts for this IP. Please try again later.'
})

router.post('/authenticate', async (req, res) => {
router.post('/authenticate', loginLimiter, async (req, res) => {
let response
try {
const { email, password } = req.body
Expand Down
23 changes: 23 additions & 0 deletions src/routes/v2/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Router } from 'express'
import { authMiddleware } from '../../utils/v2'

const router = new Router()


router.get('/', authMiddleware, async (req, res) => {
let response
try {
const users = await req.context.models.User.findAll({
attributes: ['email', 'displayName']
})

return res.status(200).json(users)
} catch (e) {
console.error(e)
response.setCode(500)
}

return res.status(response.getCode()).json(response.getMessage())
})

export default router
31 changes: 31 additions & 0 deletions src/tests/v2/user.routes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe(`User tests (v${VERSION})`, function() {
})
after(async function() {
await testUser.destroyToken()
process.env.BYPASS_LOGIN = true
})

it('should login', function (done) {
Expand Down Expand Up @@ -64,4 +65,34 @@ describe(`User tests (v${VERSION})`, function() {
done()
})
})
it('should get all users', function(done) {
request(app)
.get(`/v${VERSION}/users`)
.set('Accept', 'application/json')
.set('token', token)
.send()
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200)
.end((err, res) => {
if (err) return done(err)
expect(res.body).to.deep.include.members([{email: testUser.user.email, displayName: testUser.user.displayName}])
done()
})
})
it('should not get all users', function(done) {
process.env.BYPASS_LOGIN = false
request(app)
.get(`/v${VERSION}/users`)
.set('Accept', 'application/json')
.set('token', randomWords())
.send()
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(403)
.end((err, res) => {
if (err) return done(err)
expect(res.body.statusCode).to.equal(403)
expect(res.body.message).to.equal('Access not permitted')
done()
})
})
})
6 changes: 3 additions & 3 deletions src/utils/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Login {
constructor(version = (process.env.DEFAULT_API_VERSION || '1')) {
this.DEFAULT_API_VERSION = version
this.role = randomWords()
this.user = { email: `${randomWords()}@test.test`, password: 'Abcdefg12!', roles: [this.role] }
this.user = { email: `${randomWords()}@test.test`.toLowerCase(), password: 'Abcdefg12!', displayName: randomWords(), roles: [this.role] }
this.methods = [
'GET',
'POST',
Expand Down Expand Up @@ -71,11 +71,11 @@ class Login {
* Creates a temp user for testing.
*/
async _createUser() {
const user = await models.User.create({ email: this.user.email.toLowerCase(), password: this.user.password })
const user = await models.User.create({ email: this.user.email, password: this.user.password, displayName: this.user.displayName })
this.user.id = user.id

const e = await loadCasbin()
await e.addRoleForUser(this.user.email.toLowerCase(), this.role)
await e.addRoleForUser(this.user.email, this.role)
// await models.UserRole.create({
// ptype: 'g',
// v0: this.email.toLowerCase(),
Expand Down
Loading

0 comments on commit 68293e8

Please sign in to comment.