Skip to content

Commit

Permalink
add workspace pin
Browse files Browse the repository at this point in the history
  • Loading branch information
lyang2821 committed Nov 7, 2024
1 parent 5153292 commit f1b8172
Show file tree
Hide file tree
Showing 22 changed files with 496 additions and 108 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions lapdev-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ license.workspace = true
description.workspace = true

[dependencies]
itertools.workspace = true
rustls-webpki.workspace = true
include_dir.workspace = true
toml.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions lapdev-api/pages/not_authorised.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<link rel="stylesheet" href="/error-page/lapdev-main.css">
</head>
<body>
<section class="bg-gray-50 dark:bg-gray-900">
<section class="bg-gray-50">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900">
<svg class="w-10 h-10 mr-4" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 1024 1024">
<path d="M512 0C390.759 0 279.426 42.2227 191.719 112.656L191.719 612L351.719 612L351.719 332L422 332L431.719 332L431.719 332.344C488.169 334.127 541.249 351.138 581.875 380.625C627.591 413.806 654.875 460.633 654.875 512C654.875 563.367 627.591 610.194 581.875 643.375C541.249 672.862 488.169 689.873 431.719 691.656L431.719 1017.69C457.88 1021.81 484.68 1024 512 1024C794.77 1024 1024 794.77 1024 512C1024 229.23 794.77 0 512 0ZM111.719 192.906C41.8539 280.432 0 391.303 0 512C0 738.766 147.487 930.96 351.719 998.25L351.719 692L151.719 692L151.719 691.844L111.719 691.844L111.719 192.906ZM738.219 372C741.597 372.107 745.042 373.02 748.312 374.812L946.281 483.312C952.311 486.616 956.692 492.393 959.188 499.156C959.821 500.874 960.317 502.641 960.688 504.469C960.764 504.834 960.841 505.196 960.906 505.562C961.12 506.807 961.225 508.071 961.312 509.344C961.378 510.235 961.498 511.112 961.5 512C961.498 512.888 961.378 513.765 961.312 514.656C961.226 515.929 961.12 517.193 960.906 518.438C960.841 518.804 960.764 519.166 960.688 519.531C960.317 521.359 959.821 523.126 959.188 524.844C956.692 531.608 952.311 537.384 946.281 540.688L748.312 649.188C735.232 656.355 719.818 649.367 713.875 633.594C707.932 617.82 713.7 599.23 726.781 592.062L872.875 512L726.781 431.938C713.7 424.771 707.932 406.18 713.875 390.406C718.332 378.576 728.085 371.678 738.219 372ZM431.719 412.344L431.719 611.656C513.56 608.208 574.875 561.985 574.875 512C574.875 462.015 513.56 415.792 431.719 412.344Z" />
<path d="M742 403.688C740.062 403.483 738.097 404.438 737.094 406.25C735.756 408.666 736.615 411.694 739.031 413.031L925.719 516.375C928.135 517.712 931.194 516.822 932.531 514.406C933.869 511.99 932.979 508.962 930.562 507.625L743.875 404.281C743.271 403.947 742.646 403.756 742 403.688Z" />
Expand Down
4 changes: 2 additions & 2 deletions lapdev-api/pages/not_forwarded.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<link rel="stylesheet" href="/error-page/lapdev-main.css">
</head>
<body>
<section class="bg-gray-50 dark:bg-gray-900">
<section class="bg-gray-50">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900">
<svg class="w-10 h-10 mr-4" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 1024 1024">
<path d="M512 0C390.759 0 279.426 42.2227 191.719 112.656L191.719 612L351.719 612L351.719 332L422 332L431.719 332L431.719 332.344C488.169 334.127 541.249 351.138 581.875 380.625C627.591 413.806 654.875 460.633 654.875 512C654.875 563.367 627.591 610.194 581.875 643.375C541.249 672.862 488.169 689.873 431.719 691.656L431.719 1017.69C457.88 1021.81 484.68 1024 512 1024C794.77 1024 1024 794.77 1024 512C1024 229.23 794.77 0 512 0ZM111.719 192.906C41.8539 280.432 0 391.303 0 512C0 738.766 147.487 930.96 351.719 998.25L351.719 692L151.719 692L151.719 691.844L111.719 691.844L111.719 192.906ZM738.219 372C741.597 372.107 745.042 373.02 748.312 374.812L946.281 483.312C952.311 486.616 956.692 492.393 959.188 499.156C959.821 500.874 960.317 502.641 960.688 504.469C960.764 504.834 960.841 505.196 960.906 505.562C961.12 506.807 961.225 508.071 961.312 509.344C961.378 510.235 961.498 511.112 961.5 512C961.498 512.888 961.378 513.765 961.312 514.656C961.226 515.929 961.12 517.193 960.906 518.438C960.841 518.804 960.764 519.166 960.688 519.531C960.317 521.359 959.821 523.126 959.188 524.844C956.692 531.608 952.311 537.384 946.281 540.688L748.312 649.188C735.232 656.355 719.818 649.367 713.875 633.594C707.932 617.82 713.7 599.23 726.781 592.062L872.875 512L726.781 431.938C713.7 424.771 707.932 406.18 713.875 390.406C718.332 378.576 728.085 371.678 738.219 372ZM431.719 412.344L431.719 611.656C513.56 608.208 574.875 561.985 574.875 512C574.875 462.015 513.56 415.792 431.719 412.344Z" />
<path d="M742 403.688C740.062 403.483 738.097 404.438 737.094 406.25C735.756 408.666 736.615 411.694 739.031 413.031L925.719 516.375C928.135 517.712 931.194 516.822 932.531 514.406C933.869 511.99 932.979 508.962 930.562 507.625L743.875 404.281C743.271 403.947 742.646 403.756 742 403.688Z" />
Expand Down
4 changes: 2 additions & 2 deletions lapdev-api/pages/not_found.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<link rel="stylesheet" href="/error-page/lapdev-main.css">
</head>
<body>
<section class="bg-gray-50 dark:bg-gray-900">
<section class="bg-gray-50">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900">
<svg class="w-10 h-10 mr-4" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 1024 1024">
<path d="M512 0C390.759 0 279.426 42.2227 191.719 112.656L191.719 612L351.719 612L351.719 332L422 332L431.719 332L431.719 332.344C488.169 334.127 541.249 351.138 581.875 380.625C627.591 413.806 654.875 460.633 654.875 512C654.875 563.367 627.591 610.194 581.875 643.375C541.249 672.862 488.169 689.873 431.719 691.656L431.719 1017.69C457.88 1021.81 484.68 1024 512 1024C794.77 1024 1024 794.77 1024 512C1024 229.23 794.77 0 512 0ZM111.719 192.906C41.8539 280.432 0 391.303 0 512C0 738.766 147.487 930.96 351.719 998.25L351.719 692L151.719 692L151.719 691.844L111.719 691.844L111.719 192.906ZM738.219 372C741.597 372.107 745.042 373.02 748.312 374.812L946.281 483.312C952.311 486.616 956.692 492.393 959.188 499.156C959.821 500.874 960.317 502.641 960.688 504.469C960.764 504.834 960.841 505.196 960.906 505.562C961.12 506.807 961.225 508.071 961.312 509.344C961.378 510.235 961.498 511.112 961.5 512C961.498 512.888 961.378 513.765 961.312 514.656C961.226 515.929 961.12 517.193 960.906 518.438C960.841 518.804 960.764 519.166 960.688 519.531C960.317 521.359 959.821 523.126 959.188 524.844C956.692 531.608 952.311 537.384 946.281 540.688L748.312 649.188C735.232 656.355 719.818 649.367 713.875 633.594C707.932 617.82 713.7 599.23 726.781 592.062L872.875 512L726.781 431.938C713.7 424.771 707.932 406.18 713.875 390.406C718.332 378.576 728.085 371.678 738.219 372ZM431.719 412.344L431.719 611.656C513.56 608.208 574.875 561.985 574.875 512C574.875 462.015 513.56 415.792 431.719 412.344Z" />
<path d="M742 403.688C740.062 403.483 738.097 404.438 737.094 406.25C735.756 408.666 736.615 411.694 739.031 413.031L925.719 516.375C928.135 517.712 931.194 516.822 932.531 514.406C933.869 511.99 932.979 508.962 930.562 507.625L743.875 404.281C743.271 403.947 742.646 403.756 742 403.688Z" />
Expand Down
4 changes: 2 additions & 2 deletions lapdev-api/pages/not_running.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<link rel="stylesheet" href="/error-page/lapdev-main.css">
</head>
<body>
<section class="bg-gray-50 dark:bg-gray-900">
<section class="bg-gray-50">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900">
<svg class="w-10 h-10 mr-4" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 1024 1024">
<path d="M512 0C390.759 0 279.426 42.2227 191.719 112.656L191.719 612L351.719 612L351.719 332L422 332L431.719 332L431.719 332.344C488.169 334.127 541.249 351.138 581.875 380.625C627.591 413.806 654.875 460.633 654.875 512C654.875 563.367 627.591 610.194 581.875 643.375C541.249 672.862 488.169 689.873 431.719 691.656L431.719 1017.69C457.88 1021.81 484.68 1024 512 1024C794.77 1024 1024 794.77 1024 512C1024 229.23 794.77 0 512 0ZM111.719 192.906C41.8539 280.432 0 391.303 0 512C0 738.766 147.487 930.96 351.719 998.25L351.719 692L151.719 692L151.719 691.844L111.719 691.844L111.719 192.906ZM738.219 372C741.597 372.107 745.042 373.02 748.312 374.812L946.281 483.312C952.311 486.616 956.692 492.393 959.188 499.156C959.821 500.874 960.317 502.641 960.688 504.469C960.764 504.834 960.841 505.196 960.906 505.562C961.12 506.807 961.225 508.071 961.312 509.344C961.378 510.235 961.498 511.112 961.5 512C961.498 512.888 961.378 513.765 961.312 514.656C961.226 515.929 961.12 517.193 960.906 518.438C960.841 518.804 960.764 519.166 960.688 519.531C960.317 521.359 959.821 523.126 959.188 524.844C956.692 531.608 952.311 537.384 946.281 540.688L748.312 649.188C735.232 656.355 719.818 649.367 713.875 633.594C707.932 617.82 713.7 599.23 726.781 592.062L872.875 512L726.781 431.938C713.7 424.771 707.932 406.18 713.875 390.406C718.332 378.576 728.085 371.678 738.219 372ZM431.719 412.344L431.719 611.656C513.56 608.208 574.875 561.985 574.875 512C574.875 462.015 513.56 415.792 431.719 412.344Z" />
<path d="M742 403.688C740.062 403.483 738.097 404.438 737.094 406.25C735.756 408.666 736.615 411.694 739.031 413.031L925.719 516.375C928.135 517.712 931.194 516.822 932.531 514.406C933.869 511.99 932.979 508.962 930.562 507.625L743.875 404.281C743.271 403.947 742.646 403.756 742 403.688Z" />
Expand Down
8 changes: 8 additions & 0 deletions lapdev-api/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ fn v1_api_routes(additional_router: Option<Router<CoreState>>) -> Router<CoreSta
"/organizations/:org_id/workspaces/:workspace_name/stop",
post(workspace::stop_workspace),
)
.route(
"/organizations/:org_id/workspaces/:workspace_name/pin",
post(workspace::pin_workspace),
)
.route(
"/organizations/:org_id/workspaces/:workspace_name/unpin",
post(workspace::unpin_workspace),
)
.route(
"/organizations/:org_id/workspaces/:workspace_name/rebuild",
post(workspace::rebuild_workspace),
Expand Down
4 changes: 3 additions & 1 deletion lapdev-api/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct LapdevConfig {
https_port: Option<u16>,
ssh_proxy_port: Option<u16>,
ssh_proxy_display_port: Option<u16>,
force_osuser: Option<String>,
}

#[derive(Parser)]
Expand Down Expand Up @@ -87,7 +88,8 @@ async fn run(
.ok_or_else(|| anyhow!("can't find database url in your config file"))?;

let db = DbApi::new(&db_url, cli.no_migration).await?;
let conductor = Conductor::new(LAPDEV_VERSION, db.clone(), data_folder).await?;
let conductor =
Conductor::new(LAPDEV_VERSION, db.clone(), data_folder, config.force_osuser).await?;

let ssh_proxy_port = config.ssh_proxy_port.unwrap_or(2222);
let ssh_proxy_display_port = config.ssh_proxy_display_port.unwrap_or(2222);
Expand Down
182 changes: 179 additions & 3 deletions lapdev-api/src/workspace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, str::FromStr};
use std::{cmp::Ordering, collections::HashMap, str::FromStr};

use anyhow::Result;
use axum::{
Expand All @@ -9,11 +9,12 @@ use axum::{
use axum_extra::{headers::Cookie, TypedHeader};
use chrono::Utc;
use hyper::StatusCode;
use itertools::Itertools;
use lapdev_common::{
AuditAction, AuditResourceKind, NewWorkspace, RepoBuildResult, UpdateWorkspacePort,
WorkspaceInfo, WorkspacePort, WorkspaceService, WorkspaceStatus,
WorkspaceInfo, WorkspacePort, WorkspaceService, WorkspaceStatus, WorkspaceUpdateEvent,
};
use lapdev_db::entities;
use lapdev_db::{api::LAPDEV_PIN_UNPIN_ERROR, entities};
use lapdev_rpc::error::ApiError;
use sea_orm::{
ActiveModelTrait, ActiveValue, ColumnTrait, EntityTrait, QueryFilter, TransactionTrait,
Expand Down Expand Up @@ -105,8 +106,14 @@ pub async fn all_workspaces(
created_at: w.created_at,
hostname,
build_error: build_result.and_then(|r| r.error),
pinned: w.pinned,
})
})
.sorted_by(|a, b| match (a.pinned, b.pinned) {
(true, true) | (false, false) => b.created_at.cmp(&a.created_at),
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
})
.collect();
Ok(Json(workspaces))
}
Expand Down Expand Up @@ -201,6 +208,7 @@ pub async fn get_workspace(
created_at: ws.created_at,
hostname,
build_error: build_result.and_then(|r| r.error),
pinned: ws.pinned,
};
Ok(Json(info))
}
Expand Down Expand Up @@ -273,6 +281,174 @@ pub async fn stop_workspace(
Ok(StatusCode::NO_CONTENT.into_response())
}

