Skip to content

Commit

Permalink
Fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
augustuswm committed Apr 12, 2024
1 parent dcbd4d7 commit 92687cc
Show file tree
Hide file tree
Showing 20 changed files with 1,073 additions and 101 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = [
"parse-rfd",
"rfd-api",
"rfd-cli",
"rfd-data",
"rfd-data", "rfd-github",
"rfd-model",
"rfd-processor",
"rfd-redirect",
Expand Down
4 changes: 4 additions & 0 deletions rfd-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ hyper-rustls = { workspace = true }
jsonwebtoken = { workspace = true }
meilisearch-sdk = { workspace = true }
oauth2 = { workspace = true }
octorust = { workspace = true }
partial-struct = { workspace = true }
rand = { workspace = true, features = ["std"] }
rand_core = { workspace = true, features = ["std"] }
regex = { workspace = true }
reqwest = { workspace = true }
reqwest-middleware = { workspace = true }
reqwest-retry = { workspace = true }
reqwest-tracing = { workspace = true }
ring = { workspace = true }
rfd-data = { path = "../rfd-data" }
rfd-model = { path = "../rfd-model" }
Expand Down
19 changes: 19 additions & 0 deletions rfd-api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct AppConfig {
pub spec: Option<SpecConfig>,
pub authn: AuthnProviders,
pub search: SearchConfig,
pub services: ServicesConfig,
}

#[derive(Debug)]
Expand Down Expand Up @@ -144,6 +145,24 @@ pub struct SearchConfig {
pub index: String,
}

#[derive(Debug, Deserialize)]
pub struct ServicesConfig {
pub github: GitHubAuthConfig,
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum GitHubAuthConfig {
Installation {
app_id: i64,
installation_id: i64,
private_key: String,
},
User {
token: String,
},
}

impl AppConfig {
pub fn new(config_sources: Option<Vec<String>>) -> Result<Self, ConfigError> {
let mut config = Config::builder()
Expand Down
126 changes: 122 additions & 4 deletions rfd-api/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ use hyper::{client::HttpConnector, Body, Client};
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
use jsonwebtoken::jwk::JwkSet;
use oauth2::CsrfToken;
use octorust::{
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
http_cache::NoCache,
Client as GitHubClient,
};
use partial_struct::partial;
use rfd_model::{
schema_ext::{ContentFormat, LoginAttemptState, Visibility},
Expand All @@ -23,8 +28,12 @@ use rfd_model::{
AccessGroup, AccessToken, ApiUser, ApiUserProvider, InvalidValueError, Job, LinkRequest,
LoginAttempt, Mapper, NewAccessGroup, NewAccessToken, NewApiKey, NewApiUser,
NewApiUserProvider, NewJob, NewLinkRequest, NewLoginAttempt, NewMapper, NewOAuthClient,
NewOAuthClientRedirectUri, NewOAuthClientSecret, OAuthClient, OAuthClientRedirectUri,
OAuthClientSecret, Rfd,
NewOAuthClientRedirectUri, NewOAuthClientSecret, NewRfdRevision, OAuthClient,
OAuthClientRedirectUri, OAuthClientSecret, Rfd, RfdRevision,
};
use rsa::{
pkcs1::{DecodeRsaPrivateKey, EncodeRsaPrivateKey},
RsaPrivateKey,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand All @@ -45,7 +54,7 @@ use crate::{
key::{RawApiKey, SignedApiKey},
AuthError, AuthToken, Signer,
},
config::{AsymmetricKey, JwtConfig, SearchConfig},
config::{AsymmetricKey, GitHubAuthConfig, JwtConfig, SearchConfig, ServicesConfig},
endpoints::login::{
oauth::{
ClientType, OAuthProvider, OAuthProviderError, OAuthProviderFn, OAuthProviderName,
Expand Down Expand Up @@ -118,6 +127,7 @@ pub struct ApiContext {
pub secrets: SecretContext,
pub oauth_providers: HashMap<OAuthProviderName, Box<dyn OAuthProviderFn>>,
pub search: SearchContext,
pub github: GitHubClient,
}

pub struct JwtContext {
Expand Down Expand Up @@ -218,13 +228,28 @@ impl ApiContext {
jwt: JwtConfig,
keys: Vec<AsymmetricKey>,
search: SearchConfig,
services: ServicesConfig,
) -> Result<Self, AppError> {
let mut jwt_signers = vec![];

for key in &keys {
jwt_signers.push(JwtSigner::new(&key).await.unwrap())
}

let http = reqwest::Client::builder()
.build()
.map_err(AppError::ClientConstruction)?;
let retry_policy =
reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
let client = reqwest_middleware::ClientBuilder::new(http)
// Trace HTTP requests. See the tracing crate to make use of these traces.
.with(reqwest_tracing::TracingMiddleware::default())
// Retry failed requests.
.with(reqwest_retry::RetryTransientMiddleware::new_with_policy(
retry_policy,
))
.build();

Ok(Self {
https_client: hyper::Client::builder().build(
HttpsConnectorBuilder::new()
Expand Down Expand Up @@ -269,6 +294,33 @@ impl ApiContext {
search: SearchContext {
client: SearchClient::new(search.host, search.index, search.key),
},
github: match services.github {
GitHubAuthConfig::Installation {
app_id,
installation_id,
private_key,
} => GitHubClient::custom(
"rfd-api",
Credentials::InstallationToken(InstallationTokenGenerator::new(
installation_id,
JWTCredentials::new(
app_id,
RsaPrivateKey::from_pkcs1_pem(&private_key)?
.to_pkcs1_der()?
.to_bytes()
.to_vec(),
)?,
)),
client,
Box::new(NoCache),
),
GitHubAuthConfig::User { token } => GitHubClient::custom(
"rfd-api",
Credentials::Token(token.to_string()),
client,
Box::new(NoCache),
),
},
})
}

Expand Down Expand Up @@ -668,6 +720,67 @@ impl ApiContext {
}
}

#[instrument(skip(self, caller))]
pub async fn get_rfd_revision(
&self,
caller: &ApiCaller,
rfd_number: i32,
sha: Option<String>,
) -> ResourceResult<RfdRevision, StoreError> {
if caller.any(&[
&ApiPermission::GetRfd(rfd_number),
&ApiPermission::GetRfdsAll,
]) {
let rfds = RfdStore::list(
&*self.storage,
RfdFilter::default().rfd_number(Some(vec![rfd_number])),
&ListPagination::default().limit(1),
)
.await
.to_resource_result()?;
if let Some(rfd) = rfds.into_iter().nth(0) {
let latest_revision = RfdRevisionStore::list(
&*self.storage,
RfdRevisionFilter::default()
.rfd(Some(vec![rfd.id]))
.sha(sha.map(|sha| vec![sha])),
&ListPagination::default().limit(1),
)
.await
.to_resource_result()?;

match latest_revision.into_iter().nth(0) {
Some(revision) => Ok(revision),
None => Err(ResourceError::DoesNotExist),
}
} else {
Err(ResourceError::DoesNotExist)
}
} else {
resource_restricted()
}
}

#[instrument(skip(self, caller))]
pub async fn update_rfd_content<'a>(
&self,
caller: &ApiCaller,
rfd_number: i32,
revision: NewRfdRevision,
) -> ResourceResult<RfdRevision, StoreError> {
if caller.any(&[
&ApiPermission::UpdateRfd(rfd_number),
&ApiPermission::UpdateRfdsAll,
]) {
let revision = RfdRevisionStore::upsert(&*self.storage, revision)
.await
.to_resource_result()?;
Ok(revision)
} else {
resource_restricted()
}
}

#[instrument(skip(self, caller))]
pub async fn update_rfd_visibility(
&self,
Expand Down Expand Up @@ -1885,7 +1998,7 @@ pub(crate) mod test_mocks {
use w_api_permissions::Caller;

use crate::{
config::{JwtConfig, SearchConfig},
config::{GitHubAuthConfig, JwtConfig, SearchConfig, ServicesConfig},
endpoints::login::oauth::{google::GoogleOAuthProvider, OAuthProviderName},
permissions::ApiPermission,
util::tests::mock_key,
Expand All @@ -1904,6 +2017,11 @@ pub(crate) mod test_mocks {
mock_key(),
],
SearchConfig::default(),
ServicesConfig {
github: GitHubAuthConfig::User {
token: String::default(),
},
},
)
.await
.unwrap();
Expand Down
Loading

0 comments on commit 92687cc

Please sign in to comment.