- db.rs: add nullable git_token column (idempotent ALTER TABLE ADD COLUMN)
- models.rs: git_token on App (#[serde(skip_serializing)]), CreateApp, UpdateApp
- routes/apps.rs: encrypt token on create/update; empty string clears it
- builder.rs: decrypt token, pass as GIT_TOKEN env var to build script
- build.sh: GIT_TERMINAL_PROMPT=0 (fail fast, not hang); when GIT_TOKEN is
set, inject it into the HTTPS clone URL as x-token-auth; strip credentials
from .git/config after clone/fetch so the token is never persisted to disk
Token usage: PATCH /api/apps/:id with {"git_token": "ghp_..."}
Clear token: PATCH /api/apps/:id with {"git_token": ""}
https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
124 lines
2.9 KiB
Rust
124 lines
2.9 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct App {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub repo_url: String,
|
|
pub branch: String,
|
|
pub port: i64,
|
|
pub webhook_secret: String,
|
|
pub memory_limit: String,
|
|
pub cpu_limit: String,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
/// Encrypted git token for cloning private repos. Never serialised to API responses.
|
|
#[serde(skip_serializing)]
|
|
pub git_token: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct CreateApp {
|
|
pub name: String,
|
|
pub repo_url: Option<String>,
|
|
pub branch: Option<String>,
|
|
pub port: i64,
|
|
pub memory_limit: Option<String>,
|
|
pub cpu_limit: Option<String>,
|
|
pub git_token: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct UpdateApp {
|
|
pub repo_url: Option<String>,
|
|
pub branch: Option<String>,
|
|
pub port: Option<i64>,
|
|
pub memory_limit: Option<String>,
|
|
pub cpu_limit: Option<String>,
|
|
pub git_token: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct Deploy {
|
|
pub id: String,
|
|
pub app_id: String,
|
|
pub sha: Option<String>,
|
|
pub status: String,
|
|
pub log: String,
|
|
pub triggered_by: String,
|
|
pub started_at: Option<String>,
|
|
pub finished_at: Option<String>,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct EnvVar {
|
|
pub app_id: String,
|
|
pub key: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SetEnvVar {
|
|
pub key: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct User {
|
|
pub id: String,
|
|
pub username: String,
|
|
pub password_hash: String,
|
|
pub is_admin: i64,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct CreateUser {
|
|
pub username: String,
|
|
pub password: String,
|
|
pub is_admin: Option<bool>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct UpdateUser {
|
|
pub password: Option<String>,
|
|
pub is_admin: Option<bool>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct SshKey {
|
|
pub id: String,
|
|
pub user_id: String,
|
|
pub label: String,
|
|
pub public_key: String,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct CreateSshKey {
|
|
pub label: String,
|
|
pub public_key: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct ApiKey {
|
|
pub id: String,
|
|
pub user_id: String,
|
|
pub label: String,
|
|
pub created_at: String,
|
|
// key_hash is intentionally not exposed in serialised output
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct CreateApiKey {
|
|
pub label: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct Database {
|
|
pub app_id: String,
|
|
pub pg_user: String,
|
|
pub pg_password: String,
|
|
pub created_at: String,
|
|
}
|