Updating auth package to remove use of email address (bar logging in).
This commit is contained in:
parent
ade007482c
commit
e787f22daa
|
@ -12,6 +12,7 @@
|
||||||
"passport-google-auth": "^1.0.2",
|
"passport-google-auth": "^1.0.2",
|
||||||
"passport-google-oauth": "^2.0.0",
|
"passport-google-oauth": "^2.0.0",
|
||||||
"passport-jwt": "^4.0.0",
|
"passport-jwt": "^4.0.0",
|
||||||
"passport-local": "^1.0.0"
|
"passport-local": "^1.0.0",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
const uuid = require("uuid/v4")
|
||||||
|
|
||||||
|
exports.ViewNames = {
|
||||||
|
USER_BY_EMAIL: "by_email",
|
||||||
|
}
|
||||||
|
|
||||||
exports.StaticDatabases = {
|
exports.StaticDatabases = {
|
||||||
GLOBAL: {
|
GLOBAL: {
|
||||||
name: "global-db",
|
name: "global-db",
|
||||||
|
@ -17,28 +23,23 @@ const SEPARATOR = "_"
|
||||||
exports.SEPARATOR = SEPARATOR
|
exports.SEPARATOR = SEPARATOR
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new user ID based on the passed in email.
|
* Generates a new global user ID.
|
||||||
* @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.
|
* @returns {string} The new user ID which the user doc can be stored under.
|
||||||
*/
|
*/
|
||||||
exports.generateUserID = email => {
|
exports.generateUserID = () => {
|
||||||
return `${DocumentTypes.USER}${SEPARATOR}${email}`
|
return `${DocumentTypes.USER}${SEPARATOR}${uuid()}`
|
||||||
}
|
|
||||||
|
|
||||||
exports.getEmailFromUserID = userId => {
|
|
||||||
return userId.split(`${DocumentTypes.USER}${SEPARATOR}`)[1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets parameters for retrieving users, this is a utility function for the getDocParams function.
|
* Gets parameters for retrieving users, this is a utility function for the getDocParams function.
|
||||||
*/
|
*/
|
||||||
exports.getUserParams = (email = "", otherProps = {}) => {
|
exports.getUserParams = (globalId = "", otherProps = {}) => {
|
||||||
if (!email) {
|
if (!globalId) {
|
||||||
email = ""
|
globalId = ""
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...otherProps,
|
...otherProps,
|
||||||
startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`,
|
startkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}`,
|
||||||
endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`,
|
endkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}${UNICODE_MAX}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
const { DocumentTypes, ViewNames, StaticDatabases } = require("./utils")
|
||||||
|
const { CouchDB } = require("./index")
|
||||||
|
|
||||||
|
exports.createUserEmailView = async () => {
|
||||||
|
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
||||||
|
const designDoc = await db.get("_design/database")
|
||||||
|
const view = {
|
||||||
|
// if using variables in a map function need to inject them before use
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc._id.startsWith("${DocumentTypes.USER}")) {
|
||||||
|
emit(doc.email, doc._id)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewNames.USER_BY_EMAIL]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
|
@ -17,8 +17,8 @@ const {
|
||||||
const {
|
const {
|
||||||
generateUserID,
|
generateUserID,
|
||||||
getUserParams,
|
getUserParams,
|
||||||
getEmailFromUserID,
|
|
||||||
} = require("./db/utils")
|
} = require("./db/utils")
|
||||||
|
const { getGlobalUserByEmail } = require("./utils")
|
||||||
|
|
||||||
// Strategies
|
// Strategies
|
||||||
passport.use(new LocalStrategy(local.options, local.authenticate))
|
passport.use(new LocalStrategy(local.options, local.authenticate))
|
||||||
|
@ -49,7 +49,6 @@ module.exports = {
|
||||||
StaticDatabases,
|
StaticDatabases,
|
||||||
generateUserID,
|
generateUserID,
|
||||||
getUserParams,
|
getUserParams,
|
||||||
getEmailFromUserID,
|
|
||||||
hash,
|
hash,
|
||||||
compare,
|
compare,
|
||||||
getAppId,
|
getAppId,
|
||||||
|
@ -58,4 +57,5 @@ module.exports = {
|
||||||
clearCookie,
|
clearCookie,
|
||||||
authenticated,
|
authenticated,
|
||||||
isClient,
|
isClient,
|
||||||
|
getGlobalUserByEmail,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
const { Cookies } = require("../constants")
|
const { Cookies } = require("../constants")
|
||||||
const { getCookie } = require("../utils")
|
const { getCookie } = require("../utils")
|
||||||
const { getEmailFromUserID } = require("../db/utils")
|
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
try {
|
try {
|
||||||
|
@ -10,8 +9,6 @@ module.exports = async (ctx, next) => {
|
||||||
if (authCookie) {
|
if (authCookie) {
|
||||||
ctx.isAuthenticated = true
|
ctx.isAuthenticated = true
|
||||||
ctx.user = authCookie
|
ctx.user = authCookie
|
||||||
// make sure email is correct from ID
|
|
||||||
ctx.user.email = getEmailFromUserID(authCookie.userId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await next()
|
await next()
|
||||||
|
|
|
@ -4,6 +4,7 @@ const database = require("../../db")
|
||||||
const { StaticDatabases, generateUserID } = require("../../db/utils")
|
const { StaticDatabases, generateUserID } = require("../../db/utils")
|
||||||
const { compare } = require("../../hashing")
|
const { compare } = require("../../hashing")
|
||||||
const env = require("../../environment")
|
const env = require("../../environment")
|
||||||
|
const { getGlobalUserByEmail } = require("../../utils")
|
||||||
|
|
||||||
const INVALID_ERR = "Invalid Credentials"
|
const INVALID_ERR = "Invalid Credentials"
|
||||||
|
|
||||||
|
@ -11,21 +12,18 @@ exports.options = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passport Local Authentication Middleware.
|
* Passport Local Authentication Middleware.
|
||||||
* @param {*} username - username to login with
|
* @param {*} email - username to login with
|
||||||
* @param {*} password - plain text password to log in with
|
* @param {*} password - plain text password to log in with
|
||||||
* @param {*} done - callback from passport to return user information and errors
|
* @param {*} done - callback from passport to return user information and errors
|
||||||
* @returns The authenticated user, or errors if they occur
|
* @returns The authenticated user, or errors if they occur
|
||||||
*/
|
*/
|
||||||
exports.authenticate = async function(username, password, done) {
|
exports.authenticate = async function(email, password, done) {
|
||||||
if (!username) return done(null, false, "Email Required.")
|
if (!email) return done(null, false, "Email Required.")
|
||||||
if (!password) return done(null, false, "Password Required.")
|
if (!password) return done(null, false, "Password Required.")
|
||||||
|
|
||||||
// Check the user exists in the instance DB by email
|
|
||||||
const db = new database.CouchDB(StaticDatabases.GLOBAL.name)
|
|
||||||
|
|
||||||
let dbUser
|
let dbUser
|
||||||
try {
|
try {
|
||||||
dbUser = await db.get(generateUserID(username))
|
dbUser = await getGlobalUserByEmail(email)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("User not found", err)
|
console.error("User not found", err)
|
||||||
return done(null, false, { message: "User not found" })
|
return done(null, false, { message: "User not found" })
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const { DocumentTypes, SEPARATOR } = require("./db/utils")
|
const { DocumentTypes, SEPARATOR, ViewNames, StaticDatabases } = require("./db/utils")
|
||||||
const jwt = require("jsonwebtoken")
|
const jwt = require("jsonwebtoken")
|
||||||
const { options } = require("./middleware/passport/jwt")
|
const { options } = require("./middleware/passport/jwt")
|
||||||
|
const { createUserEmailView } = require("./db/views")
|
||||||
|
const { CouchDB } = require("./db")
|
||||||
|
|
||||||
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||||
|
|
||||||
|
@ -97,3 +99,21 @@ exports.clearCookie = (ctx, name) => {
|
||||||
exports.isClient = ctx => {
|
exports.isClient = ctx => {
|
||||||
return ctx.headers["x-budibase-type"] === "client"
|
return ctx.headers["x-budibase-type"] === "client"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getGlobalUserByEmail = async email => {
|
||||||
|
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
||||||
|
try {
|
||||||
|
let users = (await db.query(
|
||||||
|
`database/${ViewNames.USER_BY_EMAIL}`,
|
||||||
|
{
|
||||||
|
key: email
|
||||||
|
})
|
||||||
|
).rows
|
||||||
|
return users.length <= 1 ? users[0] : users
|
||||||
|
} catch (err) {
|
||||||
|
if (err != null && err.name === "not_found") {
|
||||||
|
await createUserEmailView()
|
||||||
|
return exports.getGlobalUserByEmail(email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -584,6 +584,11 @@ uuid@^3.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
|
uuid@^8.3.2:
|
||||||
|
version "8.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
verror@1.10.0:
|
verror@1.10.0:
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||||
|
|
Loading…
Reference in New Issue