hosted_projects.rs

 1use rpc::{proto, ErrorCode};
 2
 3use super::*;
 4
 5impl Database {
 6    pub async fn get_hosted_projects(
 7        &self,
 8        channel_ids: &Vec<ChannelId>,
 9        roles: &HashMap<ChannelId, ChannelRole>,
10        tx: &DatabaseTransaction,
11    ) -> Result<Vec<proto::HostedProject>> {
12        let projects = hosted_project::Entity::find()
13            .find_also_related(project::Entity)
14            .filter(hosted_project::Column::ChannelId.is_in(channel_ids.iter().map(|id| id.0)))
15            .all(tx)
16            .await?
17            .into_iter()
18            .flat_map(|(hosted_project, project)| {
19                if hosted_project.deleted_at.is_some() {
20                    return None;
21                }
22                match hosted_project.visibility {
23                    ChannelVisibility::Public => {}
24                    ChannelVisibility::Members => {
25                        let is_visible = roles
26                            .get(&hosted_project.channel_id)
27                            .map(|role| role.can_see_all_descendants())
28                            .unwrap_or(false);
29                        if !is_visible {
30                            return None;
31                        }
32                    }
33                };
34                Some(proto::HostedProject {
35                    project_id: project?.id.to_proto(),
36                    channel_id: hosted_project.channel_id.to_proto(),
37                    name: hosted_project.name.clone(),
38                    visibility: hosted_project.visibility.into(),
39                })
40            })
41            .collect();
42
43        Ok(projects)
44    }
45
46    pub async fn get_hosted_project(
47        &self,
48        hosted_project_id: HostedProjectId,
49        user_id: UserId,
50        tx: &DatabaseTransaction,
51    ) -> Result<(hosted_project::Model, ChannelRole)> {
52        let project = hosted_project::Entity::find_by_id(hosted_project_id)
53            .one(tx)
54            .await?
55            .ok_or_else(|| anyhow!(ErrorCode::NoSuchProject))?;
56        let channel = channel::Entity::find_by_id(project.channel_id)
57            .one(tx)
58            .await?
59            .ok_or_else(|| anyhow!(ErrorCode::NoSuchChannel))?;
60
61        let role = match project.visibility {
62            ChannelVisibility::Public => {
63                self.check_user_is_channel_participant(&channel, user_id, tx)
64                    .await?
65            }
66            ChannelVisibility::Members => {
67                self.check_user_is_channel_member(&channel, user_id, tx)
68                    .await?
69            }
70        };
71
72        Ok((project, role))
73    }
74
75    pub async fn is_hosted_project(&self, project_id: ProjectId) -> Result<bool> {
76        self.transaction(|tx| async move {
77            Ok(project::Entity::find_by_id(project_id)
78                .one(&*tx)
79                .await?
80                .map(|project| project.hosted_project_id.is_some())
81                .ok_or_else(|| anyhow!(ErrorCode::NoSuchProject))?)
82        })
83        .await
84    }
85}