Skip to content

Commit

Permalink
Validate couchdb
Browse files Browse the repository at this point in the history
  • Loading branch information
adrinr committed May 11, 2023
1 parent f69504f commit 1deb4e7
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 10 deletions.
14 changes: 10 additions & 4 deletions packages/backend-core/src/db/couch/DatabaseImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
isDocument,
} from "@budibase/types"
import { getCouchInfo } from "./connections"
import { directCouchCall } from "./utils"
import { directCouchUrlCall } from "./utils"
import { getPouchDB } from "./pouchDB"
import { WriteStream, ReadStream } from "fs"
import { newid } from "../../docIds/newid"
Expand Down Expand Up @@ -46,15 +46,17 @@ export class DatabaseImpl implements Database {
private readonly instanceNano?: Nano.ServerScope
private readonly pouchOpts: DatabaseOpts

private readonly couchInfo = getCouchInfo()

constructor(dbName?: string, opts?: DatabaseOpts, connection?: string) {
if (dbName == null) {
throw new Error("Database name cannot be undefined.")
}
this.name = dbName
this.pouchOpts = opts || {}
if (connection) {
const couchInfo = getCouchInfo(connection)
this.instanceNano = buildNano(couchInfo)
this.couchInfo = getCouchInfo(connection)
this.instanceNano = buildNano(this.couchInfo)
}
if (!DatabaseImpl.nano) {
DatabaseImpl.init()
Expand All @@ -67,7 +69,11 @@ export class DatabaseImpl implements Database {
}

async exists() {
let response = await directCouchCall(`/${this.name}`, "HEAD")
const response = await directCouchUrlCall({
url: `${this.couchInfo.url}/${this.name}`,
method: "HEAD",
cookie: this.couchInfo.cookie,
})
return response.status === 200
}

Expand Down
16 changes: 15 additions & 1 deletion packages/backend-core/src/db/couch/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ export async function directCouchCall(
) {
let { url, cookie } = getCouchInfo()
const couchUrl = `${url}/${path}`
return await directCouchUrlCall({ url: couchUrl, cookie, method, body })
}

export async function directCouchUrlCall({
url,
cookie,
method,
body,
}: {
url: string
cookie: string
method: string
body?: any
}) {
const params: any = {
method: method,
headers: {
Expand All @@ -19,7 +33,7 @@ export async function directCouchCall(
params.body = JSON.stringify(body)
params.headers["Content-Type"] = "application/json"
}
return await fetch(checkSlashesInUrl(encodeURI(couchUrl)), params)
return await fetch(checkSlashesInUrl(encodeURI(url)), params)
}

export async function directCouchQuery(
Expand Down
19 changes: 14 additions & 5 deletions packages/server/src/integrations/couchdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from "@budibase/types"
import { db as dbCore } from "@budibase/backend-core"

interface CouchDBConfig {
export interface CouchDBConfig {
url: string
database: string
}
Expand Down Expand Up @@ -61,11 +61,9 @@ const SCHEMA: Integration = {
}

class CouchDBIntegration implements IntegrationBase {
private config: CouchDBConfig
private readonly client: any
private readonly client: dbCore.DatabaseImpl

constructor(config: CouchDBConfig) {
this.config = config
this.client = dbCore.DatabaseWithConnection(config.database, config.url)
}

Expand All @@ -75,7 +73,7 @@ class CouchDBIntegration implements IntegrationBase {
query: { json?: object; id?: string }
) {
try {
return await this.client[command](query.id || query.json)
return await (this.client as any)[command](query.id || query.json)
} catch (err) {
console.error(errorMsg, err)
throw err
Expand Down Expand Up @@ -127,7 +125,18 @@ class CouchDBIntegration implements IntegrationBase {
}
}

async function validateConnection(config: CouchDBConfig) {
const integration = new CouchDBIntegration(config)
try {
const result = await integration.query("exists", "validation error", {})
return result === true
} catch (e: any) {
return { error: e.message as string }
}
}

export default {
schema: SCHEMA,
integration: CouchDBIntegration,
validateConnection,
}
1 change: 1 addition & 0 deletions packages/server/src/integrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export async function getIntegration(integration: SourceName) {
const VALIDATORS = {
[SourceName.POSTGRES]: postgres.validateConnection,
[SourceName.MYSQL]: mysql.validateConnection,
[SourceName.COUCHDB]: couchdb.validateConnection,
}

export default {
Expand Down
32 changes: 32 additions & 0 deletions packages/server/src/sdk/tests/datasources/validators.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SourceName } from "@budibase/types"
import integrations from "../../../integrations"
import { GenericContainer } from "testcontainers"
import { env } from "@budibase/backend-core"

jest.unmock("pg")
jest.unmock("mysql2/promise")
Expand Down Expand Up @@ -113,4 +114,35 @@ describe("datasource validators", () => {
})
})
})

describe("couchdb", () => {
const validator = integrations.getValidator[SourceName.COUCHDB]!

it("test valid connection string", async () => {
const result = await validator({
url: env.COUCH_DB_URL,
database: "",
})
expect(result).toBe(true)
})

it("test invalid database", async () => {
const result = await validator({
url: env.COUCH_DB_URL,
database: "db",
})
expect(result).toBe(false)
})

it("test invalid url", async () => {
const result = await validator({
url: "http://invalid:123",
database: "any",
})
expect(result).toEqual({
error:
"request to http://invalid:123/any failed, reason: getaddrinfo ENOTFOUND invalid",
})
})
})
})

0 comments on commit 1deb4e7

Please sign in to comment.