Skip to content

Commit

Permalink
feat: implemented find resources and improved project domain
Browse files Browse the repository at this point in the history
  • Loading branch information
paulobressan committed Jul 31, 2024
1 parent d79484e commit 322e482
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 85 deletions.
55 changes: 36 additions & 19 deletions Cargo.lock

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

2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ reqwest = { version = "0.12.5", features = ["json", "rustls-tls-webpki-roots"] }
jsonwebtoken = "9.3.0"
bech32 = "0.11.0"
argon2 = "0.5.3"
tower = "0.4.13"
hyper = "1.4.1"
chrono = "0.4.38"

[dev-dependencies]
Expand Down
2 changes: 0 additions & 2 deletions src/domain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ pub mod resource;

pub const PAGE_SIZE_DEFAULT: u32 = 12;
pub const PAGE_SIZE_MAX: u32 = 120;

pub type Count = u32;
84 changes: 69 additions & 15 deletions src/domain/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ use crate::domain::PAGE_SIZE_MAX;
use super::{
auth::{Credential, UserId},
event::{EventDrivenBridge, ProjectCreated, ProjectSecretCreated},
Count, PAGE_SIZE_DEFAULT,
PAGE_SIZE_DEFAULT,
};

pub async fn create(
cache: Arc<dyn ProjectDrivenCache>,
event: Arc<dyn EventDrivenBridge>,
cmd: CreateProjectCmd,
) -> Result<()> {
let user_id = assert_permission(cmd.credential)?;
let user_id = assert_credential(&cmd.credential)?;

if cache.find_by_namespace(&cmd.namespace).await?.is_some() {
bail!("invalid project namespace")
Expand Down Expand Up @@ -58,8 +58,8 @@ pub async fn create_cache(cache: Arc<dyn ProjectDrivenCache>, evt: ProjectCreate
pub async fn find_cache(
cache: Arc<dyn ProjectDrivenCache>,
cmd: FindProjectCmd,
) -> Result<(Vec<ProjectCache>, Count)> {
let user_id = assert_permission(cmd.credential)?;
) -> Result<Vec<ProjectCache>> {
let user_id = assert_credential(&cmd.credential)?;

cache.find(&user_id, &cmd.page, &cmd.page_size).await
}
Expand Down Expand Up @@ -93,7 +93,8 @@ pub async fn create_secret(
event: Arc<dyn EventDrivenBridge>,
cmd: CreateProjectSecretCmd,
) -> Result<String> {
assert_permission(cmd.credential)?;
assert_credential(&cmd.credential)?;
assert_permission(cache.clone(), &cmd.credential, &cmd.project_id).await?;

let Some(project) = cache.find_by_id(&cmd.project_id).await? else {
bail!("project doesnt exist")
Expand Down Expand Up @@ -190,9 +191,23 @@ pub async fn verify_secret(
Ok(secret)
}

fn assert_permission(credential: Credential) -> Result<UserId> {
fn assert_credential(credential: &Credential) -> Result<UserId> {
match credential {
Credential::Auth0(user_id) => Ok(user_id),
Credential::Auth0(user_id) => Ok(user_id.into()),
Credential::ApiKey(_) => bail!("rpc doesnt support api-key"),
}
}
async fn assert_permission(
cache: Arc<dyn ProjectDrivenCache>,
credential: &Credential,
project_id: &str,
) -> Result<()> {
match credential {
Credential::Auth0(user_id) => {
let result = cache.find_user_permission(user_id, project_id).await?;
ensure!(result.is_some(), "user doesnt have permission");
Ok(())
}
Credential::ApiKey(_) => bail!("rpc doesnt support api-key"),
}
}
Expand Down Expand Up @@ -351,12 +366,7 @@ pub struct ProjectUserCache {

#[async_trait::async_trait]
pub trait ProjectDrivenCache: Send + Sync {
async fn find(
&self,
user_id: &str,
page: &u32,
page_size: &u32,
) -> Result<(Vec<ProjectCache>, Count)>;
async fn find(&self, user_id: &str, page: &u32, page_size: &u32) -> Result<Vec<ProjectCache>>;
async fn find_by_namespace(&self, namespace: &str) -> Result<Option<ProjectCache>>;
async fn find_by_id(&self, id: &str) -> Result<Option<ProjectCache>>;
async fn create(&self, project: &ProjectCache) -> Result<()>;
Expand Down Expand Up @@ -389,7 +399,7 @@ mod tests {

#[async_trait::async_trait]
impl ProjectDrivenCache for FakeProjectDrivenCache {
async fn find(&self, user_id: &str, page: &u32, page_size: &u32) -> Result<(Vec<ProjectCache>, Count)>;
async fn find(&self, user_id: &str, page: &u32, page_size: &u32) -> Result<Vec<ProjectCache>>;
async fn find_by_namespace(&self, namespace: &str) -> Result<Option<ProjectCache>>;
async fn find_by_id(&self, id: &str) -> Result<Option<ProjectCache>>;
async fn create(&self, project: &ProjectCache) -> Result<()>;
Expand Down Expand Up @@ -472,6 +482,15 @@ mod tests {
}
}
}
impl Default for FindProjectCmd {
fn default() -> Self {
Self {
credential: Credential::Auth0("user id".into()),
page: 1,
page_size: 12,
}
}
}
impl Default for ProjectSecretCache {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -547,6 +566,7 @@ mod tests {
let result = create(Arc::new(cache), Arc::new(event), cmd).await;
assert!(result.is_err());
}

#[tokio::test]
async fn it_should_create_project_cache() {
let mut cache = MockFakeProjectDrivenCache::new();
Expand All @@ -558,9 +578,25 @@ mod tests {
assert!(result.is_ok());
}

#[tokio::test]
async fn it_should_find_user_projects_cache() {
let mut cache = MockFakeProjectDrivenCache::new();
cache
.expect_find()
.return_once(|_, _, _| Ok(vec![ProjectCache::default()]));

let evt = FindProjectCmd::default();

let result = find_cache(Arc::new(cache), evt).await;
assert!(result.is_ok());
}

#[tokio::test]
async fn it_should_create_project_secret() {
let mut cache = MockFakeProjectDrivenCache::new();
cache
.expect_find_user_permission()
.return_once(|_, _| Ok(Some(ProjectUserCache::default())));
cache
.expect_find_by_id()
.return_once(|_| Ok(Some(ProjectCache::default())));
Expand All @@ -576,6 +612,9 @@ mod tests {
#[tokio::test]
async fn it_should_fail_create_project_secret_when_project_doesnt_exists() {
let mut cache = MockFakeProjectDrivenCache::new();
cache
.expect_find_user_permission()
.return_once(|_, _| Ok(Some(ProjectUserCache::default())));
cache.expect_find_by_id().return_once(|_| Ok(None));

let event = MockFakeEventDrivenBridge::new();
Expand All @@ -586,7 +625,7 @@ mod tests {
assert!(result.is_err());
}
#[tokio::test]
async fn it_should_fail_create_project_secret_when_invalid_permission() {
async fn it_should_fail_create_project_secret_when_invalid_credential() {
let cache = MockFakeProjectDrivenCache::new();
let event = MockFakeEventDrivenBridge::new();

Expand All @@ -598,6 +637,21 @@ mod tests {
let result = create_secret(Arc::new(cache), Arc::new(event), cmd).await;
assert!(result.is_err());
}
#[tokio::test]
async fn it_should_fail_create_project_secret_when_invalid_permission() {
let mut cache = MockFakeProjectDrivenCache::new();
cache
.expect_find_user_permission()
.return_once(|_, _| Ok(None));

let event = MockFakeEventDrivenBridge::new();

let cmd = CreateProjectSecretCmd::default();

let result = create_secret(Arc::new(cache), Arc::new(event), cmd).await;
assert!(result.is_err());
}

#[tokio::test]
async fn it_should_create_project_secret_cache() {
let mut cache = MockFakeProjectDrivenCache::new();
Expand Down
Loading

0 comments on commit 322e482

Please sign in to comment.