Skip to content

Commit

Permalink
feat: added support for client and frontend tokens to offline mode. (#…
Browse files Browse the repository at this point in the history
…465)

* feat: added support for client and frontend tokens to offline mode. Assume tokens passed in --tokens are client tokens

* clean up tests to use the new interface

* fix: Added client and frontend tokens to constructor

* Updated CLI docs
  • Loading branch information
chriswk authored Sep 19, 2024
1 parent b124a63 commit b48604c
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 5 deletions.
5 changes: 3 additions & 2 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ Run in offline mode
###### **Options:**

* `-b`, `--bootstrap-file <BOOTSTRAP_FILE>` — The file to load our features from. This data will be loaded at startup
* `-t`, `--tokens <TOKENS>` — Tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--tokens` argument
* `-t`, `--tokens <TOKENS>` — Tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--tokens` argument (v19.4.0) deprecated "Please use --client-tokens | CLIENT_TOKENS instead"
* `-c`, `--client-tokens <CLIENT_TOKENS>` — Client tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--client-tokens` argument
* `-f`, `--frontend-tokens <FRONTEND_TOKENS>` — Frontend tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--frontend-tokens` argument
* `-r`, `--reload-interval <RELOAD_INTERVAL>` — The interval in seconds between reloading the bootstrap file. Disabled if unset or 0

Default value: `0`
Expand Down Expand Up @@ -194,4 +196,3 @@ Perform a ready check against a running edge instance
This document was generated automatically by
<a href="https://crates.io/crates/clap-markdown"><code>clap-markdown</code></a>.
</i></small>

