Skip to content

Commit 65fbd47

Browse files
committed
fix(providers): allow delegated refresh bootstrap
1 parent 1f130f8 commit 65fbd47

1 file changed

Lines changed: 81 additions & 12 deletions

File tree

crates/openshell-server/src/grpc/provider.rs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,8 @@ async fn provider_type_allows_empty_credentials_for_refresh(
664664
credential.refresh.as_ref().is_some_and(|refresh| {
665665
matches!(
666666
refresh.strategy,
667-
ProviderCredentialRefreshStrategy::Oauth2ClientCredentials
667+
ProviderCredentialRefreshStrategy::Oauth2RefreshToken
668+
| ProviderCredentialRefreshStrategy::Oauth2ClientCredentials
668669
| ProviderCredentialRefreshStrategy::GoogleServiceAccountJwt
669670
)
670671
})
@@ -1221,8 +1222,8 @@ mod tests {
12211222
use openshell_core::proto::{
12221223
DeleteProviderProfileRequest, GetProviderProfileRequest, ImportProviderProfilesRequest,
12231224
L7Allow, L7Rule, LintProviderProfilesRequest, ListProviderProfilesRequest, NetworkBinary,
1224-
NetworkEndpoint, ProviderProfile, ProviderProfileCategory, ProviderProfileImportItem,
1225-
Sandbox, SandboxSpec,
1225+
NetworkEndpoint, ProviderCredentialRefresh, ProviderCredentialRefreshMaterial,
1226+
ProviderProfile, ProviderProfileCategory, ProviderProfileImportItem, Sandbox, SandboxSpec,
12261227
};
12271228
use openshell_core::{ObjectId, ObjectName};
12281229
use std::collections::HashMap;
@@ -2181,12 +2182,11 @@ mod tests {
21812182

21822183
#[tokio::test]
21832184
async fn provider_validation_errors() {
2184-
let store = Store::connect("sqlite::memory:?cache=shared")
2185-
.await
2186-
.unwrap();
2185+
let state = test_server_state().await;
2186+
let store = state.store.as_ref();
21872187

21882188
let create_missing_type = create_provider_record(
2189-
&store,
2189+
store,
21902190
Provider {
21912191
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
21922192
id: String::new(),
@@ -2205,7 +2205,7 @@ mod tests {
22052205
assert_eq!(create_missing_type.code(), Code::InvalidArgument);
22062206

22072207
let create_missing_credentials = create_provider_record(
2208-
&store,
2208+
store,
22092209
Provider {
22102210
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
22112211
id: String::new(),
@@ -2224,7 +2224,7 @@ mod tests {
22242224
assert_eq!(create_missing_credentials.code(), Code::InvalidArgument);
22252225

22262226
let refresh_bootstrap_provider = create_provider_record(
2227-
&store,
2227+
store,
22282228
Provider {
22292229
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
22302230
id: String::new(),
@@ -2242,14 +2242,83 @@ mod tests {
22422242
.unwrap();
22432243
assert!(refresh_bootstrap_provider.credentials.is_empty());
22442244

2245-
let get_err = get_provider_record(&store, "").await.unwrap_err();
2245+
handle_import_provider_profiles(
2246+
&state,
2247+
Request::new(ImportProviderProfilesRequest {
2248+
profiles: vec![ProviderProfileImportItem {
2249+
profile: Some(ProviderProfile {
2250+
id: "delegated-refresh-api".to_string(),
2251+
display_name: "Delegated Refresh API".to_string(),
2252+
description: String::new(),
2253+
category: ProviderProfileCategory::Messaging as i32,
2254+
credentials: vec![openshell_core::proto::ProviderProfileCredential {
2255+
name: "access_token".to_string(),
2256+
description: String::new(),
2257+
env_vars: vec!["DELEGATED_ACCESS_TOKEN".to_string()],
2258+
required: true,
2259+
auth_style: "bearer".to_string(),
2260+
header_name: "authorization".to_string(),
2261+
query_param: String::new(),
2262+
refresh: Some(ProviderCredentialRefresh {
2263+
strategy: ProviderCredentialRefreshStrategy::Oauth2RefreshToken
2264+
as i32,
2265+
token_url: "https://login.example/token".to_string(),
2266+
scopes: vec!["https://example.test/.default".to_string()],
2267+
refresh_before_seconds: 300,
2268+
max_lifetime_seconds: 3600,
2269+
material: vec![
2270+
ProviderCredentialRefreshMaterial {
2271+
name: "client_id".to_string(),
2272+
description: String::new(),
2273+
required: true,
2274+
secret: false,
2275+
},
2276+
ProviderCredentialRefreshMaterial {
2277+
name: "refresh_token".to_string(),
2278+
description: String::new(),
2279+
required: true,
2280+
secret: true,
2281+
},
2282+
],
2283+
}),
2284+
}],
2285+
endpoints: vec![],
2286+
binaries: vec![],
2287+
inference_capable: false,
2288+
}),
2289+
source: "delegated-refresh-api.yaml".to_string(),
2290+
}],
2291+
}),
2292+
)
2293+
.await
2294+
.unwrap();
2295+
let delegated_refresh_bootstrap_provider = create_provider_record(
2296+
store,
2297+
Provider {
2298+
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
2299+
id: String::new(),
2300+
name: "delegated-refresh-no-token-yet".to_string(),
2301+
created_at_ms: 1_000_000,
2302+
labels: HashMap::new(),
2303+
}),
2304+
r#type: "delegated-refresh-api".to_string(),
2305+
credentials: HashMap::new(),
2306+
config: HashMap::new(),
2307+
credential_expires_at_ms: HashMap::new(),
2308+
},
2309+
)
2310+
.await
2311+
.unwrap();
2312+
assert!(delegated_refresh_bootstrap_provider.credentials.is_empty());
2313+
2314+
let get_err = get_provider_record(store, "").await.unwrap_err();
22462315
assert_eq!(get_err.code(), Code::InvalidArgument);
22472316

2248-
let delete_err = delete_provider_record(&store, "").await.unwrap_err();
2317+
let delete_err = delete_provider_record(store, "").await.unwrap_err();
22492318
assert_eq!(delete_err.code(), Code::InvalidArgument);
22502319

22512320
let update_missing_err = update_provider_record(
2252-
&store,
2321+
store,
22532322
Provider {
22542323
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
22552324
id: String::new(),

0 commit comments

Comments
 (0)