From 8d1a622f8408d3c19add9e03f2d95244dbda7d29 Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Wed, 11 Dec 2024 19:14:49 +1100 Subject: [PATCH] chore(cognito): upgrade dependency and code refactoring --- Cargo.lock | 58 ++++++----- docs/catalog/cognito.md | 24 ++++- wrappers/Cargo.toml | 4 +- wrappers/src/fdw/cognito_fdw/README.md | 1 + .../src/fdw/cognito_fdw/cognito_client/mod.rs | 44 --------- .../src/fdw/cognito_fdw/cognito_client/row.rs | 95 ++++++++----------- .../cognito_client/rows_iterator.rs | 59 ++++++------ wrappers/src/fdw/cognito_fdw/cognito_fdw.rs | 89 +++-------------- wrappers/src/fdw/cognito_fdw/mod.rs | 53 +++++++++++ 9 files changed, 189 insertions(+), 238 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd837324d..0592edf4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -616,7 +616,7 @@ dependencies = [ "aws-sdk-sts", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16838e6c9e12125face1c1eff1343c75e3ff540de98ff7ebd61874a89bcfeb9" +checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -648,15 +648,16 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.4.0" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f42c2d4218de4dcd890a109461e2f799a1a2ba3bcd2cde9af88360f5df9266c6" +checksum = "b5ac934720fbb46206292d2c75b57e67acfc56fe7dfd34fb9a02334af08409ea" dependencies = [ "aws-credential-types", "aws-sigv4", "aws-smithy-async", "aws-smithy-eventstream", "aws-smithy-http", + "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", @@ -673,15 +674,15 @@ dependencies = [ [[package]] name = "aws-sdk-cognitoidentityprovider" -version = "1.29.0" +version = "1.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4292571f2e349864c0339eef5e39a649ae8b72068b28657b81c8776dc873ae2" +checksum = "9507adb5d9ca167ca83c12fadbca0e22dbb742d9c93b411720a92b4638dc7b7d" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.61.1", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -707,7 +708,7 @@ dependencies = [ "aws-smithy-checksums", "aws-smithy-eventstream", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -738,7 +739,7 @@ dependencies = [ "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -760,7 +761,7 @@ dependencies = [ "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -782,7 +783,7 @@ dependencies = [ "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-query", "aws-smithy-runtime", "aws-smithy-runtime-api", @@ -797,9 +798,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.2.3" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5df1b0fa6be58efe9d4ccc257df0a53b89cd8909e86591a13ca54817c87517be" +checksum = "7d3820e0c08d0737872ff3c7c1f21ebbb6693d832312d6152bf18ef50a5471c2" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -858,9 +859,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.4" +version = "0.60.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" +checksum = "cef7d0a272725f87e51ba2bf89f8c21e4df61b9e49ae1ac367a6d69916ef7c90" dependencies = [ "aws-smithy-types", "bytes", @@ -869,9 +870,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.9" +version = "0.60.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9cd0ae3d97daa0a2bf377a4d8e8e1362cae590c4a1aad0d40058ebca18eb91e" +checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -897,6 +898,15 @@ dependencies = [ "aws-smithy-types", ] +[[package]] +name = "aws-smithy-json" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4e69cc50921eb913c6b662f8d909131bb3e6ad6cb6090d3a39b66fc5c52095" +dependencies = [ + "aws-smithy-types", +] + [[package]] name = "aws-smithy-query" version = "0.60.7" @@ -909,9 +919,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.6.3" +version = "1.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0abbf454960d0db2ad12684a1640120e7557294b0ff8e2f11236290a1b293225" +checksum = "9f20685047ca9d6f17b994a07f629c813f08b5bce65523e47124879e60103d45" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -936,9 +946,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -953,9 +963,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.2" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cee7cadb433c781d3299b916fbf620fea813bf38f49db282fb6858141a05cc8" +checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" dependencies = [ "base64-simd", "bytes", diff --git a/docs/catalog/cognito.md b/docs/catalog/cognito.md index 2631b83f9..ad28b6bef 100644 --- a/docs/catalog/cognito.md +++ b/docs/catalog/cognito.md @@ -82,21 +82,30 @@ The Cognito Wrapper supports data reads from Cognito's [User Records](https://do | Cognito | Select | Insert | Update | Delete | Truncate | | ------- | :----: | :----: | :----: | :----: | :------: | -| Records | ✅ | ❌ | ❌ | ❌ | ❌ | +| Users | ✅ | ❌ | ❌ | ❌ | ❌ | For example: ```sql create foreign table cognito ( - email text, - username text + username text, + email text, + status text, + enabled boolean, + created_at timestamp, + updated_at timestamp, + attributes jsonb ) server cognito_server options ( - object 'users' + object 'users' ); ``` +!!! note + + Only columns listed above are accepted in the foreign table. + ### Foreign table options The full list of foreign table options are below: @@ -117,8 +126,13 @@ This will create a "foreign table" inside your Postgres database called `cognito ```sql create foreign table cognito_table ( + username text, email text, - username text + status text, + enabled boolean, + created_at timestamp, + updated_at timestamp, + attributes jsonb ) server cognito_server options ( diff --git a/wrappers/Cargo.toml b/wrappers/Cargo.toml index d956f062e..96c5d0a5d 100644 --- a/wrappers/Cargo.toml +++ b/wrappers/Cargo.toml @@ -89,7 +89,6 @@ cognito_fdw = [ "serde", "url", "thiserror", - "chrono", ] logflare_fdw = [ "http", @@ -198,8 +197,7 @@ aws-config = { version = "1.1.7", features = ["behavior-version-latest"], option aws-sdk-s3 = { version = "1.45.0", optional = true } # for cognito fdw -aws-sdk-cognitoidentityprovider = {version ="1.10.0", optional = true} - +aws-sdk-cognitoidentityprovider = { version ="1.60.0", optional = true } csv = { version = "1.2", optional = true } tokio = { version = "1", features = ["full"], optional = true } diff --git a/wrappers/src/fdw/cognito_fdw/README.md b/wrappers/src/fdw/cognito_fdw/README.md index 63ec6a44d..b3d09b7ef 100644 --- a/wrappers/src/fdw/cognito_fdw/README.md +++ b/wrappers/src/fdw/cognito_fdw/README.md @@ -10,5 +10,6 @@ This is a demo foreign data wrapper which is developed using [Wrappers](https:// | Version | Date | Notes | | ------- | ---------- | ---------------------------------------------------- | +| 0.1.3 | 2024-12-11 | Code quality improvment | | 0.1.2 | 2024-09-30 | Support for pgrx 0.12.6 | | 0.1.0 | 2024-01-25 | Initial version | diff --git a/wrappers/src/fdw/cognito_fdw/cognito_client/mod.rs b/wrappers/src/fdw/cognito_fdw/cognito_client/mod.rs index 106652f47..b8807b391 100644 --- a/wrappers/src/fdw/cognito_fdw/cognito_client/mod.rs +++ b/wrappers/src/fdw/cognito_fdw/cognito_client/mod.rs @@ -1,46 +1,2 @@ -use pgrx::pg_sys::panic::ErrorReport; -use pgrx::PgSqlErrorCode; -use supabase_wrappers::prelude::*; -use thiserror::Error; -use url::ParseError; - pub(crate) mod row; - pub(crate) mod rows_iterator; - -#[allow(clippy::enum_variant_names)] -#[derive(Error, Debug)] -pub(crate) enum CognitoClientError { - #[error("{0}")] - CreateRuntimeError(#[from] CreateRuntimeError), - - #[error("reqwest error: {0}")] - ReqwestError(#[from] reqwest::Error), - - #[error("reqwest middleware error: {0}")] - ReqwestMiddlewareError(#[from] reqwest_middleware::Error), - - #[error("invalid json response: {0}")] - SerdeError(#[from] serde_json::Error), - - #[error("failed to parse url: {0}")] - UrlParseError(#[from] ParseError), - - #[error("AWS Cognito error: {0}")] - AWSCognitoError(String), -} - -impl From for ErrorReport { - fn from(value: CognitoClientError) -> Self { - match value { - CognitoClientError::CreateRuntimeError(e) => e.into(), - CognitoClientError::UrlParseError(_) - | CognitoClientError::AWSCognitoError(_) - | CognitoClientError::ReqwestError(_) - | CognitoClientError::ReqwestMiddlewareError(_) - | CognitoClientError::SerdeError(_) => { - ErrorReport::new(PgSqlErrorCode::ERRCODE_FDW_ERROR, format!("{value}"), "") - } - } - } -} diff --git a/wrappers/src/fdw/cognito_fdw/cognito_client/row.rs b/wrappers/src/fdw/cognito_fdw/cognito_client/row.rs index 4f0c10e50..e6ab94c4f 100644 --- a/wrappers/src/fdw/cognito_fdw/cognito_client/row.rs +++ b/wrappers/src/fdw/cognito_fdw/cognito_client/row.rs @@ -1,39 +1,13 @@ -use aws_sdk_cognitoidentityprovider::types::UserType; -use chrono::DateTime; -use serde::Deserialize; -use serde_json::Value; -use supabase_wrappers::prelude::Cell; -use supabase_wrappers::prelude::Column; -use supabase_wrappers::prelude::Row; +#![allow(clippy::result_large_err)] +use aws_sdk_cognitoidentityprovider::primitives::DateTime; +use aws_sdk_cognitoidentityprovider::types::{AttributeType, UserType}; +use serde_json::{json, Value}; +use supabase_wrappers::prelude::{Cell, Column, Row}; -use aws_sdk_cognitoidentityprovider::types::AttributeType; -use serde_json::json; +use super::super::CognitoFdwError; -#[derive(Debug, Deserialize, PartialEq)] -pub struct ResultPayload { - pub(crate) users: Vec, - pub(crate) next_page_offset: Option, -} - -#[derive(Debug, Deserialize, PartialEq)] -pub struct CognitoUser { - pub created_at: String, - pub email: String, - pub email_verified: bool, - pub identities: Option, - // Additional fields from UserType - pub username: String, - pub status: Option, -} - -#[derive(Debug)] -pub enum IntoRowError { - #[allow(dead_code)] - UnsupportedColumnType(String), -} - -pub trait IntoRow { - fn into_row(self, columns: &[Column]) -> Result; +pub(in super::super) trait IntoRow { + fn into_row(self, columns: &[Column]) -> Result; } fn serialize_attributes(attributes: &Vec) -> Value { @@ -48,46 +22,59 @@ fn serialize_attributes(attributes: &Vec) -> Value { json!(attrs) } +fn convert_to_timestamp(dt: DateTime) -> Cell { + let millis = dt.to_millis().expect("timestamp should be valid"); + // convert Unix epoch to Postgres epoch + let ts = pgrx::prelude::Timestamp::try_from(millis * 1000 - 946_684_800_000_000) + .expect("timestamp should be converted Postgres epoch"); + Cell::Timestamp(ts) +} + impl IntoRow for UserType { - fn into_row(self, columns: &[Column]) -> Result { + fn into_row(self, columns: &[Column]) -> Result { let mut row = Row::new(); for column in columns { match column.name.as_str() { "username" => { - if let Some(ref username) = self.username { - row.push("username", Some(Cell::String(username.to_string()))); - } + row.push("username", self.username.clone().map(Cell::String)); } "attributes" => { if let Some(ref attributes) = self.attributes { let serialized_attributes = serialize_attributes(attributes); - let attributes_json_b = pgrx::JsonB(serialized_attributes); row.push("attributes", Some(Cell::Json(attributes_json_b))); } } "created_at" => { - if let Some(created_at) = self.extract_attribute_value("created_at") { - let parsed_date = DateTime::parse_from_rfc3339(&created_at) - .expect("Failed to parse date"); - let ts = pgrx::prelude::Timestamp::try_from(parsed_date.timestamp()) - .expect("valid timestamp"); - row.push("created_at", Some(Cell::Timestamp(ts))); - } + row.push( + "created_at", + self.user_create_date.map(convert_to_timestamp), + ); + } + "updated_at" => { + row.push( + "updated_at", + self.user_last_modified_date.map(convert_to_timestamp), + ); } "email" => { - if let Some(email) = self.extract_attribute_value("email") { - row.push("email", Some(Cell::String(email))); - } + let value = self.extract_attribute_value("email").map(Cell::String); + row.push("email", value); + } + "enabled" => { + row.push("enabled", Some(Cell::Bool(self.enabled))); } "status" => { - if let Some(status) = self.extract_attribute_value("status") { - row.push("status", Some(Cell::String(status))); - } + row.push( + "status", + self.user_status + .clone() + .map(|s| Cell::String(s.as_str().to_owned())), + ); } _ => { - return Err(IntoRowError::UnsupportedColumnType(column.name.clone())); + return Err(CognitoFdwError::UnsupportedColumn(column.name.clone())); } } } @@ -96,7 +83,7 @@ impl IntoRow for UserType { } } -pub trait UserTypeExt { +pub(in super::super) trait UserTypeExt { fn extract_attribute_value(&self, attr_name: &str) -> Option; } diff --git a/wrappers/src/fdw/cognito_fdw/cognito_client/rows_iterator.rs b/wrappers/src/fdw/cognito_fdw/cognito_client/rows_iterator.rs index 0533d6fc5..110b1dfe8 100644 --- a/wrappers/src/fdw/cognito_fdw/cognito_client/rows_iterator.rs +++ b/wrappers/src/fdw/cognito_fdw/cognito_client/rows_iterator.rs @@ -1,13 +1,16 @@ -use crate::fdw::cognito_fdw::cognito_client::row::IntoRow; -use crate::fdw::cognito_fdw::cognito_client::CognitoClientError; +#![allow(clippy::result_large_err)] +use aws_sdk_cognitoidentityprovider::Client; +use std::collections::VecDeque; +use std::sync::Arc; -use supabase_wrappers::prelude::create_async_runtime; +use supabase_wrappers::prelude::{Column, Row, Runtime}; -use std::collections::VecDeque; -use supabase_wrappers::prelude::{Column, Row}; +use super::super::CognitoFdwResult; +use super::row::IntoRow; -pub(crate) struct RowsIterator { - cognito_client: aws_sdk_cognitoidentityprovider::Client, +pub(in super::super) struct RowsIterator { + rt: Arc, + cognito_client: Client, columns: Vec, rows: VecDeque, user_pool_id: String, @@ -16,12 +19,14 @@ pub(crate) struct RowsIterator { } impl RowsIterator { - pub(crate) fn new( + pub(in super::super) fn new( + rt: Arc, columns: Vec, user_pool_id: String, - cognito_client: aws_sdk_cognitoidentityprovider::Client, + cognito_client: Client, ) -> Self { Self { + rt, columns, cognito_client, user_pool_id, @@ -31,9 +36,8 @@ impl RowsIterator { } } - fn fetch_rows_batch(&mut self) -> Result, CognitoClientError> { + fn fetch_rows_batch(&mut self) -> CognitoFdwResult> { self.have_more_rows = false; - let rt = create_async_runtime()?; let mut request = self .cognito_client @@ -43,26 +47,21 @@ impl RowsIterator { if let Some(ref token) = self.pagination_token { request = request.pagination_token(token.clone()); } - self.rows = rt.block_on(async { - match request.send().await { - Ok(response) => { - self.pagination_token.clone_from(&response.pagination_token); - Ok(response - .users - .clone() - .unwrap_or_else(Vec::new) - .into_iter() - .filter_map(|u| u.into_row(&self.columns).ok()) - .collect::>()) - } - Err(e) => Err(CognitoClientError::AWSCognitoError(format!( - "Error sending request: {:?}", - e - ))), - } - })?; + + let resp = self + .rt + .block_on(request.send()) + .map_err(aws_sdk_cognitoidentityprovider::Error::from)?; + self.pagination_token.clone_from(&resp.pagination_token); + self.rows = resp + .users + .unwrap_or_default() + .into_iter() + .map(|u| u.into_row(&self.columns)) + .collect::, _>>()?; self.have_more_rows = self.pagination_token.is_some(); + Ok(self.get_next_row()) } @@ -72,7 +71,7 @@ impl RowsIterator { } impl Iterator for RowsIterator { - type Item = Result; + type Item = CognitoFdwResult; fn next(&mut self) -> Option { if let Some(row) = self.get_next_row() { diff --git a/wrappers/src/fdw/cognito_fdw/cognito_fdw.rs b/wrappers/src/fdw/cognito_fdw/cognito_fdw.rs index 74341b69b..ac1a6a785 100644 --- a/wrappers/src/fdw/cognito_fdw/cognito_fdw.rs +++ b/wrappers/src/fdw/cognito_fdw/cognito_fdw.rs @@ -1,102 +1,34 @@ -use crate::fdw::cognito_fdw::cognito_client::rows_iterator::RowsIterator; -use crate::fdw::cognito_fdw::cognito_client::CognitoClientError; - use std::env; +use std::sync::Arc; -use aws_sdk_cognitoidentityprovider::config::BehaviorVersion; -use aws_sdk_cognitoidentityprovider::Client; +use aws_sdk_cognitoidentityprovider::{config::BehaviorVersion, Client}; use crate::stats; use pgrx::pg_sys; use std::collections::HashMap; use supabase_wrappers::prelude::*; -use pgrx::pg_sys::panic::ErrorReport; -use pgrx::PgSqlErrorCode; -use thiserror::Error; +use super::cognito_client::rows_iterator::RowsIterator; +use super::{CognitoFdwError, CognitoFdwResult}; #[wrappers_fdw( - version = "0.1.2", + version = "0.1.3", author = "Joel", website = "https://github.com/supabase/wrappers/tree/main/wrappers/src/fdw/cognito_fdw", error_type = "CognitoFdwError" )] pub(crate) struct CognitoFdw { - // row counter + rt: Arc, client: aws_sdk_cognitoidentityprovider::Client, user_pool_id: String, rows_iterator: Option, } -#[derive(Error, Debug)] -enum CognitoFdwError { - #[error("{0}")] - CognitoClientError(#[from] CognitoClientError), - - #[error("{0}")] - CreateRuntimeError(#[from] CreateRuntimeError), - - #[error("parse url failed: {0}")] - UrlParseError(#[from] url::ParseError), - - #[error("request failed: {0}")] - RequestError(#[from] reqwest::Error), - - #[error("request middleware failed: {0}")] - RequestMiddlewareError(#[from] reqwest_middleware::Error), - #[error("invalid json response: {0}")] - SerdeError(#[from] serde_json::Error), - - #[error("{0}")] - OptionsError(#[from] OptionsError), - - #[error("{0}")] - NumericConversionError(#[from] pgrx::numeric::Error), - - #[error("no secret found in vault with id {0}")] - SecretNotFound(String), - - #[error("both `api_key` and `api_secret_key` options must be set")] - ApiKeyAndSecretKeySet, - - #[error("exactly one of `aws_secret_access_key` or `api_key_id` options must be set")] - SetOneOfSecretKeyAndApiKeyIdSet, -} - -impl From for ErrorReport { - fn from(value: CognitoFdwError) -> Self { - match value { - CognitoFdwError::CreateRuntimeError(e) => e.into(), - CognitoFdwError::OptionsError(e) => e.into(), - CognitoFdwError::CognitoClientError(e) => e.into(), - CognitoFdwError::SecretNotFound(_) => { - ErrorReport::new(PgSqlErrorCode::ERRCODE_FDW_ERROR, format!("{value}"), "") - } - _ => ErrorReport::new(PgSqlErrorCode::ERRCODE_FDW_ERROR, format!("{value}"), ""), - } - } -} - -type CognitoFdwResult = Result; - impl CognitoFdw { const FDW_NAME: &'static str = "CognitoFdw"; } impl ForeignDataWrapper for CognitoFdw { - // 'options' is the key-value pairs defined in `CREATE SERVER` SQL, for example, - // - // create server my_cognito_server - // foreign data wrapper wrappers_cognito - // options ( - // foo 'bar' - // ); - // 'options' passed here will be a hashmap { 'foo' -> 'bar' }. - // - // You can do any initalization in this new() function, like saving connection - // info or API url in an variable, but don't do any heavy works like making a - // database connection or API call. - fn new(server: ForeignServer) -> Result { let user_pool_id = require_option("user_pool_id", &server.options)?.to_string(); let aws_region = require_option("region", &server.options)?.to_string(); @@ -134,7 +66,9 @@ impl ForeignDataWrapper for CognitoFdw { }); stats::inc_stats(Self::FDW_NAME, stats::Metric::CreateTimes, 1); + Ok(Self { + rt: Arc::new(rt), client, user_pool_id, rows_iterator: None, @@ -149,12 +83,11 @@ impl ForeignDataWrapper for CognitoFdw { _limit: &Option, _options: &HashMap, ) -> CognitoFdwResult<()> { - let cognito_client = &self.client; - let user_pool_id = self.user_pool_id.to_string(); self.rows_iterator = Some(RowsIterator::new( + self.rt.clone(), columns.to_vec(), - user_pool_id, - cognito_client.clone(), + self.user_pool_id.clone(), + self.client.clone(), )); Ok(()) diff --git a/wrappers/src/fdw/cognito_fdw/mod.rs b/wrappers/src/fdw/cognito_fdw/mod.rs index f39ddc336..39d9492ac 100644 --- a/wrappers/src/fdw/cognito_fdw/mod.rs +++ b/wrappers/src/fdw/cognito_fdw/mod.rs @@ -2,3 +2,56 @@ mod cognito_client; mod cognito_fdw; mod tests; + +use pgrx::pg_sys::panic::ErrorReport; +use pgrx::PgSqlErrorCode; +use thiserror::Error; + +use supabase_wrappers::prelude::{CreateRuntimeError, OptionsError}; + +#[derive(Error, Debug)] +enum CognitoFdwError { + #[error("{0}")] + CognitoClientError(#[from] aws_sdk_cognitoidentityprovider::Error), + + #[error("column not supported: {0}")] + UnsupportedColumn(String), + + #[error("{0}")] + CreateRuntimeError(#[from] CreateRuntimeError), + + #[error("parse url failed: {0}")] + UrlParseError(#[from] url::ParseError), + + #[error("request failed: {0}")] + RequestError(#[from] reqwest::Error), + + #[error("request middleware failed: {0}")] + RequestMiddlewareError(#[from] reqwest_middleware::Error), + + #[error("invalid json response: {0}")] + SerdeError(#[from] serde_json::Error), + + #[error("{0}")] + OptionsError(#[from] OptionsError), + + #[error("{0}")] + NumericConversionError(#[from] pgrx::numeric::Error), + + #[error("no secret found in vault with id {0}")] + SecretNotFound(String), + + #[error("both `api_key` and `api_secret_key` options must be set")] + ApiKeyAndSecretKeySet, + + #[error("exactly one of `aws_secret_access_key` or `api_key_id` options must be set")] + SetOneOfSecretKeyAndApiKeyIdSet, +} + +impl From for ErrorReport { + fn from(value: CognitoFdwError) -> Self { + ErrorReport::new(PgSqlErrorCode::ERRCODE_FDW_ERROR, format!("{value}"), "") + } +} + +type CognitoFdwResult = Result;