SectionList on home screen with API

This commit is contained in:
John Lyon-Smith
2018-04-08 18:33:21 -07:00
parent 5634acb967
commit 7891bb71c9
19 changed files with 1278 additions and 1201 deletions

View File

@@ -1,11 +1,12 @@
import passport from 'passport'
import createError from 'http-errors'
import crypto from 'crypto'
import urlSafeBase64 from 'urlsafe-base64'
import url from 'url'
import util from 'util'
import autobind from 'autobind-decorator'
import config from 'config'
import passport from "passport"
import createError from "http-errors"
import crypto from "crypto"
import urlSafeBase64 from "urlsafe-base64"
import url from "url"
import util from "util"
import autobind from "autobind-decorator"
import config from "config"
import { catchAll } from "."
@autobind
export class UserRoutes {
@@ -16,23 +17,48 @@ export class UserRoutes {
this.db = container.db
this.mq = container.mq
this.ws = container.ws
this.maxEmailTokenAgeInHours = config.get('email.maxEmailTokenAgeInHours')
this.sendEmail = config.get('email.sendEmail')
app.route('/users')
.get(passport.authenticate('bearer', { session: false }), this.listUsers)
this.maxEmailTokenAgeInHours = config.get("email.maxEmailTokenAgeInHours")
this.sendEmail = config.get("email.sendEmail")
app
.route("/users")
.get(
passport.authenticate("bearer", { session: false }),
catchAll(this.listUsers)
)
// Add a new user, send email confirmation email
.post(passport.authenticate('bearer', { session: false }), this.createUser)
.put(passport.authenticate('bearer', { session: false }), this.updateUser)
.post(
passport.authenticate("bearer", { session: false }),
catchAll(this.createUser)
)
.put(
passport.authenticate("bearer", { session: false }),
catchAll(this.updateUser)
)
app.route('/users/:_id([a-f0-9]{24})')
.get(passport.authenticate('bearer', { session: false }), this.getUser)
.delete(passport.authenticate('bearer', { session: false }), this.deleteUser)
app
.route("/users/:_id([a-f0-9]{24})")
.get(
passport.authenticate("bearer", { session: false }),
catchAll(this.getUser)
)
.delete(
passport.authenticate("bearer", { session: false }),
catchAll(this.deleteUser)
)
app.route('/users/enter-room/:roomName')
.put(passport.authenticate('bearer', { session: false }), this.enterRoom)
app
.route("/users/enter-room/:roomName")
.put(
passport.authenticate("bearer", { session: false }),
catchAll(this.enterRoom)
)
app.route('/users/leave-room')
.put(passport.authenticate('bearer', { session: false }), this.leaveRoom)
app
.route("/users/leave-room")
.put(
passport.authenticate("bearer", { session: false }),
catchAll(this.leaveRoom)
)
}
async listUsers(req, res, next) {
@@ -44,169 +70,145 @@ export class UserRoutes {
const team = req.query.team
let query = {}
try {
if (team) {
query = { team }
}
if (team) {
query = { team }
}
if (!isAdmin) {
throw createError.Forbidden()
}
if (!isAdmin) {
throw createError.Forbidden()
}
const total = await User.count({})
let users = []
let cursor = User.find(query).limit(limit).skip(skip).cursor().map((doc) => {
const total = await User.count({})
let users = []
let cursor = User.find(query)
.limit(limit)
.skip(skip)
.cursor()
.map((doc) => {
return doc.toClient(req.user)
})
cursor.on('data', (doc) => {
users.push(doc)
cursor.on("data", (doc) => {
users.push(doc)
})
cursor.on("end", () => {
res.json({
total: total,
offset: skip,
count: users.length,
items: users,
})
cursor.on('end', () => {
res.json({
total: total,
offset: skip,
count: users.length,
items: users
})
})
cursor.on('error', (err) => {
throw err
})
} catch(err) {
if (err instanceof createError.HttpError) {
next(err)
} else {
next(createError.InternalServerError(err.message))
}
}
})
cursor.on("error", (err) => {
throw err
})
}
async getUser(req, res, next) {
let User = this.db.User
const _id = req.params._id
const isSelf = (_id === req.user._id)
const isSelf = _id === req.user._id
const isAdmin = req.user.administrator
try {
// User can see themselves, otherwise must be super user
if (!isSelf && !isAdmin) {
throw createError.Forbidden()
}
const user = await User.findById(_id)
if (!user) {
return Promise.reject(createError.NotFound(`User with _id ${_id} was not found`))
}
res.json(user.toClient(req.user))
} catch(err) {
if (err instanceof createError.HttpError) {
next(err)
} else {
next(createError.InternalServerError(err.message))
}
// User can see themselves, otherwise must be super user
if (!isSelf && !isAdmin) {
throw createError.Forbidden()
}
const user = await User.findById(_id)
if (!user) {
return Promise.reject(
createError.NotFound(`User with _id ${_id} was not found`)
)
}
res.json(user.toClient(req.user))
}
async createUser(req, res, next) {
const isAdmin = req.user.administrator
try {
if (!isAdmin) {
throw new createError.Forbidden()
}
if (!isAdmin) {
throw new createError.Forbidden()
}
let User = this.db.User
let user = new User(req.body)
let User = this.db.User
let user = new User(req.body)
// Add email confirmation required token
const buf = await util.promisify(crypto.randomBytes)(32)
// Add email confirmation required token
const buf = await util.promisify(crypto.randomBytes)(32)
user.emailToken = {
value: urlSafeBase64.encode(buf),
created: new Date()
}
const savedUser = await user.save()
const userFullName = `${savedUser.firstName} ${savedUser.lastName}`
const senderFullName = `${req.user.firstName} ${req.user.lastName}`
const siteUrl = url.parse(req.headers.referer)
const msg = {
toEmail: savedUser.email,
templateName: 'welcome',
templateData: {
recipientFullName: userFullName,
senderFullName: senderFullName,
confirmEmailLink: `${siteUrl.protocol}//${siteUrl.host}/confirm-email?email-token%3D${savedUser.emailToken.value}`,
confirmEmailLinkExpirationHours: this.maxEmailTokenAgeInHours,
supportEmail: this.supportEmail
}
}
user.emailToken = {
value: urlSafeBase64.encode(buf),
created: new Date(),
}
const savedUser = await user.save()
const userFullName = `${savedUser.firstName} ${savedUser.lastName}`
const senderFullName = `${req.user.firstName} ${req.user.lastName}`
const siteUrl = url.parse(req.headers.referer)
const msg = {
toEmail: savedUser.email,
templateName: "welcome",
templateData: {
recipientFullName: userFullName,
senderFullName: senderFullName,
confirmEmailLink: `${siteUrl.protocol}//${
siteUrl.host
}/confirm-email?email-token%3D${savedUser.emailToken.value}`,
confirmEmailLinkExpirationHours: this.maxEmailTokenAgeInHours,
supportEmail: this.supportEmail,
},
}
res.json(savedUser.toClient())
res.json(savedUser.toClient())
if (this.sendEmail) {
await this.mq.request('dar-email', 'sendEmail', msg)
}
} catch(err) {
if (err instanceof createError.HttpError) {
next(err)
} else {
next(createError.InternalServerError(err.message))
}
if (this.sendEmail) {
await this.mq.request("dar-email", "sendEmail", msg)
}
}
async updateUser(req, res, next) {
const isAdmin = req.user.administrator
try {
// Do this here because Mongoose will add it automatically otherwise
if (!req.body._id) {
throw createError.BadRequest('No user _id given in body')
}
const isSelf = (req.body._id === req.user._id.toString())
// User can change themselves, otherwise must be super user
if (!isSelf && !isAdmin) {
throw createError.Forbidden()
}
const User = this.db.User
let userUpdates = null
try {
userUpdates = new User(req.body)
} catch (err) {
throw createError.BadRequest('Invalid data')
}
if (isSelf && !isAdmin) {
throw createError.BadRequest('Cannot modify own administrator level')
}
const foundUser = await User.findById(userUpdates._id)
if (!foundUser) {
throw createError.NotFound(`User with _id ${user._id} was not found`)
}
// We don't allow direct updates to the email field so remove it if present
delete userUpdates.email
foundUser.merge(userUpdates)
const savedUser = await foundUser.save()
res.json(savedUser.toClient(req.user))
} catch (err) {
if (err instanceof createError.HttpError) {
next(err)
} else {
next(createError.InternalServerError(err.message))
}
// Do this here because Mongoose will add it automatically otherwise
if (!req.body._id) {
throw createError.BadRequest("No user _id given in body")
}
const isSelf = req.body._id === req.user._id.toString()
// User can change themselves, otherwise must be super user
if (!isSelf && !isAdmin) {
throw createError.Forbidden()
}
const User = this.db.User
let userUpdates = null
try {
userUpdates = new User(req.body)
} catch (err) {
throw createError.BadRequest("Invalid data")
}
if (isSelf && !isAdmin) {
throw createError.BadRequest("Cannot modify own administrator level")
}
const foundUser = await User.findById(userUpdates._id)
if (!foundUser) {
throw createError.NotFound(`User with _id ${user._id} was not found`)
}
// We don't allow direct updates to the email field so remove it if present
delete userUpdates.email
foundUser.merge(userUpdates)
const savedUser = await foundUser.save()
res.json(savedUser.toClient(req.user))
}
enterRoom(req, res, next) {
@@ -222,41 +224,33 @@ export class UserRoutes {
async deleteUser(req, res, next) {
const isAdmin = req.user.administrator
try {
if (!isAdmin) {
throw createError.Forbidden()
}
if (!isAdmin) {
throw createError.Forbidden()
}
let User = this.db.User
const _id = req.params._id
const deletedUser = await User.remove({ _id })
let User = this.db.User
const _id = req.params._id
const deletedUser = await User.remove({ _id })
if (!deletedUser) {
throw createError.NotFound(`User with _id ${_id} was not found`)
}
if (!deletedUser) {
throw createError.NotFound(`User with _id ${_id} was not found`)
}
const userFullName = `${deletedUser.firstName} ${deletedUser.lastName}`
const senderFullName = `${req.user.firstName} ${req.user.lastName}`
const msg = {
toEmail: deletedUser.newEmail,
templateName: 'accountDeleted',
templateData: {
recipientFullName: userFullName,
senderFullName: senderFullName,
supportEmail: this.supportEmail
}
}
res.json({})
const userFullName = `${deletedUser.firstName} ${deletedUser.lastName}`
const senderFullName = `${req.user.firstName} ${req.user.lastName}`
const msg = {
toEmail: deletedUser.newEmail,
templateName: "accountDeleted",
templateData: {
recipientFullName: userFullName,
senderFullName: senderFullName,
supportEmail: this.supportEmail,
},
}
res.json({})
if (this.sendEmail) {
await this.mq.request('dar-email', 'sendEmail', msg)
}
} catch (err) {
if (err instanceof createError.HttpError) {
next(err)
} else {
next(createError.InternalServerError(err.message))
}
if (this.sendEmail) {
await this.mq.request("dar-email", "sendEmail", msg)
}
}
}