49 changes: 48 additions & 1 deletion server/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,36 @@ async fn hydrate_from_persistent_storage(cache: CacheContainer, storage: Arc<dyn
pub(crate) fn build_offline_mode(
client_features: ClientFeatures,
tokens: Vec<String>,
client_tokens: Vec<String>,
frontend_tokens: Vec<String>,
) -> EdgeResult<CacheContainer> {
let (token_cache, features_cache, engine_cache) = build_caches();

let edge_tokens: Vec<EdgeToken> = tokens
.iter()
.map(|token| EdgeToken::from_str(token).unwrap_or_else(|_| EdgeToken::offline_token(token)))
.map(|mut token| {
token.token_type = Some(TokenType::Client);
token
})
.collect();

let edge_client_tokens: Vec<EdgeToken> = client_tokens
.iter()
.map(|token| EdgeToken::from_str(token).unwrap_or_else(|_| EdgeToken::offline_token(token)))
.map(|mut token| {
token.token_type = Some(TokenType::Client);
token
})
.collect();
let edge_frontend_tokens: Vec<EdgeToken> = frontend_tokens
.iter()
.map(|token| EdgeToken::from_str(token).unwrap_or_else(|_| EdgeToken::offline_token(token)))
.map(|mut token| {
token.token_type = Some(TokenType::Frontend);
token
})
.collect();
for edge_token in edge_tokens {
token_cache.insert(edge_token.token.clone(), edge_token.clone());

Expand All @@ -96,6 +118,24 @@ pub(crate) fn build_offline_mode(
client_features.clone(),
);
}
for client_token in edge_client_tokens {
token_cache.insert(client_token.token.clone(), client_token.clone());
load_offline_engine_cache(
&client_token,
features_cache.clone(),
engine_cache.clone(),
client_features.clone(),
);
}
for frontend_token in edge_frontend_tokens {
token_cache.insert(frontend_token.token.clone(), frontend_token.clone());
load_offline_engine_cache(
&frontend_token,
features_cache.clone(),
engine_cache.clone(),
client_features.clone(),
)
}
Ok((token_cache, features_cache, engine_cache))
}

Expand All @@ -118,7 +158,12 @@ fn build_offline(offline_args: OfflineArgs) -> EdgeResult<CacheContainer> {

let client_features = load_bootstrap(&bootstrap)?;

build_offline_mode(client_features, offline_args.tokens)
build_offline_mode(
client_features,
offline_args.tokens,
offline_args.client_tokens,
offline_args.frontend_tokens,
)
} else {
Err(EdgeError::NoFeaturesFile)
}
Expand Down Expand Up @@ -267,6 +312,8 @@ mod tests {
bootstrap_file: None,
tokens: vec![],
reload_interval: Default::default(),
client_tokens: vec![],
frontend_tokens: vec![],
};

let result = build_offline(args);
Expand Down
7 changes: 7 additions & 0 deletions server/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,15 @@ pub struct OfflineArgs {
#[clap(short, long, env)]
pub bootstrap_file: Option<PathBuf>,
/// Tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--tokens` argument
/// (v19.4.0) deprecated "Please use --client-tokens | CLIENT_TOKENS instead"
#[clap(short, long, env, value_delimiter = ',')]
pub tokens: Vec<String>,
/// Client tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--client-tokens` argument
#[clap(short, long, env, value_delimiter = ',')]
pub client_tokens: Vec<String>,
/// Frontend tokens that should be allowed to connect to Edge. Supports a comma separated list or multiple instances of the `--frontend-tokens` argument
#[clap(short, long, env, value_delimiter = ',')]
pub frontend_tokens: Vec<String>,
/// The interval in seconds between reloading the bootstrap file. Disabled if unset or 0
#[clap(short, long, env, default_value_t = 0)]
pub reload_interval: u64,
Expand Down
2 changes: 2 additions & 0 deletions server/src/client_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ mod tests {
.app_data(Data::new(crate::cli::EdgeMode::Offline(OfflineArgs {
bootstrap_file: Some(PathBuf::from("../examples/features.json")),
tokens: vec!["secret_123".into()],
client_tokens: vec![],
frontend_tokens: vec![],
reload_interval: 0,
})))
.service(web::scope("/api/client").service(get_features)),
Expand Down
39 changes: 37 additions & 2 deletions server/src/frontend_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,8 @@ mod tests {
"*:development.03fa5f506428fe80ed5640c351c7232e38940814d2923b08f5c05fa7"
.to_string(),
],
vec![],
vec![],
)
.unwrap();

Expand Down Expand Up @@ -975,6 +977,8 @@ mod tests {
"*:development.03fa5f506428fe80ed5640c351c7232e38940814d2923b08f5c05fa7"
.to_string(),
],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1023,6 +1027,8 @@ mod tests {
"*:development.03fa5f506428fe80ed5640c351c7232e38940814d2923b08f5c05fa7"
.to_string(),
],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1081,6 +1087,8 @@ mod tests {
"*:development.03fa5f506428fe80ed5640c351c7232e38940814d2923b08f5c05fa7"
.to_string(),
],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1137,6 +1145,8 @@ mod tests {
"*:development.03fa5f506428fe80ed5640c351c7232e38940814d2923b08f5c05fa7"
.to_string(),
],
vec![],
vec![],
)
.unwrap();

Expand Down Expand Up @@ -1248,8 +1258,13 @@ mod tests {
#[tokio::test]
async fn when_running_in_offline_mode_with_proxy_key_should_not_filter_features() {
let client_features = client_features_with_constraint_requiring_user_id_of_seven();
let (token_cache, feature_cache, engine_cache) =
build_offline_mode(client_features.clone(), vec!["secret-123".to_string()]).unwrap();
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features.clone(),
vec!["secret-123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
App::new()
.app_data(Data::from(token_cache))
Expand All @@ -1259,6 +1274,8 @@ mod tests {
bootstrap_file: None,
tokens: vec!["secret-123".into()],
reload_interval: 0,
client_tokens: vec![],
frontend_tokens: vec![],
})))
.service(web::scope("/api/frontend").service(super::get_frontend_all_features)),
)
Expand All @@ -1280,6 +1297,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features.clone(),
vec!["dx:development.secret123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1368,6 +1387,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features,
vec!["dx:development.secret123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1397,6 +1418,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features.clone(),
vec!["dx:development.secret123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1425,6 +1448,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features_with_constraint_requiring_test_property_to_be_42(),
vec!["*:development.secret123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1453,6 +1478,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features.clone(),
vec!["dx:development.secret123".to_string()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down Expand Up @@ -1484,6 +1511,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features_with_custom_context_field.clone(),
vec![auth_key.clone()],
vec![],
vec![],
)
.unwrap();
let config =
Expand Down Expand Up @@ -1524,6 +1553,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features_with_custom_context_field.clone(),
vec![auth_key.clone()],
vec![],
vec![],
)
.unwrap();
let trust_proxy = TrustProxy {
Expand Down Expand Up @@ -1561,6 +1592,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features_with_custom_context_field.clone(),
vec![auth_key.clone()],
vec![],
vec![],
)
.unwrap();
let trust_proxy = TrustProxy {
Expand Down Expand Up @@ -1599,6 +1632,8 @@ mod tests {
let (token_cache, feature_cache, engine_cache) = build_offline_mode(
client_features_with_custom_context_field.clone(),
vec![auth_key.clone()],
vec![],
vec![],
)
.unwrap();
let app = test::init_service(
Expand Down

0 comments on commit b48604c

Please sign in to comment.