Skip to content

Commit

Permalink
Merge branch 'main' into feat/search-database-by-name
Browse files Browse the repository at this point in the history
  • Loading branch information
speed2exe committed Nov 21, 2024
2 parents d7478fb + 1e18180 commit 687b5d9
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 170 deletions.
85 changes: 54 additions & 31 deletions libs/access-control/src/casbin/collab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tracing::instrument;
use crate::{
act::{Action, ActionVariant},
collab::{CollabAccessControl, RealtimeAccessControl},
entity::{ObjectType, SubjectType},
entity::ObjectType,
};

use super::access::AccessControl;
Expand All @@ -28,16 +28,25 @@ impl CollabAccessControl for CollabAccessControlImpl {
&self,
workspace_id: &str,
uid: &i64,
oid: &str,
_oid: &str,
action: Action,
) -> Result<(), AppError> {
// TODO: allow non workspace member to read a collab.

// Anyone who can write to a workspace, can also delete a collab.
let workspace_action = match action {
Action::Read => Action::Read,
Action::Write => Action::Write,
Action::Delete => Action::Write,
};

self
.access_control
.enforce(
workspace_id,
uid,
ObjectType::Collab(oid),
ActionVariant::FromAction(&action),
ObjectType::Workspace(workspace_id),
ActionVariant::FromAction(&workspace_action),
)
.await
}
Expand All @@ -46,45 +55,44 @@ impl CollabAccessControl for CollabAccessControlImpl {
&self,
workspace_id: &str,
uid: &i64,
oid: &str,
_oid: &str,
access_level: AFAccessLevel,
) -> Result<(), AppError> {
// TODO: allow non workspace member to read a collab.

// Anyone who can write to a workspace, also have full access to a collab.
let workspace_action = match access_level {
AFAccessLevel::ReadOnly => Action::Read,
AFAccessLevel::ReadAndComment => Action::Read,
AFAccessLevel::ReadAndWrite => Action::Write,
AFAccessLevel::FullAccess => Action::Write,
};

self
.access_control
.enforce(
workspace_id,
uid,
ObjectType::Collab(oid),
ActionVariant::FromAccessLevel(&access_level),
ObjectType::Workspace(workspace_id),
ActionVariant::FromAction(&workspace_action),
)
.await
}

#[instrument(level = "info", skip_all)]
async fn update_access_level_policy(
&self,
uid: &i64,
oid: &str,
level: AFAccessLevel,
_uid: &i64,
_oid: &str,
_level: AFAccessLevel,
) -> Result<(), AppError> {
self
.access_control
.update_policy(
SubjectType::User(*uid),
ObjectType::Collab(oid),
ActionVariant::FromAccessLevel(&level),
)
.await?;

// TODO: allow non workspace member to read a collab.
Ok(())
}

#[instrument(level = "info", skip_all)]
async fn remove_access_level(&self, uid: &i64, oid: &str) -> Result<(), AppError> {
self
.access_control
.remove_policy(&SubjectType::User(*uid), &ObjectType::Collab(oid))
.await?;
async fn remove_access_level(&self, _uid: &i64, _oid: &str) -> Result<(), AppError> {
// TODO: allow non workspace member to read a collab.
Ok(())
}
}
Expand All @@ -103,20 +111,35 @@ impl RealtimeCollabAccessControlImpl {
&self,
workspace_id: &str,
uid: &i64,
oid: &str,
_oid: &str,
required_action: Action,
) -> Result<bool, AppError> {
self
// TODO: allow non workspace member to read a collab.

// Anyone who can write to a workspace, can also delete a collab.
let workspace_action = match required_action {
Action::Read => Action::Read,
Action::Write => Action::Write,
Action::Delete => Action::Write,
};

let enforcement_result = self
.access_control
.enforce(
workspace_id,
uid,
ObjectType::Collab(oid),
ActionVariant::FromAction(&required_action),
ObjectType::Workspace(workspace_id),
ActionVariant::FromAction(&workspace_action),
)
.await?;

Ok(true)
.await;
match enforcement_result {
Ok(_) => Ok(true),
Err(AppError::NotEnoughPermissions {
user: _user,
workspace_id: _workspace_id,
}) => Ok(false),
Err(e) => Err(e),
}
}
}

