Adde schema and route information for all entities.
This commit is contained in:
@@ -72,6 +72,9 @@ Promise.all([
|
||||
container.authRoutes = new Routes.AuthRoutes(container)
|
||||
container.userRoutes = new Routes.UserRoutes(container)
|
||||
container.assetRoutes = new Routes.AssetRoutes(container)
|
||||
container.workItemRoutes = new Routes.WorkItemRoutes(container)
|
||||
container.teamRoutes = new Routes.TeamRoutes(container)
|
||||
container.activityRoutes = new Routes.ActivityRoutes(container)
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.status(404).json({
|
||||
|
||||
153
server/src/api/routes/ActivityRoutes.js
Normal file
153
server/src/api/routes/ActivityRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import passport from 'passport'
|
||||
import createError from 'http-errors'
|
||||
import autobind from 'autobind-decorator'
|
||||
|
||||
@autobind
|
||||
export class ActivityRoutes {
|
||||
constructor(container) {
|
||||
const app = container.app
|
||||
|
||||
this.log = container.log
|
||||
this.db = container.db
|
||||
this.mq = container.mq
|
||||
this.ws = container.ws
|
||||
|
||||
app.route('/activities')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listActivitys)
|
||||
.post(passport.authenticate('bearer', { session: false }), this.createActivity)
|
||||
.put(passport.authenticate('bearer', { session: false }), this.updateActivity)
|
||||
|
||||
app.route('/activities/:_id([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getActivity)
|
||||
.delete(passport.authenticate('bearer', { session: false }), this.deleteActivity)
|
||||
}
|
||||
|
||||
listActivitys(req, res, next) {
|
||||
const Activity = this.db.Activity
|
||||
let limit = req.params.limit || 20
|
||||
let skip = req.params.skip || 0
|
||||
let partial = !!req.params.partial
|
||||
let branch = req.params.branch
|
||||
let query = {}
|
||||
|
||||
if (branch) {
|
||||
query.branch = branch
|
||||
}
|
||||
|
||||
Activity.count({}).then((total) => {
|
||||
let activities = []
|
||||
let cursor = Activity.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||
return doc.toClient(partial)
|
||||
})
|
||||
|
||||
cursor.on('data', (doc) => {
|
||||
activities.push(doc)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: total,
|
||||
offset: skip,
|
||||
count: activities.length,
|
||||
items: activities
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
createActivity(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
// Create a new Activity template then assign it to a value in the req.body
|
||||
const Activity = this.db.Activity
|
||||
let activity = new Activity(req.body)
|
||||
|
||||
// Save the activity (with promise) - If it doesnt, catch and throw error
|
||||
activity.save().then((newActivity) => {
|
||||
res.json(newActivity.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
updateActivity(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
// Do this here because Mongoose will add it automatically otherwise
|
||||
if (!req.body._id) {
|
||||
return next(createError.BadRequest('No _id given in body'))
|
||||
}
|
||||
|
||||
let Activity = this.db.Activity
|
||||
let activityUpdates = null
|
||||
|
||||
try {
|
||||
activityUpdates = new Activity(req.body)
|
||||
} catch (err) {
|
||||
return next(createError.BadRequest('Invalid data'))
|
||||
}
|
||||
|
||||
Activity.findById(activityUpdates._id).then((foundActivity) => {
|
||||
if (!foundActivity) {
|
||||
return next(createError.NotFound(`Activity with _id ${_id} was not found`))
|
||||
}
|
||||
foundActivity.merge(activityUpdates)
|
||||
return foundActivity.save()
|
||||
}).then((savedActivity) => {
|
||||
res.json(savedActivity.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
getActivity(req, res, next) {
|
||||
const Activity = this.db.Activity
|
||||
const _id = req.params._id
|
||||
|
||||
Activity.findById(_id).then((activity) => {
|
||||
if (!activity) {
|
||||
return next(createError.NotFound(`Activity with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json(activity.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
deleteActivity(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
const Activity = this.db.Activity
|
||||
const _id = req.params._id
|
||||
|
||||
Activity.remove({ _id }).then((activity) => {
|
||||
if (!activity) {
|
||||
return next(createError.NotFound(`Activity with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json({})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,493 +0,0 @@
|
||||
import passport from 'passport'
|
||||
import createError from 'http-errors'
|
||||
import { makeFingerprint } from '../makeFingerprint'
|
||||
import autobind from 'autobind-decorator'
|
||||
|
||||
@autobind
|
||||
export class ProjectRoutes {
|
||||
constructor(container) {
|
||||
const app = container.app
|
||||
|
||||
this.log = container.log
|
||||
this.db = container.db
|
||||
this.mq = container.mq
|
||||
this.ws = container.ws
|
||||
|
||||
app.route('/projects')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listProjects)
|
||||
.post(passport.authenticate('bearer', { session: false }), this.createProject)
|
||||
.put(passport.authenticate('bearer', { session: false }), this.updateProject)
|
||||
|
||||
app.route('/projects/:_id([a-f0-9]{24})/broker/:brokerId([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getProjectBrokerClientData)
|
||||
|
||||
app.route('/projects/:_id([a-f0-9]{24})/broker/:brokerId([a-f0-9]{24})/sign-off')
|
||||
.post(passport.authenticate('bearer', { session: false }), this.signOffProjectBrokerClientData)
|
||||
|
||||
app.route('/projects/:projectId([a-f0-9]{24})/create-packages')
|
||||
.post(passport.authenticate('bearer', { session: false }), this.createProjectPackages)
|
||||
|
||||
app.route('/projects/:projectId([a-f0-9]{24})/reset-packages')
|
||||
.post(passport.authenticate('bearer', { session: false }), this.resetProjectPackages)
|
||||
|
||||
app.route('/projects/:projectId([a-f0-9]{24})/build-pdfs')
|
||||
.post(passport.authenticate('bearer', { session: false }), this.buildProjectPDFs)
|
||||
|
||||
app.route('/projects/:_id([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getProject)
|
||||
.delete(passport.authenticate('bearer', { session: false }), this.deleteProject)
|
||||
|
||||
app.route('/projects/import-client-data')
|
||||
.post(passport.authenticate('bearer', { session: false }), this.importProjectClientData)
|
||||
|
||||
app.route('/projects/:_id([a-f0-9]{24})/populated')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getPopulatedProject)
|
||||
|
||||
app.route('/projects/dashboard')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listDashboardProjects)
|
||||
|
||||
app.route('/projects/broker/:_id([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listBrokerProjects)
|
||||
}
|
||||
|
||||
listProjects(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
let limit = req.params.limit || 20
|
||||
let skip = req.params.skip || 0
|
||||
let partial = !!req.params.partial
|
||||
let branch = req.params.branch
|
||||
let query = {}
|
||||
|
||||
if (branch) {
|
||||
query.branch = branch
|
||||
}
|
||||
|
||||
Project.count({}).then((total) => {
|
||||
let projects = []
|
||||
let cursor = Project.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||
return doc.toClient(partial)
|
||||
})
|
||||
|
||||
cursor.on('data', (doc) => {
|
||||
projects.push(doc)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: total,
|
||||
offset: skip,
|
||||
count: projects.length,
|
||||
items: projects
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
listDashboardProjects(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
|
||||
let projects = []
|
||||
let cursor = Project.find({}).select('_id name fingerprint branch').populate({
|
||||
path: 'branch', select: '_id name fingerprint corporation', populate: {
|
||||
path: 'corporation', select: '_id name imageId fingerprint'
|
||||
}
|
||||
}).cursor()
|
||||
|
||||
cursor.on('data', (project) => {
|
||||
projects.push(project)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: projects.length,
|
||||
offset: 0,
|
||||
count: projects.length,
|
||||
items: projects
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
listBrokerProjects(req, res, next) {
|
||||
const brokerId = req.params._id
|
||||
const Project = this.db.Project
|
||||
let projects = []
|
||||
let cursor = Project.find({ brokers: brokerId }).select('_id name clientData').cursor()
|
||||
|
||||
cursor.on('data', (project) => {
|
||||
projects.push(project)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: projects.length,
|
||||
offset: 0,
|
||||
count: projects.length,
|
||||
items: projects
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
createProject(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
// Create a new Project template then assign it to a value in the req.body
|
||||
const Project = this.db.Project
|
||||
let project = new Project(req.body)
|
||||
|
||||
project.fingerprint = makeFingerprint(project.name)
|
||||
|
||||
// Save the project (with promise) - If it doesnt, catch and throw error
|
||||
project.save().then((newProject) => {
|
||||
res.json(newProject.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
updateProject(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
// Do this here because Mongoose will add it automatically otherwise
|
||||
if (!req.body._id) {
|
||||
return next(createError.BadRequest('No _id given in body'))
|
||||
}
|
||||
|
||||
let Project = this.db.Project
|
||||
let projectUpdates = null
|
||||
|
||||
try {
|
||||
projectUpdates = new Project(req.body)
|
||||
} catch (err) {
|
||||
return next(createError.BadRequest('Invalid data'))
|
||||
}
|
||||
|
||||
if (projectUpdates.name) {
|
||||
projectUpdates.fingerprint = makeFingerprint(projectUpdates.name)
|
||||
}
|
||||
|
||||
Project.findById(projectUpdates._id).then((foundProject) => {
|
||||
if (!foundProject) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} was not found`))
|
||||
}
|
||||
foundProject.merge(projectUpdates)
|
||||
return foundProject.save()
|
||||
}).then((savedProject) => {
|
||||
res.json(savedProject.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
importProjectClientData(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
if (role !== 'broker' && role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
const { _id, brokerId, assetId } = req.body
|
||||
|
||||
if (!_id || !brokerId || !assetId) {
|
||||
return next(createError.BadRequest('Must specify _id, brokerId and assetId'))
|
||||
}
|
||||
|
||||
this.mq.request('dar-import', 'importClientData', {
|
||||
projectId: _id,
|
||||
brokerId: brokerId,
|
||||
assetId: assetId,
|
||||
passback: {
|
||||
rooms: [ req.user._id ],
|
||||
projectId: _id,
|
||||
brokerId: brokerId,
|
||||
routerName: 'projectRoutes',
|
||||
funcName: 'completeImportClientData'
|
||||
}
|
||||
}).then((correlationId) => {
|
||||
res.json({ correlationId })
|
||||
}).catch((err) => {
|
||||
// TODO: Should delete the asset
|
||||
next(createError.InternalServerError('Unable to import uploaded file to project'))
|
||||
})
|
||||
}
|
||||
|
||||
completeImportClientData(passback, error, data) {
|
||||
if (!passback.rooms) {
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {
|
||||
brokerId: passback.brokerId,
|
||||
projectId: passback.projectId,
|
||||
}
|
||||
|
||||
if (error) {
|
||||
obj.problems = error.problems
|
||||
obj.error = error.message
|
||||
}
|
||||
|
||||
this.ws.notify(passback.rooms, 'clientDataImportComplete', obj)
|
||||
}
|
||||
|
||||
getProject(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
const _id = req.params._id
|
||||
|
||||
Project.findById(_id).then((project) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json(project.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
getPopulatedProject(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
const _id = req.params._id
|
||||
|
||||
Project.findById(_id).then((project) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
return project.populate({ path: 'brokers', select: '_id firstName lastName email thumbnailImageId t12 aum numHouseholds homePhone cellPhone' }).execPopulate()
|
||||
}).then((project) => {
|
||||
res.json(project.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
getProjectBrokerClientData(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
const _id = req.params._id
|
||||
const brokerId = req.params.brokerId
|
||||
|
||||
Project.findById(_id).select('clientData').then((project) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
if (!project.clientData) {
|
||||
return res.json({})
|
||||
}
|
||||
|
||||
const clientData = project.clientData.find(data => data.brokerId.toString() === brokerId)
|
||||
|
||||
if (clientData) {
|
||||
res.json(clientData)
|
||||
} else {
|
||||
res.json({})
|
||||
}
|
||||
}).catch((error) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
signOffProjectBrokerClientData(req, res, next) {
|
||||
const Project = this.db.Project
|
||||
const _id = req.params._id
|
||||
const brokerId = req.params.brokerId
|
||||
|
||||
Project.findById(_id).then((project) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
for (let clientData of project.clientData) {
|
||||
if (clientData.brokerId && clientData.brokerId.toString() === brokerId) {
|
||||
if (clientData.submitted || clientData.numProblems !== 0 || clientData.problems.length !== 0 || clientData.error) {
|
||||
return next(createError.BadRequest(`Project ${_id}, broker ${brokerId} cannot be signed off at this time`))
|
||||
}
|
||||
|
||||
clientData.submitted = new Date()
|
||||
return project.save(project)
|
||||
}
|
||||
}
|
||||
|
||||
return next(createError.NotFound(`Client data for broker ${brokerId} was not found`))
|
||||
}).then((savedProject) => {
|
||||
res.json({})
|
||||
}).catch((error) => {
|
||||
next(createError.InternalServerError(error.message))
|
||||
})
|
||||
}
|
||||
|
||||
createProjectPackages(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
const { projectId } = req.params
|
||||
|
||||
this.mq.request('dar-import', 'createPackages', {
|
||||
projectId,
|
||||
passback: {
|
||||
rooms: [ req.user._id ], // TODO: Add a room for the specific project
|
||||
projectId,
|
||||
routerName: 'projectRoutes',
|
||||
funcName: 'completeCreatePackageData'
|
||||
}
|
||||
}).then((correlationId) => {
|
||||
res.json({ correlationId })
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError('Unable to create package data'))
|
||||
})
|
||||
}
|
||||
|
||||
resetProjectPackages(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
const { projectId } = req.params
|
||||
const Package = this.db.Package
|
||||
const cursor = Package.find({ project: projectId }).cursor()
|
||||
let totalPDFs = 0
|
||||
let totalPackages = 0
|
||||
|
||||
new Promise((resolve, reject) => {
|
||||
cursor.on('data', (pkg) => {
|
||||
pkg.remove().then((pkg) => {
|
||||
if (pkg.assetId) {
|
||||
totalPDFs += 1
|
||||
return this.db.gridfs.remove({ _id: pkg.assetId })
|
||||
}
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
|
||||
totalPackages += 1
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
resolve()
|
||||
})
|
||||
cursor.on('error', (error) => {
|
||||
reject(error)
|
||||
})
|
||||
}).then(() => {
|
||||
res.json({ totalPackages, totalPDFs })
|
||||
}).catch((error) => {
|
||||
next(createError.InternalServerError('Unable to delete all project packages'))
|
||||
})
|
||||
}
|
||||
|
||||
completeCreatePackageData(passback, error, data) {
|
||||
if (!passback.rooms) {
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {
|
||||
projectId: passback.projectId,
|
||||
}
|
||||
|
||||
if (error) {
|
||||
obj.problems = error.problems
|
||||
obj.error = error.message
|
||||
}
|
||||
|
||||
this.ws.notify(passback.rooms, 'packageGenerationComplete', obj)
|
||||
}
|
||||
|
||||
buildProjectPDFs(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
const projectId = req.params.projectId
|
||||
const Package = this.db.Package
|
||||
let total = 0
|
||||
let cursor = Package.find({ project: projectId }).cursor()
|
||||
|
||||
cursor.on('data', (pkg) => {
|
||||
const packageId = pkg._id
|
||||
this.mq.request('dar-pdf', 'createPackagePDF', {
|
||||
packageId,
|
||||
passback: {
|
||||
rooms: [ req.user._id ], // TODO: Add a room for the specific project
|
||||
packageId,
|
||||
routerName: 'projectRoutes',
|
||||
funcName: 'completeCreatePackagePDF'
|
||||
}
|
||||
}).then((correlationId) => {
|
||||
res.json({ correlationId })
|
||||
}).catch((err) => {
|
||||
// TODO: Collect errors and return to user
|
||||
})
|
||||
total += 1
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({ total })
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
completeCreatePackagePDF(passback, error, data) {
|
||||
if (!passback.rooms) {
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {
|
||||
packageId: passback.packageId,
|
||||
}
|
||||
|
||||
if (error) {
|
||||
obj.problems = error.problems
|
||||
obj.error = error.message
|
||||
} else {
|
||||
obj.assetId = data.assetId
|
||||
}
|
||||
|
||||
this.ws.notify(passback.rooms, 'createPackagePDFComplete', obj)
|
||||
}
|
||||
|
||||
deleteProject(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
const Project = this.db.Project
|
||||
const _id = req.params._id
|
||||
|
||||
Project.remove({ _id }).then((project) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json({})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
}
|
||||
153
server/src/api/routes/TeamRoutes.js
Normal file
153
server/src/api/routes/TeamRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import passport from 'passport'
|
||||
import createError from 'http-errors'
|
||||
import autobind from 'autobind-decorator'
|
||||
|
||||
@autobind
|
||||
export class TeamRoutes {
|
||||
constructor(container) {
|
||||
const app = container.app
|
||||
|
||||
this.log = container.log
|
||||
this.db = container.db
|
||||
this.mq = container.mq
|
||||
this.ws = container.ws
|
||||
|
||||
app.route('/teams')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listTeams)
|
||||
.post(passport.authenticate('bearer', { session: false }), this.createTeam)
|
||||
.put(passport.authenticate('bearer', { session: false }), this.updateTeam)
|
||||
|
||||
app.route('/teams/:_id([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getTeam)
|
||||
.delete(passport.authenticate('bearer', { session: false }), this.deleteTeam)
|
||||
}
|
||||
|
||||
listTeams(req, res, next) {
|
||||
const Team = this.db.Team
|
||||
let limit = req.params.limit || 20
|
||||
let skip = req.params.skip || 0
|
||||
let partial = !!req.params.partial
|
||||
let branch = req.params.branch
|
||||
let query = {}
|
||||
|
||||
if (branch) {
|
||||
query.branch = branch
|
||||
}
|
||||
|
||||
Team.count({}).then((total) => {
|
||||
let teams = []
|
||||
let cursor = Team.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||
return doc.toClient(partial)
|
||||
})
|
||||
|
||||
cursor.on('data', (doc) => {
|
||||
teams.push(doc)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: total,
|
||||
offset: skip,
|
||||
count: teams.length,
|
||||
items: teams
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
createTeam(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
// Create a new Team template then assign it to a value in the req.body
|
||||
const Team = this.db.Team
|
||||
let team = new Team(req.body)
|
||||
|
||||
// Save the team (with promise) - If it doesnt, catch and throw error
|
||||
team.save().then((newTeam) => {
|
||||
res.json(newTeam.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
updateTeam(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
// Do this here because Mongoose will add it automatically otherwise
|
||||
if (!req.body._id) {
|
||||
return next(createError.BadRequest('No _id given in body'))
|
||||
}
|
||||
|
||||
let Team = this.db.Team
|
||||
let teamUpdates = null
|
||||
|
||||
try {
|
||||
teamUpdates = new Team(req.body)
|
||||
} catch (err) {
|
||||
return next(createError.BadRequest('Invalid data'))
|
||||
}
|
||||
|
||||
Team.findById(teamUpdates._id).then((foundTeam) => {
|
||||
if (!foundTeam) {
|
||||
return next(createError.NotFound(`Team with _id ${_id} was not found`))
|
||||
}
|
||||
foundTeam.merge(teamUpdates)
|
||||
return foundTeam.save()
|
||||
}).then((savedTeam) => {
|
||||
res.json(savedTeam.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
getTeam(req, res, next) {
|
||||
const Team = this.db.Team
|
||||
const _id = req.params._id
|
||||
|
||||
Team.findById(_id).then((team) => {
|
||||
if (!team) {
|
||||
return next(createError.NotFound(`Team with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json(team.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
deleteTeam(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
const Team = this.db.Team
|
||||
const _id = req.params._id
|
||||
|
||||
Team.remove({ _id }).then((team) => {
|
||||
if (!project) {
|
||||
return next(createError.NotFound(`Team with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json({})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
}
|
||||
153
server/src/api/routes/WorkItemRoutes.js
Normal file
153
server/src/api/routes/WorkItemRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import passport from 'passport'
|
||||
import createError from 'http-errors'
|
||||
import autobind from 'autobind-decorator'
|
||||
|
||||
@autobind
|
||||
export class WorkItemRoutes {
|
||||
constructor(container) {
|
||||
const app = container.app
|
||||
|
||||
this.log = container.log
|
||||
this.db = container.db
|
||||
this.mq = container.mq
|
||||
this.ws = container.ws
|
||||
|
||||
app.route('/workitems')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.listWorkItems)
|
||||
.post(passport.authenticate('bearer', { session: false }), this.createWorkItem)
|
||||
.put(passport.authenticate('bearer', { session: false }), this.updateWorkItem)
|
||||
|
||||
app.route('/workitems/:_id([a-f0-9]{24})')
|
||||
.get(passport.authenticate('bearer', { session: false }), this.getWorkItem)
|
||||
.delete(passport.authenticate('bearer', { session: false }), this.deleteWorkItem)
|
||||
}
|
||||
|
||||
listWorkItems(req, res, next) {
|
||||
const WorkItem = this.db.WorkItem
|
||||
let limit = req.params.limit || 20
|
||||
let skip = req.params.skip || 0
|
||||
let partial = !!req.params.partial
|
||||
let branch = req.params.branch
|
||||
let query = {}
|
||||
|
||||
if (branch) {
|
||||
query.branch = branch
|
||||
}
|
||||
|
||||
WorkItem.count({}).then((total) => {
|
||||
let workItems = []
|
||||
let cursor = WorkItem.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||
return doc.toClient(partial)
|
||||
})
|
||||
|
||||
cursor.on('data', (doc) => {
|
||||
workItems.push(doc)
|
||||
})
|
||||
cursor.on('end', () => {
|
||||
res.json({
|
||||
total: total,
|
||||
offset: skip,
|
||||
count: workItems.length,
|
||||
items: workItems
|
||||
})
|
||||
})
|
||||
cursor.on('error', (err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
createWorkItem(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return next(new createError.Forbidden())
|
||||
}
|
||||
|
||||
// Create a new WorkItem template then assign it to a value in the req.body
|
||||
const WorkItem = this.db.WorkItem
|
||||
let workItem = new WorkItem(req.body)
|
||||
|
||||
// Save the workItem (with promise) - If it doesnt, catch and throw error
|
||||
workItem.save().then((newWorkItem) => {
|
||||
res.json(newWorkItem.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
updateWorkItem(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
// Do this here because Mongoose will add it automatically otherwise
|
||||
if (!req.body._id) {
|
||||
return next(createError.BadRequest('No _id given in body'))
|
||||
}
|
||||
|
||||
let WorkItem = this.db.WorkItem
|
||||
let workItemUpdates = null
|
||||
|
||||
try {
|
||||
workItemUpdates = new WorkItem(req.body)
|
||||
} catch (err) {
|
||||
return next(createError.BadRequest('Invalid data'))
|
||||
}
|
||||
|
||||
WorkItem.findById(workItemUpdates._id).then((foundWorkItem) => {
|
||||
if (!foundWorkItem) {
|
||||
return next(createError.NotFound(`WorkItem with _id ${_id} was not found`))
|
||||
}
|
||||
foundWorkItem.merge(workItemUpdates)
|
||||
return foundWorkItem.save()
|
||||
}).then((savedWorkItem) => {
|
||||
res.json(savedWorkItem.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
getWorkItem(req, res, next) {
|
||||
const WorkItem = this.db.WorkItem
|
||||
const _id = req.params._id
|
||||
|
||||
WorkItem.findById(_id).then((workItem) => {
|
||||
if (!workItem) {
|
||||
return next(createError.NotFound(`WorkItem with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json(workItem.toClient())
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
|
||||
deleteWorkItem(req, res, next) {
|
||||
const role = req.user.role
|
||||
|
||||
// If user's role is not Executive or Administrator, return an error
|
||||
if (role !== 'executive' && role !== 'administrator') {
|
||||
return new createError.Forbidden()
|
||||
}
|
||||
|
||||
const WorkItem = this.db.WorkItem
|
||||
const _id = req.params._id
|
||||
|
||||
WorkItem.remove({ _id }).then((workItem) => {
|
||||
if (!workItem) {
|
||||
return next(createError.NotFound(`WorkItem with _id ${_id} not found`))
|
||||
}
|
||||
|
||||
res.json({})
|
||||
}).catch((err) => {
|
||||
next(createError.InternalServerError(err.message))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
export { AuthRoutes } from './AuthRoutes'
|
||||
export { AssetRoutes } from './AssetRoutes'
|
||||
export { UserRoutes } from './UserRoutes'
|
||||
export { WorkItemRoutes } from './WorkItemRoutes'
|
||||
export { ActivityRoutes } from './ActivityRoutes'
|
||||
export { TeamRoutes } from './TeamRoutes'
|
||||
|
||||
@@ -25,6 +25,8 @@ export class DB {
|
||||
|
||||
this.User = connection.model('User', Schemas.userSchema)
|
||||
this.WorkItem = connection.model('WorkItem', Schemas.workItemSchema)
|
||||
this.Activity = connection.model('Activity', Schemas.activitySchema)
|
||||
this.Team = connection.model('Team', Schemas.teamSchema)
|
||||
|
||||
return Promise.resolve(this)
|
||||
})
|
||||
|
||||
25
server/src/database/schemas/activity.js
Normal file
25
server/src/database/schemas/activity.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
export let activitySchema = new Schema({
|
||||
_id: { type: Schema.Types.ObjectId, required: true, auto: true },
|
||||
resolution: String,
|
||||
workItem: { type: Schema.Types.ObjectId, required: true },
|
||||
status: { type: String, required: true, enum: {
|
||||
values: [ 'planned', 'open', 'onHold', 'closed'],
|
||||
message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
||||
}},
|
||||
notes: String,
|
||||
when: Date,
|
||||
loc: {
|
||||
type: { type: String },
|
||||
coordinates: [Number],
|
||||
},
|
||||
address: String,
|
||||
fromStreetNumber: Number,
|
||||
toStreetNumber: Number,
|
||||
photos: [ Schema.Types.ObjectId ],
|
||||
}, { timestamps: true, id: false })
|
||||
|
||||
activitySchema.methods.toClient = function() {
|
||||
return this.toObject()
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export { workItemSchema } from './workItem'
|
||||
export { userSchema } from './user'
|
||||
export { teamSchema } from './team'
|
||||
export { activitySchema } from './activity'
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
export let team = new Schema({
|
||||
export let teamSchema = new Schema({
|
||||
name: { type: String },
|
||||
members: { type: Schema.Types.ObjectId, required: true },
|
||||
}, { timestamps: true, id: false })
|
||||
|
||||
teamSchema.methods.toClient = function() {
|
||||
return this.toObject()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ export let userSchema = new Schema({
|
||||
},
|
||||
email: { type: String, match: regExpPattern.email, required: true, index: true, unique: true },
|
||||
newEmail: { type: String, match: regExpPattern.email },
|
||||
imageId: { type: Schema.Types.ObjectId },
|
||||
thumbnailImageId: { type: Schema.Types.ObjectId },
|
||||
emailToken: {
|
||||
type: {
|
||||
@@ -32,6 +31,7 @@ export let userSchema = new Schema({
|
||||
firstName: { type: String, required: true },
|
||||
lastName: { type: String, required: true },
|
||||
administrator: { type: Boolean, required: true },
|
||||
team: Schema.Types.ObjectId,
|
||||
}, { timestamps: true, id: false })
|
||||
|
||||
userSchema.methods.toClient = function(authUser) {
|
||||
@@ -47,7 +47,8 @@ userSchema.methods.toClient = function(authUser) {
|
||||
thumbnailImageId: this.thumbnailImageId,
|
||||
firstName: this.firstName,
|
||||
lastName: this.lastName,
|
||||
administrator: this.administrator
|
||||
administrator: this.administrator,
|
||||
team: this.team
|
||||
}
|
||||
|
||||
return user
|
||||
|
||||
@@ -7,11 +7,16 @@ export let workItemSchema = new Schema({
|
||||
values: [ 'order', 'inspection', 'complaint'],
|
||||
message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
||||
}},
|
||||
number: Number,
|
||||
loc: {
|
||||
type: { type: String },
|
||||
coordinates: [Number],
|
||||
},
|
||||
address: String,
|
||||
photos: [ Schema.Types.ObjectId ],
|
||||
details: String,
|
||||
}, { timestamps: true, id: false })
|
||||
|
||||
workItemSchema.methods.toClient = function() {
|
||||
return {
|
||||
_id: this._id,
|
||||
workItemType: this.workItemType
|
||||
}
|
||||
return this.toObject()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user