Updating worker package with the various parts of server that needed moved over.
This commit is contained in:
parent
76f330fc36
commit
9423128369
|
@ -21,6 +21,7 @@
|
|||
"dependencies": {
|
||||
"@koa/router": "^8.0.0",
|
||||
"aws-sdk": "^2.811.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"dotenv": "^8.2.0",
|
||||
"got": "^11.8.1",
|
||||
"joi": "^17.2.1",
|
||||
|
@ -33,7 +34,7 @@
|
|||
"koa-static": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"pino-pretty": "^4.0.0",
|
||||
"pouchdb": "^7.2.2",
|
||||
"pouchdb": "^7.2.1",
|
||||
"pouchdb-all-dbs": "^1.0.2",
|
||||
"server-destroy": "^1.0.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
const CouchDB = require("../../../db")
|
||||
const { StaticDatabases, generateUserID, getUserParams } = require("../../../db/utils")
|
||||
const { hash } = require("./utils")
|
||||
const { UserStatus } = require("../../../constants")
|
||||
|
||||
const USER_DB = StaticDatabases.USER.name
|
||||
|
||||
exports.userSave = async ctx => {
|
||||
const db = new CouchDB(USER_DB)
|
||||
const { email, password, _id } = ctx.request.body
|
||||
const hashedPassword = password ? await hash(password) : null
|
||||
let user = {
|
||||
...ctx.request.body,
|
||||
_id: generateUserID(email),
|
||||
password: hashedPassword,
|
||||
}, dbUser
|
||||
// in-case user existed already
|
||||
if (_id) {
|
||||
dbUser = await db.get(_id)
|
||||
}
|
||||
// add the active status to a user if its not provided
|
||||
if (user.status == null) {
|
||||
user.status = UserStatus.ACTIVE
|
||||
}
|
||||
try {
|
||||
const response = await db.post({
|
||||
password: hashedPassword || dbUser.password,
|
||||
...user,
|
||||
})
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
email,
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.status === 409) {
|
||||
ctx.throw(400, "User exists already")
|
||||
} else {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.userDelete = async ctx => {
|
||||
const db = new CouchDB(USER_DB)
|
||||
await db.destroy(generateUserID(ctx.params.email))
|
||||
ctx.body = {
|
||||
message: `User ${ctx.params.email} deleted.`,
|
||||
}
|
||||
}
|
||||
|
||||
// called internally by app server user fetch
|
||||
exports.userFetch = async ctx => {
|
||||
const db = new CouchDB(USER_DB)
|
||||
const users = (
|
||||
await db.allDocs(
|
||||
getUserParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
).rows.map(row => row.doc)
|
||||
// user hashed password shouldn't ever be returned
|
||||
for (let user of users) {
|
||||
if (user) {
|
||||
delete user.password
|
||||
}
|
||||
}
|
||||
ctx.body = users
|
||||
}
|
||||
|
||||
// called internally by app server user find
|
||||
exports.userFind = async ctx => {
|
||||
const db = new CouchDB(USER_DB)
|
||||
const user = await db.get(generateUserID(ctx.params.email))
|
||||
if (user) {
|
||||
delete user.password
|
||||
}
|
||||
ctx.body = user
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
const bcrypt = require("bcryptjs")
|
||||
const env = require("../environment")
|
||||
|
||||
const SALT_ROUNDS = env.SALT_ROUNDS || 10
|
||||
|
||||
exports.hash = async data => {
|
||||
const salt = await bcrypt.genSalt(SALT_ROUNDS)
|
||||
return bcrypt.hash(data, salt)
|
||||
}
|
||||
|
||||
exports.compare = async (data, encrypted) => {
|
||||
return bcrypt.compare(data, encrypted)
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
const env = require("../../environment")
|
||||
const got = require("got")
|
||||
const AWS = require("aws-sdk")
|
||||
|
||||
const APP_BUCKET = "app-assets"
|
||||
// this doesn't matter in self host
|
||||
const REGION = "eu-west-1"
|
||||
const PUBLIC_READ_POLICY = {
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
{
|
||||
Effect: "Allow",
|
||||
Principal: {
|
||||
AWS: ["*"],
|
||||
},
|
||||
Action: "s3:GetObject",
|
||||
Resource: [`arn:aws:s3:::${APP_BUCKET}/*`],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
async function getCouchSession() {
|
||||
// fetch session token for the api user
|
||||
const session = await got.post(`${env.COUCH_DB_URL}/_session`, {
|
||||
responseType: "json",
|
||||
credentials: "include",
|
||||
json: {
|
||||
username: env.COUCH_DB_USERNAME,
|
||||
password: env.COUCH_DB_PASSWORD,
|
||||
},
|
||||
})
|
||||
|
||||
const cookie = session.headers["set-cookie"][0]
|
||||
// Get the session cookie value only
|
||||
return cookie.split(";")[0]
|
||||
}
|
||||
|
||||
async function getMinioSession() {
|
||||
AWS.config.update({
|
||||
accessKeyId: env.MINIO_ACCESS_KEY,
|
||||
secretAccessKey: env.MINIO_SECRET_KEY,
|
||||
})
|
||||
|
||||
// make sure the bucket exists
|
||||
const objClient = new AWS.S3({
|
||||
endpoint: env.MINIO_URL,
|
||||
region: REGION,
|
||||
s3ForcePathStyle: true, // needed with minio?
|
||||
params: {
|
||||
Bucket: APP_BUCKET,
|
||||
},
|
||||
})
|
||||
// make sure the bucket exists
|
||||
try {
|
||||
await objClient
|
||||
.headBucket({
|
||||
Bucket: APP_BUCKET,
|
||||
})
|
||||
.promise()
|
||||
} catch (err) {
|
||||
// bucket doesn't exist create it
|
||||
if (err.statusCode === 404) {
|
||||
await objClient
|
||||
.createBucket({
|
||||
Bucket: APP_BUCKET,
|
||||
})
|
||||
.promise()
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
// always make sure policy is correct
|
||||
await objClient
|
||||
.putBucketPolicy({
|
||||
Bucket: APP_BUCKET,
|
||||
Policy: JSON.stringify(PUBLIC_READ_POLICY),
|
||||
})
|
||||
.promise()
|
||||
// Ideally want to send back some pre-signed URLs for files that are to be uploaded
|
||||
return {
|
||||
accessKeyId: env.MINIO_ACCESS_KEY,
|
||||
secretAccessKey: env.MINIO_SECRET_KEY,
|
||||
}
|
||||
}
|
||||
|
||||
exports.deploy = async ctx => {
|
||||
ctx.body = {
|
||||
couchDbSession: await getCouchSession(),
|
||||
bucket: APP_BUCKET,
|
||||
objectStoreSession: await getMinioSession(),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/admin")
|
||||
const authorized = require("../../../middleware/authorized")
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.post("/api/admin/users", authorized, controller.userSave)
|
||||
.delete("/api/admin/users/:email", authorized, controller.userDelete)
|
||||
.get("/api/admin/users", authorized, controller.userFetch)
|
||||
.get("/api/admin/users/:email", authorized, controller.userFind)
|
||||
|
||||
module.exports = router
|
|
@ -1,9 +0,0 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../controllers/deploy")
|
||||
const checkKey = require("../../middleware/check-key")
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.post("/api/deploy", checkKey, controller.deploy)
|
||||
|
||||
module.exports = router
|
|
@ -1,4 +1,4 @@
|
|||
const deployRoutes = require("./deploy")
|
||||
const adminRoutes = require("./admin")
|
||||
const appRoutes = require("./app")
|
||||
|
||||
exports.routes = [deployRoutes, appRoutes]
|
||||
exports.routes = [adminRoutes, appRoutes]
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
exports.UserStatus = {
|
||||
ACTIVE: "active",
|
||||
INACTIVE: "inactive",
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
exports.StaticDatabases = {
|
||||
USER: {
|
||||
name: "user-db",
|
||||
}
|
||||
}
|
||||
|
||||
const DocumentTypes = {
|
||||
USER: "us"
|
||||
}
|
||||
|
||||
const UNICODE_MAX = "\ufff0"
|
||||
const SEPARATOR = "_"
|
||||
|
||||
/**
|
||||
* Generates a new user ID based on the passed in email.
|
||||
* @param {string} email The email which the ID is going to be built up of.
|
||||
* @returns {string} The new user ID which the user doc can be stored under.
|
||||
*/
|
||||
exports.generateUserID = email => {
|
||||
return `${DocumentTypes.USER}${SEPARATOR}${email}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameters for retrieving users, this is a utility function for the getDocParams function.
|
||||
*/
|
||||
exports.getUserParams = (email = "", otherProps = {}) => {
|
||||
return {
|
||||
...otherProps,
|
||||
startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`,
|
||||
endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`,
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@ module.exports = {
|
|||
MINIO_URL: process.env.MINIO_URL,
|
||||
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
||||
LOG_LEVEL: process.env.LOG_LEVEL,
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
||||
/* TODO: to remove - once deployment removed */
|
||||
SELF_HOST_KEY: process.env.SELF_HOST_KEY,
|
||||
COUCH_DB_USERNAME: process.env.COUCH_DB_USERNAME,
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Check the user token, used when creating admin resources, like for example
|
||||
* a global user record.
|
||||
*/
|
||||
module.exports = async (ctx, next) => {
|
||||
next()
|
||||
}
|
|
@ -285,6 +285,11 @@ base64-js@^1.0.2, base64-js@^1.3.1:
|
|||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
bcryptjs@^2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
||||
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
|
@ -1813,7 +1818,7 @@ pouchdb-promise@5.4.3:
|
|||
dependencies:
|
||||
lie "3.0.4"
|
||||
|
||||
pouchdb@^7.2.2:
|
||||
pouchdb@^7.2.1:
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.2.2.tgz#fcae82862db527e4cf7576ed8549d1384961f364"
|
||||
integrity sha512-5gf5nw5XH/2H/DJj8b0YkvG9fhA/4Jt6kL0Y8QjtztVjb1y4J19Rg4rG+fUbXu96gsUrlyIvZ3XfM0b4mogGmw==
|
||||
|
|
Loading…
Reference in New Issue