pub async fn pin_workspace(
TypedHeader(cookie): TypedHeader<Cookie>,
Path((org_id, workspace_name)): Path<(Uuid, String)>,
State(state): State<CoreState>,
info: RequestInfo,
) -> Result<Response, ApiError> {
let user = state.authenticate(&cookie).await?;
state
.db
.get_organization_member(user.id, org_id)
.await
.map_err(|_| ApiError::Unauthorized)?;
let ws = state
.db
.get_workspace_by_name(&workspace_name)
.await
.map_err(|_| ApiError::InvalidRequest("workspace name doesn't exist".to_string()))?;
if ws.user_id != user.id {
return Err(ApiError::Unauthorized);
}

let org = state.db.get_organization(ws.organization_id).await?;
if org.running_workspace_limit > 0 {
return Err(ApiError::InvalidRequest(
state
.db
.get_config(LAPDEV_PIN_UNPIN_ERROR)
.await
.unwrap_or_else(|_| "You can't pin/unpin workspaces".to_string()),
));
}

if ws.compose_parent.is_some() {
return Err(ApiError::InvalidRequest(
"you can only pin the main workspace".to_string(),
));
}

if ws.pinned {
return Err(ApiError::InvalidRequest(
"workspace is already pinned".to_string(),
));
}

let now = Utc::now();
let txn = state.db.conn.begin().await?;
state
.conductor
.enterprise
.insert_audit_log(
&txn,
now.into(),
ws.user_id,
ws.organization_id,
AuditResourceKind::Workspace.to_string(),
ws.id,
format!("{} pin", ws.name),
AuditAction::WorkspaceUpdate.to_string(),
info.ip.clone(),
info.user_agent.clone(),
)
.await?;
let ws = entities::workspace::ActiveModel {
id: ActiveValue::Set(ws.id),
pinned: ActiveValue::Set(true),
..Default::default()
}
.update(&txn)
.await?;
txn.commit().await?;

// send a status update to trigger frontend update
state
.conductor
.add_workspace_update_event(
Some(ws.user_id),
ws.id,
WorkspaceUpdateEvent::Status(WorkspaceStatus::from_str(&ws.status)?),
)
.await;

Ok(StatusCode::NO_CONTENT.into_response())
}

