2020-05-07 21:53:34 +12:00
|
|
|
const jwt = require("jsonwebtoken")
|
|
|
|
const CouchDB = require("../../db")
|
|
|
|
const bcrypt = require("../../utilities/bcrypt")
|
2020-10-29 09:35:06 +13:00
|
|
|
const env = require("../../environment")
|
2020-10-08 05:56:47 +13:00
|
|
|
const { getAPIKey } = require("../../utilities/usageQuota")
|
2021-04-10 02:11:49 +12:00
|
|
|
const { generateUserMetadataID } = require("../../db/utils")
|
2020-11-04 02:45:49 +13:00
|
|
|
const { setCookie } = require("../../utilities")
|
2021-02-19 23:32:24 +13:00
|
|
|
const { outputProcessing } = require("../../utilities/rowProcessor")
|
2021-04-10 04:33:21 +12:00
|
|
|
const { InternalTables } = require("../../db/utils")
|
2021-04-09 03:58:33 +12:00
|
|
|
const { UserStatus } = require("@budibase/auth")
|
2021-04-08 03:08:29 +12:00
|
|
|
const setBuilderToken = require("../../utilities/builder/setBuilderToken")
|
2020-04-08 07:34:21 +12:00
|
|
|
|
2021-02-23 00:39:58 +13:00
|
|
|
const INVALID_ERR = "Invalid Credentials"
|
|
|
|
|
2020-04-24 01:37:08 +12:00
|
|
|
exports.authenticate = async ctx => {
|
2020-11-04 02:45:49 +13:00
|
|
|
const appId = ctx.appId
|
2020-10-29 23:28:27 +13:00
|
|
|
if (!appId) ctx.throw(400, "No appId")
|
2020-06-13 07:42:55 +12:00
|
|
|
|
2020-12-05 01:22:45 +13:00
|
|
|
const { email, password } = ctx.request.body
|
2020-04-21 03:17:11 +12:00
|
|
|
|
2020-12-05 01:22:45 +13:00
|
|
|
if (!email) ctx.throw(400, "Email Required.")
|
2020-10-29 09:35:06 +13:00
|
|
|
if (!password) ctx.throw(400, "Password Required.")
|
2020-05-06 21:33:30 +12:00
|
|
|
|
2020-12-05 01:22:45 +13:00
|
|
|
// Check the user exists in the instance DB by email
|
2020-10-29 23:28:27 +13:00
|
|
|
const db = new CouchDB(appId)
|
|
|
|
const app = await db.get(appId)
|
2020-05-06 21:33:30 +12:00
|
|
|
|
2020-05-28 04:23:01 +12:00
|
|
|
let dbUser
|
|
|
|
try {
|
2021-04-10 02:11:49 +12:00
|
|
|
dbUser = await db.get(generateUserMetadataID(email))
|
2020-05-28 04:23:01 +12:00
|
|
|
} catch (_) {
|
|
|
|
// do not want to throw a 404 - as this could be
|
2020-12-05 01:22:45 +13:00
|
|
|
// used to determine valid emails
|
2021-02-23 00:39:58 +13:00
|
|
|
ctx.throw(401, INVALID_ERR)
|
|
|
|
}
|
|
|
|
|
2021-02-23 01:29:49 +13:00
|
|
|
// check that the user is currently inactive, if this is the case throw invalid
|
|
|
|
if (dbUser.status === UserStatus.INACTIVE) {
|
2021-02-23 00:39:58 +13:00
|
|
|
ctx.throw(401, INVALID_ERR)
|
2020-05-28 04:23:01 +12:00
|
|
|
}
|
2020-05-06 21:33:30 +12:00
|
|
|
|
|
|
|
// authenticate
|
2020-04-24 01:37:08 +12:00
|
|
|
if (await bcrypt.compare(password, dbUser.password)) {
|
2020-05-07 21:53:34 +12:00
|
|
|
const payload = {
|
|
|
|
userId: dbUser._id,
|
2020-12-03 02:20:56 +13:00
|
|
|
roleId: dbUser.roleId,
|
2020-11-04 03:30:20 +13:00
|
|
|
version: app.version,
|
2020-05-07 21:53:34 +12:00
|
|
|
}
|
2021-03-25 07:21:23 +13:00
|
|
|
// if in prod add the user api key, unless self hosted
|
2021-03-11 01:20:07 +13:00
|
|
|
/* istanbul ignore next */
|
2021-03-25 07:21:23 +13:00
|
|
|
if (env.isProd() && !env.SELF_HOSTED) {
|
2021-03-30 05:32:05 +13:00
|
|
|
const { apiKey } = await getAPIKey(ctx.appId)
|
2020-10-10 09:42:20 +13:00
|
|
|
payload.apiKey = apiKey
|
2020-10-07 07:13:41 +13:00
|
|
|
}
|
2020-05-07 07:29:47 +12:00
|
|
|
|
|
|
|
const token = jwt.sign(payload, ctx.config.jwtSecret, {
|
2020-05-07 21:53:34 +12:00
|
|
|
expiresIn: "1 day",
|
|
|
|
})
|
2020-05-07 07:49:21 +12:00
|
|
|
|
2021-01-29 07:30:59 +13:00
|
|
|
setCookie(ctx, token, appId)
|
2020-05-07 07:29:47 +12:00
|
|
|
|
2020-11-03 09:14:10 +13:00
|
|
|
delete dbUser.password
|
2020-05-06 21:33:30 +12:00
|
|
|
ctx.body = {
|
|
|
|
token,
|
2020-05-07 21:53:34 +12:00
|
|
|
...dbUser,
|
2020-11-03 09:14:10 +13:00
|
|
|
appId,
|
2020-05-07 21:53:34 +12:00
|
|
|
}
|
2020-04-24 01:37:08 +12:00
|
|
|
} else {
|
2021-02-23 00:39:58 +13:00
|
|
|
ctx.throw(401, INVALID_ERR)
|
2020-04-24 01:37:08 +12:00
|
|
|
}
|
2020-05-07 21:53:34 +12:00
|
|
|
}
|
2021-01-29 03:29:35 +13:00
|
|
|
|
2021-04-08 03:08:29 +12:00
|
|
|
exports.builderLogin = async ctx => {
|
|
|
|
await setBuilderToken(ctx)
|
|
|
|
ctx.status = 200
|
|
|
|
}
|
|
|
|
|
2021-01-29 03:29:35 +13:00
|
|
|
exports.fetchSelf = async ctx => {
|
|
|
|
const { userId, appId } = ctx.user
|
2021-03-11 01:20:07 +13:00
|
|
|
/* istanbul ignore next */
|
2021-01-29 03:29:35 +13:00
|
|
|
if (!userId || !appId) {
|
|
|
|
ctx.body = {}
|
2021-02-19 23:32:24 +13:00
|
|
|
return
|
|
|
|
}
|
|
|
|
const db = new CouchDB(appId)
|
|
|
|
const user = await db.get(userId)
|
2021-04-10 04:33:21 +12:00
|
|
|
const userTable = await db.get(InternalTables.USER_METADATA)
|
2021-02-19 23:32:24 +13:00
|
|
|
if (user) {
|
|
|
|
delete user.password
|
2021-01-29 03:29:35 +13:00
|
|
|
}
|
2021-02-19 23:32:24 +13:00
|
|
|
// specifically needs to make sure is enriched
|
|
|
|
ctx.body = await outputProcessing(appId, userTable, user)
|
2021-01-29 03:29:35 +13:00
|
|
|
}
|