1use rpc::{proto, ErrorCode};
2
3use super::*;
4
5impl Database {
6 pub async fn get_hosted_projects(
7 &self,
8 channel_ids: &[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}