pub async fn unpin_workspace(
TypedHeader(cookie): TypedHeader<Cookie>,
Path((org_id, workspace_name)): Path<(Uuid, String)>,
State(state): State<CoreState>,
info: RequestInfo,
) -> Result<Response, ApiError> {
let user = state.authenticate(&cookie).await?;
state
.db
.get_organization_member(user.id, org_id)
.await
.map_err(|_| ApiError::Unauthorized)?;
let ws = state
.db
.get_workspace_by_name(&workspace_name)
.await
.map_err(|_| ApiError::InvalidRequest("workspace name doesn't exist".to_string()))?;
if ws.user_id != user.id {
return Err(ApiError::Unauthorized);
}

let org = state.db.get_organization(ws.organization_id).await?;
if org.running_workspace_limit > 0 {
return Err(ApiError::InvalidRequest(
state
.db
.get_config(LAPDEV_PIN_UNPIN_ERROR)
.await
.unwrap_or_else(|_| "You can't pin/unpin workspaces".to_string()),
));
}

if ws.compose_parent.is_some() {
return Err(ApiError::InvalidRequest(
"you can only unpin the main workspace".to_string(),
));
}

if !ws.pinned {
return Err(ApiError::InvalidRequest(
"workspace is not pinned".to_string(),
));
}

let now = Utc::now();
let txn = state.db.conn.begin().await?;
state
.conductor
.enterprise
.insert_audit_log(
&txn,
now.into(),
ws.user_id,
ws.organization_id,
AuditResourceKind::Workspace.to_string(),
ws.id,
format!("{} unpin", ws.name),
AuditAction::WorkspaceUpdate.to_string(),
info.ip.clone(),
info.user_agent.clone(),
)
.await?;
let ws = entities::workspace::ActiveModel {
id: ActiveValue::Set(ws.id),
pinned: ActiveValue::Set(false),
..Default::default()
}
.update(&txn)
.await?;
txn.commit().await?;

// send a status update to trigger frontend update
state
.conductor
.add_workspace_update_event(
Some(ws.user_id),
ws.id,
WorkspaceUpdateEvent::Status(WorkspaceStatus::from_str(&ws.status)?),
)
.await;

Ok(StatusCode::NO_CONTENT.into_response())
}

pub async fn rebuild_workspace(
TypedHeader(cookie): TypedHeader<Cookie>,
Path((org_id, workspace_name)): Path<(Uuid, String)>,
Expand Down
1 change: 1 addition & 0 deletions lapdev-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ pub struct WorkspaceInfo {
pub created_at: DateTime<FixedOffset>,
pub hostname: String,
pub build_error: Option<RepobuildError>,
pub pinned: bool,
}

#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
Expand Down
1 change: 1 addition & 0 deletions lapdev-conductor/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ mod tests {
deleted_at: ActiveValue::Set(None),
env: ActiveValue::Set(None),
last_inactivity: ActiveValue::Set(None),
pinned: ActiveValue::Set(false),
}
.insert(&txn)
.await
Expand Down
Loading

0 comments on commit f1b8172

Please sign in to comment.