Fixing an issue with cookie auth.

This commit is contained in:
mike12345567 2022-04-27 16:56:30 +01:00
parent 056d9defe4
commit 00c67289b0
3 changed files with 44 additions and 48 deletions

View File

@ -1,35 +1,36 @@
const PouchDB = require("pouchdb") const PouchDB = require("pouchdb")
const env = require("../environment") const env = require("../environment")
exports.getCouchUrl = () => { exports.getCouchInfo = () => {
if (!env.COUCH_DB_URL) return let url = "http://localhost:4005"
if (env.COUCH_DB_URL && env.COUCH_DB_URL.includes("@")) {
// username and password already exist in URL url = env.COUCH_DB_URL
if (env.COUCH_DB_URL.includes("@")) { } else if (env.COUCH_DB_URL) {
return env.COUCH_DB_URL const [protocol, ...rest] = env.COUCH_DB_URL.split("://")
url = `${protocol}://${env.COUCH_DB_USERNAME}:${env.COUCH_DB_PASSWORD}@${rest}`
if (!env.COUCH_DB_USERNAME || !env.COUCH_DB_PASSWORD) {
throw new Error(
"CouchDB configuration invalid. You must provide a fully qualified CouchDB url, or the COUCH_DB_USER and COUCH_DB_PASSWORD environment variables."
)
}
} }
const [protocol, ...rest] = env.COUCH_DB_URL.split("://")
if (!env.COUCH_DB_USERNAME || !env.COUCH_DB_PASSWORD) {
throw new Error(
"CouchDB configuration invalid. You must provide a fully qualified CouchDB url, or the COUCH_DB_USER and COUCH_DB_PASSWORD environment variables."
)
}
return `${protocol}://${env.COUCH_DB_USERNAME}:${env.COUCH_DB_PASSWORD}@${rest}`
}
exports.splitCouchUrl = url => {
const [protocol, rest] = url.split("://") const [protocol, rest] = url.split("://")
const [auth, host] = rest.split("@") const [auth, host] = rest.split("@")
const [username, password] = auth.split(":") let [username, password] = auth.split(":")
if (!username && env.COUCH_DB_USERNAME) {
username = env.COUCH_DB_USERNAME
}
if (!password && env.COUCH_DB_PASSWORD) {
password = env.COUCH_DB_PASSWORD
}
const authCookie = Buffer.from(`${username}:${password}`).toString("base64")
return { return {
url: `${protocol}://${host}`, url: `${protocol}://${host}`,
auth: { auth: {
username, username: username,
password, password: password,
}, },
cookie: `Basic ${authCookie}`,
} }
} }
@ -39,26 +40,12 @@ exports.splitCouchUrl = url => {
* Exposed for exceptional cases such as in-memory views. * Exposed for exceptional cases such as in-memory views.
*/ */
exports.getPouch = (opts = {}) => { exports.getPouch = (opts = {}) => {
let auth = { let { url, cookie } = exports.getCouchInfo()
username: env.COUCH_DB_USERNAME,
password: env.COUCH_DB_PASSWORD,
}
let url = exports.getCouchUrl() || "http://localhost:4005"
// need to update security settings
if (!auth.username || !auth.password || url.includes("@")) {
const split = exports.splitCouchUrl(url)
url = split.url
auth = split.auth
}
const authCookie = Buffer.from(`${auth.username}:${auth.password}`).toString(
"base64"
)
let POUCH_DB_DEFAULTS = { let POUCH_DB_DEFAULTS = {
prefix: url, prefix: url,
fetch: (url, opts) => { fetch: (url, opts) => {
// use a specific authorization cookie - be very explicit about how we authenticate // use a specific authorization cookie - be very explicit about how we authenticate
opts.headers.set("Authorization", `Basic ${authCookie}`) opts.headers.set("Authorization", cookie)
return PouchDB.fetch(url, opts) return PouchDB.fetch(url, opts)
}, },
} }

View File

@ -12,7 +12,7 @@ const {
const { getTenantId, getGlobalDBName } = require("../tenancy") const { getTenantId, getGlobalDBName } = require("../tenancy")
const fetch = require("node-fetch") const fetch = require("node-fetch")
const { doWithDB, allDbs } = require("./index") const { doWithDB, allDbs } = require("./index")
const { getCouchUrl } = require("./pouch") const { getCouchInfo } = require("./pouch")
const { getAppMetadata } = require("../cache/appMetadata") const { getAppMetadata } = require("../cache/appMetadata")
const { checkSlashesInUrl } = require("../helpers") const { checkSlashesInUrl } = require("../helpers")
const { const {
@ -169,8 +169,14 @@ exports.getAllDbs = async (opts = { efficient: false }) => {
return allDbs() return allDbs()
} }
let dbs = [] let dbs = []
async function addDbs(url) { let { url, cookie } = getCouchInfo()
const response = await fetch(checkSlashesInUrl(encodeURI(url))) async function addDbs(couchUrl) {
const response = await fetch(checkSlashesInUrl(encodeURI(couchUrl)), {
method: "GET",
headers: {
Authorization: cookie,
},
})
if (response.status === 200) { if (response.status === 200) {
let json = await response.json() let json = await response.json()
dbs = dbs.concat(json) dbs = dbs.concat(json)
@ -178,7 +184,7 @@ exports.getAllDbs = async (opts = { efficient: false }) => {
throw "Cannot connect to CouchDB instance" throw "Cannot connect to CouchDB instance"
} }
} }
let couchUrl = `${getCouchUrl()}/_all_dbs` let couchUrl = `${url}/_all_dbs`
let tenantId = getTenantId() let tenantId = getTenantId()
if (!env.MULTI_TENANCY || (!efficient && tenantId === DEFAULT_TENANT_ID)) { if (!env.MULTI_TENANCY || (!efficient && tenantId === DEFAULT_TENANT_ID)) {
// just get all DBs when: // just get all DBs when:

View File

@ -1,6 +1,6 @@
const { SearchIndexes } = require("../../../db/utils") const { SearchIndexes } = require("../../../db/utils")
const fetch = require("node-fetch") const fetch = require("node-fetch")
const { getCouchUrl } = require("@budibase/backend-core/db") const { getCouchInfo } = require("@budibase/backend-core/db")
const { getAppId } = require("@budibase/backend-core/context") const { getAppId } = require("@budibase/backend-core/context")
/** /**
@ -242,11 +242,10 @@ class QueryBuilder {
async run() { async run() {
const appId = getAppId() const appId = getAppId()
const url = `${getCouchUrl()}/${appId}/_design/database/_search/${ const { url, cookie } = getCouchInfo()
SearchIndexes.ROWS const fullPath = `${url}/${appId}/_design/database/_search/${SearchIndexes.ROWS}`
}`
const body = this.buildSearchBody() const body = this.buildSearchBody()
return await runQuery(url, body) return await runQuery(fullPath, body, cookie)
} }
} }
@ -254,12 +253,16 @@ class QueryBuilder {
* Executes a lucene search query. * Executes a lucene search query.
* @param url The query URL * @param url The query URL
* @param body The request body defining search criteria * @param body The request body defining search criteria
* @param cookie The auth cookie for CouchDB
* @returns {Promise<{rows: []}>} * @returns {Promise<{rows: []}>}
*/ */
const runQuery = async (url, body) => { const runQuery = async (url, body, cookie) => {
const response = await fetch(url, { const response = await fetch(url, {
body: JSON.stringify(body), body: JSON.stringify(body),
method: "POST", method: "POST",
headers: {
Authorization: cookie,
},
}) })
const json = await response.json() const json = await response.json()