1
0
Fork 0
mirror of synced 2024-10-02 10:08:09 +13:00

Validate mysql

This commit is contained in:
Adria Navarro 2023-05-11 13:25:35 +02:00
parent f10a66cc42
commit 721492e76d
2 changed files with 80 additions and 6 deletions

View file

@ -85,8 +85,6 @@ const SCHEMA: Integration = {
},
}
const TimezoneAwareDateTypes = ["timestamp"]
function bindingTypeCoerce(bindings: any[]) {
for (let i = 0; i < bindings.length; i++) {
const binding = bindings[i]
@ -113,7 +111,7 @@ function bindingTypeCoerce(bindings: any[]) {
class MySQLIntegration extends Sql implements DatasourcePlus {
private config: MySQLConfig
private client: any
private client?: mysql.Connection
public tables: Record<string, Table> = {}
public schemaErrors: Record<string, string> = {}
@ -167,7 +165,7 @@ class MySQLIntegration extends Sql implements DatasourcePlus {
}
async disconnect() {
await this.client.end()
await this.client!.end()
}
async internalQuery(
@ -186,10 +184,10 @@ class MySQLIntegration extends Sql implements DatasourcePlus {
? baseBindings
: bindingTypeCoerce(baseBindings)
// Node MySQL is callback based, so we must wrap our call in a promise
const response = await this.client.query(query.sql, bindings)
const response = await this.client!.query(query.sql, bindings)
return response[0]
} finally {
if (opts?.connect) {
if (opts?.connect && this.client) {
await this.disconnect()
}
}
@ -288,7 +286,21 @@ class MySQLIntegration extends Sql implements DatasourcePlus {
}
}
async function validateConnection(config: MySQLConfig) {
const integration = new MySQLIntegration(config)
try {
const [result] = await integration.internalQuery(
{ sql: "SELECT 1+1 AS checkRes" },
{ connect: true }
)
return result?.checkRes == 2
} catch (e: any) {
return { error: e.message as string }
}
}
export default {
schema: SCHEMA,
integration: MySQLIntegration,
validateConnection,
}

View file

@ -2,6 +2,7 @@ import { GenericContainer } from "testcontainers"
import postgres from "../../../../packages/server/src/integrations/postgres"
jest.unmock("pg")
jest.unmock("mysql2/promise")
describe("datasource validators", () => {
describe("postgres", () => {
@ -50,4 +51,65 @@ describe("datasource validators", () => {
})
})
})
describe("mysql", () => {
const validator = integrations.getValidator[SourceName.MYSQL]!
let host: string
let port: number
beforeAll(async () => {
const container = await new GenericContainer("mysql")
.withExposedPorts(3306)
.withEnv("MYSQL_ROOT_PASSWORD", "admin")
.withEnv("MYSQL_DATABASE", "db")
.withEnv("MYSQL_USER", "user")
.withEnv("MYSQL_PASSWORD", "password")
.start()
host = container.getContainerIpAddress()
port = container.getMappedPort(3306)
})
it("test valid connection string", async () => {
const result = await validator({
host,
port,
user: "user",
database: "db",
password: "password",
rejectUnauthorized: true,
})
expect(result).toBe(true)
})
it("test invalid database", async () => {
const result = await validator({
host,
port,
user: "user",
database: "test",
password: "password",
rejectUnauthorized: true,
})
expect(result).toEqual({
error: "Access denied for user 'user'@'%' to database 'test'",
})
})
it("test invalid password", async () => {
const result = await validator({
host,
port,
user: "root",
database: "test",
password: "wrong",
rejectUnauthorized: true,
})
expect(result).toEqual({
error:
"Access denied for user 'root'@'172.17.0.1' (using password: YES)",
})
})
})
})