dev_servers.rs

  1use rpc::proto;
  2use sea_orm::{
  3    ActiveValue, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter,
  4};
  5
  6use super::{dev_server, dev_server_project, Database, DevServerId, UserId};
  7
  8impl Database {
  9    pub async fn get_dev_server(
 10        &self,
 11        dev_server_id: DevServerId,
 12    ) -> crate::Result<dev_server::Model> {
 13        self.transaction(|tx| async move {
 14            Ok(dev_server::Entity::find_by_id(dev_server_id)
 15                .one(&*tx)
 16                .await?
 17                .ok_or_else(|| anyhow::anyhow!("no dev server with id {}", dev_server_id))?)
 18        })
 19        .await
 20    }
 21
 22    pub async fn get_dev_servers(&self, user_id: UserId) -> crate::Result<Vec<dev_server::Model>> {
 23        self.transaction(|tx| async move {
 24            Ok(dev_server::Entity::find()
 25                .filter(dev_server::Column::UserId.eq(user_id))
 26                .all(&*tx)
 27                .await?)
 28        })
 29        .await
 30    }
 31
 32    pub async fn dev_server_projects_update(
 33        &self,
 34        user_id: UserId,
 35    ) -> crate::Result<proto::DevServerProjectsUpdate> {
 36        self.transaction(|tx| async move {
 37            self.dev_server_projects_update_internal(user_id, &tx).await
 38        })
 39        .await
 40    }
 41
 42    pub async fn dev_server_projects_update_internal(
 43        &self,
 44        user_id: UserId,
 45        tx: &DatabaseTransaction,
 46    ) -> crate::Result<proto::DevServerProjectsUpdate> {
 47        let dev_servers = dev_server::Entity::find()
 48            .filter(dev_server::Column::UserId.eq(user_id))
 49            .all(tx)
 50            .await?;
 51
 52        let dev_server_projects = dev_server_project::Entity::find()
 53            .filter(
 54                dev_server_project::Column::DevServerId
 55                    .is_in(dev_servers.iter().map(|d| d.id).collect::<Vec<_>>()),
 56            )
 57            .find_also_related(super::project::Entity)
 58            .all(tx)
 59            .await?;
 60
 61        Ok(proto::DevServerProjectsUpdate {
 62            dev_servers: dev_servers
 63                .into_iter()
 64                .map(|d| d.to_proto(proto::DevServerStatus::Offline))
 65                .collect(),
 66            dev_server_projects: dev_server_projects
 67                .into_iter()
 68                .map(|(dev_server_project, project)| dev_server_project.to_proto(project))
 69                .collect(),
 70        })
 71    }
 72
 73    pub async fn create_dev_server(
 74        &self,
 75        name: &str,
 76        hashed_access_token: &str,
 77        user_id: UserId,
 78    ) -> crate::Result<(dev_server::Model, proto::DevServerProjectsUpdate)> {
 79        self.transaction(|tx| async move {
 80            let dev_server = dev_server::Entity::insert(dev_server::ActiveModel {
 81                id: ActiveValue::NotSet,
 82                hashed_token: ActiveValue::Set(hashed_access_token.to_string()),
 83                name: ActiveValue::Set(name.to_string()),
 84                user_id: ActiveValue::Set(user_id),
 85            })
 86            .exec_with_returning(&*tx)
 87            .await?;
 88
 89            let dev_server_projects = self
 90                .dev_server_projects_update_internal(user_id, &tx)
 91                .await?;
 92
 93            Ok((dev_server, dev_server_projects))
 94        })
 95        .await
 96    }
 97
 98    pub async fn delete_dev_server(
 99        &self,
100        id: DevServerId,
101        user_id: UserId,
102    ) -> crate::Result<proto::DevServerProjectsUpdate> {
103        self.transaction(|tx| async move {
104            let Some(dev_server) = dev_server::Entity::find_by_id(id).one(&*tx).await? else {
105                return Err(anyhow::anyhow!("no dev server with id {}", id))?;
106            };
107            if dev_server.user_id != user_id {
108                return Err(anyhow::anyhow!(proto::ErrorCode::Forbidden))?;
109            }
110
111            dev_server_project::Entity::delete_many()
112                .filter(dev_server_project::Column::DevServerId.eq(id))
113                .exec(&*tx)
114                .await?;
115
116            dev_server::Entity::delete(dev_server.into_active_model())
117                .exec(&*tx)
118                .await?;
119
120            let dev_server_projects = self
121                .dev_server_projects_update_internal(user_id, &tx)
122                .await?;
123
124            Ok(dev_server_projects)
125        })
126        .await
127    }
128}