Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataConnect + PGLite prototype. #7615

Merged
merged 30 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
feb3560
Hacking away at pglite+dataconnect emulator
joehan Aug 15, 2024
412ae45
Hacking away at it
joehan Aug 19, 2024
0d8ec81
More debugging
joehan Aug 20, 2024
766ebd2
I THINK IT WORKSSSSS
joehan Aug 22, 2024
0c99fce
Merge remote-tracking branch 'public/master' into jh-pglite
joehan Aug 28, 2024
5b4e0f6
Saving my progress at EoD
joehan Aug 28, 2024
36dd2be
--amend
joehan Aug 28, 2024
b65fb1c
Progress
joehan Aug 30, 2024
dab3523
clean up
joehan Sep 3, 2024
3c8964c
formatting
joehan Sep 3, 2024
0a4c9e3
Use extended query patch (thanks @gregnr!)
joehan Sep 9, 2024
13a8590
Merge remote-tracking branch 'public/master' into jh-pglite
joehan Sep 9, 2024
c86ce4e
Format and merge master
joehan Sep 9, 2024
890bcc2
PR fixes
joehan Sep 9, 2024
63bcc6b
Remove JSON comments
joehan Sep 9, 2024
5e7da7c
format
joehan Sep 9, 2024
a8d8aa6
Fxing test compilation issues
joehan Sep 9, 2024
3866a0e
Cleaning up build issues
joehan Sep 9, 2024
d96874d
PR fixes
joehan Sep 10, 2024
17601cc
Format and generate json schema
joehan Sep 10, 2024
dfd93f8
Patching in missing types for VSCode builds
joehan Sep 10, 2024
25c1bc0
More type fixing
joehan Sep 10, 2024
2b7cdeb
More type fixing
joehan Sep 11, 2024
78a4f47
Little bit mroe code review
joehan Sep 11, 2024
feeb1b6
Removed unused dep
joehan Sep 11, 2024
7a9d054
More pr fixes
joehan Sep 11, 2024
115224b
test:emualtors build fixed
joehan Sep 11, 2024
d959f67
Merging in launch
joehan Sep 11, 2024
f1e038e
PR fixes
joehan Sep 11, 2024
1439370
Fix port disagreement
joehan Sep 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ module.exports = {
// TODO(jamesdaniels): add this to overrides instead
ignorePatterns: [
"src/dynamicImport.js",
"src/emulator/dataconnect/pg-gateway",
"scripts/webframeworks-deploy-tests/nextjs/**",
"scripts/webframeworks-deploy-tests/angular/**",
"scripts/frameworks-tests/vite-project/**",
Expand Down
11 changes: 11 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
]
},
"dependencies": {
"@electric-sql/pglite": "^0.2.0",
"@google-cloud/cloud-sql-connector": "^1.3.3",
"@google-cloud/pubsub": "^4.5.0",
"abort-controller": "^3.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/emulator/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@

/**
* Exports emulator data on clean exit (SIGINT or process end)
* @param options

Check warning on line 71 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing JSDoc @param "options" description
*/
export async function exportOnExit(options: any) {

Check warning on line 73 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing return type on function

Check warning on line 73 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
const exportOnExitDir = options.exportOnExit;

Check warning on line 74 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe assignment of an `any` value

Check warning on line 74 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .exportOnExit on an `any` value
if (exportOnExitDir) {
try {
utils.logBullet(
`Automatically exporting data using ${FLAG_EXPORT_ON_EXIT_NAME} "${exportOnExitDir}" ` +

Check warning on line 78 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Invalid type "any" of template literal expression
"please wait for the export to finish...",
);
await exportEmulatorData(exportOnExitDir, options, /* initiatedBy= */ "exit");

Check warning on line 81 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `string`
} catch (e: any) {

Check warning on line 82 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
utils.logWarning(e);

Check warning on line 83 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `string`
utils.logWarning(`Automatic export to "${exportOnExitDir}" failed, going to exit now...`);

Check warning on line 84 in src/emulator/controller.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Invalid type "any" of template literal expression
}
}
}
Expand Down Expand Up @@ -851,6 +851,7 @@
configDir,
rc: options.rc,
config: options.config,
autostartPostgres: experiments.isEnabled("fdcpglite"),
});
await startEmulator(dataConnectEmulator);
}
Expand Down
6 changes: 6 additions & 0 deletions src/emulator/dataconnect/pg-gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The code in this directory is a very slightly modified version of https://github.com/supabase-community/pg-gateway/tree/next.
Full credit for this code goes to @gregnr and the other contributors on that repo.

Due to some known issues with how PGLite handles prepared statements, this versiom of pg-gateway includes middleware
to remove the extra Ready for Query messages that break schema migration. Once these underlying issues with PGLite are fixed,
we'll migrate to a normal dependency on pg-gateway.
32 changes: 32 additions & 0 deletions src/emulator/dataconnect/pg-gateway/auth/base-auth-flow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { BufferReader } from '../buffer-reader';
import type { BufferWriter } from '../buffer-writer';
import type { ConnectionSignal } from '../connection';
import type { ConnectionState } from '../connection.types';