Expand Down
47 changes: 3 additions & 44 deletions libs/client-api-test/src/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ use client_api::entity::{
};
use client_api::ws::{WSClient, WSClientConfig};
use database_entity::dto::{
AFAccessLevel, AFRole, AFSnapshotMeta, AFSnapshotMetas, AFUserProfile, AFUserWorkspaceInfo,
AFWorkspace, AFWorkspaceInvitationStatus, AFWorkspaceMember, BatchQueryCollabResult,
CollabParams, CreateCollabParams, InsertCollabMemberParams, QueryCollab, QueryCollabParams,
QuerySnapshotParams, SnapshotData, UpdateCollabMemberParams,
AFRole, AFSnapshotMeta, AFSnapshotMetas, AFUserProfile, AFUserWorkspaceInfo, AFWorkspace,
AFWorkspaceInvitationStatus, AFWorkspaceMember, BatchQueryCollabResult, CollabParams,
CreateCollabParams, QueryCollab, QueryCollabParams, QuerySnapshotParams, SnapshotData,
};
use shared_entity::dto::workspace_dto::{
BlobMetadata, CollabResponse, PublishedDuplicate, WorkspaceMemberChangeset,
Expand Down Expand Up @@ -441,46 +440,6 @@ impl TestClient {
self.api_client.get_workspace_member(params).await
}

pub async fn add_collab_member(
&self,
workspace_id: &str,
object_id: &str,
other_client: &TestClient,
access_level: AFAccessLevel,
) {
let uid = other_client.uid().await;
self
.api_client
.add_collab_member(InsertCollabMemberParams {
uid,
workspace_id: workspace_id.to_string(),
object_id: object_id.to_string(),
access_level,
})
.await
.unwrap();
}

pub async fn update_collab_member_access_level(
&self,
workspace_id: &str,
object_id: &str,
other_client: &TestClient,
access_level: AFAccessLevel,
) {
let uid = other_client.uid().await;
self
.api_client
.update_collab_member(UpdateCollabMemberParams {
uid,
workspace_id: workspace_id.to_string(),
object_id: object_id.to_string(),
access_level,
})
.await
.unwrap();
}

pub async fn wait_object_sync_complete(&self, object_id: &str) -> Result<(), Error> {
self
.wait_object_sync_complete_with_secs(object_id, 60)
Expand Down
21 changes: 20 additions & 1 deletion libs/client-api/src/http_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use client_api_entity::workspace_dto::{
CreatePageParams, CreateSpaceParams, Page, PageCollab, Space, UpdatePageParams,
CreatePageParams, CreateSpaceParams, Page, PageCollab, Space, UpdatePageParams, UpdateSpaceParams,
};
use reqwest::Method;
use serde_json::json;
Expand Down Expand Up @@ -129,4 +129,23 @@ impl Client {
.await?;
AppResponse::<Space>::from_response(resp).await?.into_data()
}

pub async fn update_space(
&self,
workspace_id: Uuid,
view_id: &str,
params: &UpdateSpaceParams,
) -> Result<(), AppResponseError> {
let url = format!(
"{}/api/workspace/{}/space/{}",
self.base_url, workspace_id, view_id
);
let resp = self
.http_client_with_auth(Method::PATCH, &url)
.await?
.json(params)
.send()
.await?;
AppResponse::<()>::from_response(resp).await?.into_error()
}
}
8 changes: 8 additions & 0 deletions libs/shared-entity/src/dto/workspace_dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ pub struct CreateSpaceParams {
pub space_icon_color: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateSpaceParams {
pub space_permission: SpacePermission,
pub name: String,
pub space_icon: String,
pub space_icon_color: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreatePageParams {
pub parent_view_id: String,
Expand Down
7 changes: 7 additions & 0 deletions services/appflowy-worker/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ pub async fn create_app(listener: TcpListener, config: Config) -> Result<(), Err
.parse::<u64>()
.unwrap_or(10);

// Maximum file size for import
let maximum_import_file_size =
get_env_var("APPFLOWY_WORKER_MAX_IMPORT_FILE_SIZE", "1_000_000_000")
.parse::<u64>()
.unwrap_or(1_000_000_000);

let import_worker_fut = local_set.run_until(run_import_worker(
state.pg_pool.clone(),
state.redis_client.clone(),
Expand All @@ -115,6 +121,7 @@ pub async fn create_app(listener: TcpListener, config: Config) -> Result<(), Err
Arc::new(email_notifier),
"import_task_stream",
tick_interval,
maximum_import_file_size,
));

let app = Router::new()
Expand Down
30 changes: 30 additions & 0 deletions services/appflowy-worker/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ pub enum ImportError {
#[error("Upload file expired")]
UploadFileExpire,

#[error("Please upgrade to the latest version of the app")]
UpgradeToLatestVersion(String),

#[error("Upload file too large")]
UploadFileTooLarge {
file_size_in_mb: f64,
max_size_in_mb: f64,
},

#[error(transparent)]
Internal(#[from] anyhow::Error),
}
Expand Down Expand Up @@ -184,6 +193,27 @@ impl ImportError {
format!("Task ID: {} - Upload file expired", task_id),
)
}
ImportError::UpgradeToLatestVersion(s) => {
(
format!(
"Task ID: {} - {}, please upgrade to the latest version of the app to import this file",
task_id,
s,

),
format!("Task ID: {} - Upgrade to latest version", task_id),
)
}
ImportError::UploadFileTooLarge{ file_size_in_mb, max_size_in_mb}=> {
(
format!(
"Task ID: {} - The file size is too large. The maximum file size allowed is {} MB. Please upload a smaller file.",
task_id,
max_size_in_mb,
),
format!("Task ID: {} - Upload file too large: {} MB", task_id, file_size_in_mb),
)
}
}
}
}
Loading

0 comments on commit 687b5d9

Please sign in to comment.