export interface AuthFlow {
createInitialAuthMessage(): Uint8Array | undefined;
handleClientMessage(message: BufferSource): AsyncGenerator<Uint8Array | ConnectionSignal>;
isCompleted: boolean;
}

export abstract class BaseAuthFlow implements AuthFlow {
protected reader: BufferReader;
protected writer: BufferWriter;
protected connectionState: ConnectionState;

constructor(params: {
reader: BufferReader;
writer: BufferWriter;
connectionState: ConnectionState;
}) {
this.reader = params.reader;
this.writer = params.writer;
this.connectionState = params.connectionState;
}

abstract createInitialAuthMessage(): Uint8Array | undefined;
abstract handleClientMessage(
message: BufferSource,
): AsyncGenerator<Uint8Array | ConnectionSignal>;
abstract get isCompleted(): boolean;
}
100 changes: 100 additions & 0 deletions src/emulator/dataconnect/pg-gateway/auth/cert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { PeerCertificate } from 'node:tls';
import { createBackendErrorMessage } from '../backend-error';
import type { BufferReader } from '../buffer-reader';
import type { BufferWriter } from '../buffer-writer';
import type { ConnectionState } from '../connection.types';
import { BaseAuthFlow } from './base-auth-flow';
import { closeSignal } from '../connection';

export type CertAuthOptions = {
method: 'cert';
validateCredentials?: (
credentials: {
username: string;
certificate: PeerCertificate;
},
connectionState: ConnectionState,
) => boolean | Promise<boolean>;
};

export class CertAuthFlow extends BaseAuthFlow {
private auth: CertAuthOptions & {
validateCredentials: NonNullable<CertAuthOptions['validateCredentials']>;
};
private username: string;
private completed = false;

constructor(params: {
auth: CertAuthOptions;
username: string;
reader: BufferReader;
writer: BufferWriter;
connectionState: ConnectionState;
}) {
super(params);
this.auth = {
...params.auth,
validateCredentials:
params.auth.validateCredentials ??
(async ({ username, certificate }) => {
return certificate.subject.CN === username;
}),
};
this.username = params.username;
}

async *handleClientMessage(message: BufferSource) {
// biome-ignore lint/correctness/noConstantCondition: TODO: detect TLS state
if (false) {
yield createBackendErrorMessage({
severity: 'FATAL',
code: '08000',
message: `ssl connection required when auth mode is 'certificate'`,
});
yield closeSignal;
return;
}

// biome-ignore lint/correctness/noConstantCondition: TODO: detect if cert authorized
if (false) {
yield createBackendErrorMessage({
severity: 'FATAL',
code: '08000',
message: 'client certificate is invalid',
});
yield closeSignal;
return;
}

// TODO: get peer cert and validate through hook
const isValid = false;

// const isValid = await this.auth.validateCredentials(
// {
// username: this.username,
// certificate: this.socket.getPeerCertificate(),
// },
// this.connectionState,
// );
Comment on lines +71 to +80
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be handled? (not sure if this is directly copied from pg-gateway or not)

Copy link
Contributor Author

@joehan joehan Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for us to actually authenticate the toolkit's creds - the FDC toolkit is trusted, so we are using 'trust' auth and will never hit this code.

I removed this while debugging some import issues that arose from converting these files to cjs.


if (!isValid) {
yield createBackendErrorMessage({
severity: 'FATAL',
code: '08000',
message: 'client certificate is invalid',
});
yield closeSignal;
return;
}

this.completed = true;
}

override createInitialAuthMessage() {
return undefined;
}

get isCompleted(): boolean {
return this.completed;
}
}
37 changes: 37 additions & 0 deletions src/emulator/dataconnect/pg-gateway/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { BufferReader } from '../buffer-reader';
import type { BufferWriter } from '../buffer-writer';
import type { ConnectionState } from '../connection.types';
import type { AuthFlow } from './base-auth-flow';
import { CertAuthFlow, type CertAuthOptions } from './cert';
import { Md5AuthFlow, type Md5AuthOptions } from './md5';
import { PasswordAuthFlow, type PasswordAuthOptions } from './password';
import { ScramSha256AuthFlow, type ScramSha256AuthOptions } from './sasl/scram-sha-256';
import type { TrustAuthOptions } from './trust';

export type AuthOptions =
| TrustAuthOptions
| PasswordAuthOptions
| Md5AuthOptions
| ScramSha256AuthOptions
| CertAuthOptions;

export function createAuthFlow(options: {
reader: BufferReader;
writer: BufferWriter;
auth: AuthOptions;
username: string;
connectionState: ConnectionState;
}): AuthFlow {
switch (options.auth.method) {
case 'password':
return new PasswordAuthFlow({ ...options, auth: options.auth });
case 'md5':
return new Md5AuthFlow({ ...options, auth: options.auth });
case 'scram-sha-256':
return new ScramSha256AuthFlow({ ...options, auth: options.auth });
case 'cert':
return new CertAuthFlow({ ...options, auth: options.auth });
default:
throw new Error(`Unsupported auth method: ${options.auth.method}`);
}
}
Loading
Loading