2025-11-29 16:29:28 -03:00
|
|
|
use anyhow::Result;
|
|
|
|
|
use aws_sdk_s3::Client as S3Client;
|
2025-12-02 21:09:43 -03:00
|
|
|
use diesel::r2d2::{ConnectionManager, Pool};
|
2025-11-29 16:29:28 -03:00
|
|
|
use diesel::PgConnection;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
2025-12-02 21:09:43 -03:00
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
use std::sync::Arc;
|
2025-12-02 21:09:43 -03:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
|
|
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
pub struct UserProvisioningService {
|
2025-12-02 21:09:43 -03:00
|
|
|
db_pool: DbPool,
|
|
|
|
|
s3_client: Option<Arc<S3Client>>,
|
2025-11-29 16:29:28 -03:00
|
|
|
base_url: String,
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
impl std::fmt::Debug for UserProvisioningService {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
f.debug_struct("UserProvisioningService")
|
|
|
|
|
.field("base_url", &self.base_url)
|
|
|
|
|
.field("has_s3_client", &self.s3_client.is_some())
|
|
|
|
|
.finish_non_exhaustive()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
pub struct UserAccount {
|
|
|
|
|
pub username: String,
|
|
|
|
|
pub email: String,
|
|
|
|
|
pub first_name: String,
|
|
|
|
|
pub last_name: String,
|
|
|
|
|
pub organization: String,
|
|
|
|
|
pub is_admin: bool,
|
|
|
|
|
pub bots: Vec<BotAccess>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
pub struct BotAccess {
|
|
|
|
|
pub bot_id: String,
|
|
|
|
|
pub bot_name: String,
|
|
|
|
|
pub role: UserRole,
|
|
|
|
|
pub home_path: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
pub enum UserRole {
|
|
|
|
|
Admin,
|
|
|
|
|
User,
|
|
|
|
|
ReadOnly,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl UserProvisioningService {
|
2025-12-02 21:09:43 -03:00
|
|
|
pub fn new(db_pool: DbPool, s3_client: Option<Arc<S3Client>>, base_url: String) -> Self {
|
2025-11-29 16:29:28 -03:00
|
|
|
Self {
|
2025-12-02 21:09:43 -03:00
|
|
|
db_pool,
|
2025-11-29 16:29:28 -03:00
|
|
|
s3_client,
|
|
|
|
|
base_url,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
pub fn get_base_url(&self) -> &str {
|
|
|
|
|
&self.base_url
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn build_profile_url(&self, username: &str) -> String {
|
|
|
|
|
format!("{}/users/{}/profile", self.base_url, username)
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
pub async fn provision_user(&self, account: &UserAccount) -> Result<()> {
|
2025-12-02 21:09:43 -03:00
|
|
|
log::info!(
|
|
|
|
|
"Provisioning user: {} via directory at {}",
|
|
|
|
|
account.username,
|
|
|
|
|
self.base_url
|
|
|
|
|
);
|
2025-11-29 16:29:28 -03:00
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
let user_id = self.create_database_user(account)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
for bot_access in &account.bots {
|
|
|
|
|
self.create_s3_home(account, bot_access).await?;
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
if let Err(e) = self.setup_email_account(account) {
|
2025-11-29 16:29:28 -03:00
|
|
|
log::warn!("Email account creation failed: {}", e);
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
self.setup_oauth_config(&user_id, account)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let profile_url = self.build_profile_url(&account.username);
|
|
|
|
|
log::info!(
|
|
|
|
|
"User {} provisioned successfully. Profile: {}",
|
|
|
|
|
account.username,
|
|
|
|
|
profile_url
|
|
|
|
|
);
|
2025-11-29 16:29:28 -03:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
fn create_database_user(&self, account: &UserAccount) -> Result<String> {
|
2025-11-29 16:29:28 -03:00
|
|
|
use crate::shared::models::schema::users;
|
2025-12-02 21:09:43 -03:00
|
|
|
use argon2::{
|
|
|
|
|
password_hash::{rand_core::OsRng, SaltString},
|
|
|
|
|
Argon2, PasswordHasher,
|
|
|
|
|
};
|
2025-11-29 16:29:28 -03:00
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let user_id = Uuid::new_v4();
|
|
|
|
|
let salt = SaltString::generate(&mut OsRng);
|
2025-11-30 23:48:08 -03:00
|
|
|
let argon2 = Argon2::default();
|
|
|
|
|
let password_hash = argon2
|
|
|
|
|
.hash_password(Uuid::new_v4().to_string().as_bytes(), &salt)
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Password hashing failed: {}", e))?
|
|
|
|
|
.to_string();
|
2025-11-29 16:29:28 -03:00
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let mut conn = self
|
|
|
|
|
.db_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Failed to get database connection: {}", e))?;
|
2025-11-29 16:29:28 -03:00
|
|
|
diesel::insert_into(users::table)
|
|
|
|
|
.values((
|
2025-12-02 21:09:43 -03:00
|
|
|
users::id.eq(user_id),
|
2025-11-29 16:29:28 -03:00
|
|
|
users::username.eq(&account.username),
|
|
|
|
|
users::email.eq(&account.email),
|
|
|
|
|
users::password_hash.eq(&password_hash),
|
|
|
|
|
users::is_admin.eq(account.is_admin),
|
|
|
|
|
users::created_at.eq(chrono::Utc::now()),
|
|
|
|
|
))
|
2025-12-02 21:09:43 -03:00
|
|
|
.execute(&mut conn)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
Ok(user_id.to_string())
|
2025-11-29 16:29:28 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn create_s3_home(&self, account: &UserAccount, bot_access: &BotAccess) -> Result<()> {
|
2025-12-26 08:59:25 -03:00
|
|
|
let Some(s3_client) = &self.s3_client else {
|
|
|
|
|
log::warn!("S3 client not configured, skipping S3 home creation");
|
|
|
|
|
return Ok(());
|
2025-12-02 21:09:43 -03:00
|
|
|
};
|
|
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
let bucket_name = format!("{}.gbdrive", bot_access.bot_name);
|
|
|
|
|
let home_path = format!("home/{}/", account.username);
|
|
|
|
|
|
2025-12-26 08:59:25 -03:00
|
|
|
if s3_client
|
|
|
|
|
.head_bucket()
|
|
|
|
|
.bucket(&bucket_name)
|
|
|
|
|
.send()
|
|
|
|
|
.await
|
|
|
|
|
.is_err()
|
|
|
|
|
{
|
|
|
|
|
s3_client
|
|
|
|
|
.create_bucket()
|
|
|
|
|
.bucket(&bucket_name)
|
|
|
|
|
.send()
|
|
|
|
|
.await?;
|
2025-11-29 16:29:28 -03:00
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
s3_client
|
2025-11-29 16:29:28 -03:00
|
|
|
.put_object()
|
|
|
|
|
.bucket(&bucket_name)
|
|
|
|
|
.key(&home_path)
|
|
|
|
|
.body(aws_sdk_s3::primitives::ByteStream::from(vec![]))
|
|
|
|
|
.send()
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
for folder in &["documents", "projects", "shared"] {
|
|
|
|
|
let folder_key = format!("{}{}/", home_path, folder);
|
2025-12-02 21:09:43 -03:00
|
|
|
s3_client
|
2025-11-29 16:29:28 -03:00
|
|
|
.put_object()
|
|
|
|
|
.bucket(&bucket_name)
|
|
|
|
|
.key(&folder_key)
|
|
|
|
|
.body(aws_sdk_s3::primitives::ByteStream::from(vec![]))
|
|
|
|
|
.send()
|
|
|
|
|
.await?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log::info!(
|
|
|
|
|
"Created S3 home for {} in {}",
|
|
|
|
|
account.username,
|
|
|
|
|
bucket_name
|
|
|
|
|
);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
fn setup_email_account(&self, account: &UserAccount) -> Result<()> {
|
2025-11-29 16:29:28 -03:00
|
|
|
use crate::shared::models::schema::user_email_accounts;
|
|
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let mut conn = self
|
|
|
|
|
.db_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Failed to get database connection: {}", e))?;
|
|
|
|
|
|
|
|
|
|
let user_uuid = Uuid::new_v4();
|
2025-11-29 16:29:28 -03:00
|
|
|
diesel::insert_into(user_email_accounts::table)
|
|
|
|
|
.values((
|
2025-12-02 21:09:43 -03:00
|
|
|
user_email_accounts::user_id.eq(user_uuid),
|
2025-11-29 16:29:28 -03:00
|
|
|
user_email_accounts::email.eq(&account.email),
|
|
|
|
|
user_email_accounts::imap_server.eq("localhost"),
|
|
|
|
|
user_email_accounts::imap_port.eq(993),
|
|
|
|
|
user_email_accounts::smtp_server.eq("localhost"),
|
|
|
|
|
user_email_accounts::smtp_port.eq(465),
|
|
|
|
|
user_email_accounts::username.eq(&account.username),
|
|
|
|
|
user_email_accounts::password_encrypted.eq("oauth"),
|
|
|
|
|
user_email_accounts::is_active.eq(true),
|
|
|
|
|
))
|
2025-12-02 21:09:43 -03:00
|
|
|
.execute(&mut conn)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
log::info!("Setup email configuration for: {}", account.email);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
fn setup_oauth_config(&self, _user_id: &str, account: &UserAccount) -> Result<()> {
|
2025-11-30 23:48:08 -03:00
|
|
|
use crate::shared::models::schema::bot_configuration;
|
2025-11-29 16:29:28 -03:00
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
|
|
|
|
let services = vec![
|
|
|
|
|
("oauth-drive-enabled", "true"),
|
|
|
|
|
("oauth-email-enabled", "true"),
|
|
|
|
|
("oauth-git-enabled", "true"),
|
|
|
|
|
("oauth-provider", "zitadel"),
|
|
|
|
|
];
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let mut conn = self
|
|
|
|
|
.db_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Failed to get database connection: {}", e))?;
|
2025-11-29 16:29:28 -03:00
|
|
|
for (key, value) in services {
|
2025-11-30 23:48:08 -03:00
|
|
|
diesel::insert_into(bot_configuration::table)
|
2025-11-29 16:29:28 -03:00
|
|
|
.values((
|
2025-12-02 21:09:43 -03:00
|
|
|
bot_configuration::bot_id.eq(Uuid::nil()),
|
2025-11-30 23:48:08 -03:00
|
|
|
bot_configuration::config_key.eq(key),
|
|
|
|
|
bot_configuration::config_value.eq(value),
|
|
|
|
|
bot_configuration::is_encrypted.eq(false),
|
|
|
|
|
bot_configuration::config_type.eq("string"),
|
|
|
|
|
bot_configuration::created_at.eq(chrono::Utc::now()),
|
|
|
|
|
bot_configuration::updated_at.eq(chrono::Utc::now()),
|
2025-11-29 16:29:28 -03:00
|
|
|
))
|
2025-11-30 23:48:08 -03:00
|
|
|
.on_conflict((bot_configuration::bot_id, bot_configuration::config_key))
|
2025-11-29 16:29:28 -03:00
|
|
|
.do_update()
|
2025-11-30 23:48:08 -03:00
|
|
|
.set(bot_configuration::config_value.eq(value))
|
2025-12-02 21:09:43 -03:00
|
|
|
.execute(&mut conn)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log::info!("Setup OAuth configuration for user: {}", account.username);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn deprovision_user(&self, username: &str) -> Result<()> {
|
|
|
|
|
log::info!("Deprovisioning user: {}", username);
|
|
|
|
|
|
|
|
|
|
self.remove_s3_data(username).await?;
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
self.remove_email_config(username)?;
|
|
|
|
|
self.remove_user_from_db(username)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
log::info!("User {} deprovisioned successfully", username);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
fn remove_user_from_db(&self, username: &str) -> Result<()> {
|
2025-11-29 16:29:28 -03:00
|
|
|
use crate::shared::models::schema::users;
|
|
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let mut conn = self
|
|
|
|
|
.db_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Failed to get database connection: {}", e))?;
|
|
|
|
|
diesel::delete(users::table.filter(users::username.eq(username))).execute(&mut conn)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn remove_s3_data(&self, username: &str) -> Result<()> {
|
2025-12-02 21:09:43 -03:00
|
|
|
if let Some(s3_client) = &self.s3_client {
|
|
|
|
|
let buckets_result = s3_client.list_buckets().send().await?;
|
|
|
|
|
|
|
|
|
|
if let Some(buckets) = buckets_result.buckets {
|
|
|
|
|
for bucket in buckets {
|
|
|
|
|
if let Some(name) = bucket.name {
|
|
|
|
|
if name.ends_with(".gbdrive") {
|
|
|
|
|
let prefix = format!("home/{}/", username);
|
|
|
|
|
|
|
|
|
|
let objects = s3_client
|
|
|
|
|
.list_objects_v2()
|
|
|
|
|
.bucket(&name)
|
|
|
|
|
.prefix(&prefix)
|
|
|
|
|
.send()
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
if let Some(contents) = objects.contents {
|
|
|
|
|
for object in contents {
|
|
|
|
|
if let Some(key) = object.key {
|
|
|
|
|
s3_client
|
|
|
|
|
.delete_object()
|
|
|
|
|
.bucket(&name)
|
|
|
|
|
.key(&key)
|
|
|
|
|
.send()
|
|
|
|
|
.await?;
|
|
|
|
|
}
|
2025-11-29 16:29:28 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
|
|
|
fn remove_email_config(&self, username: &str) -> Result<()> {
|
2025-11-29 16:29:28 -03:00
|
|
|
use crate::shared::models::schema::user_email_accounts;
|
|
|
|
|
use diesel::prelude::*;
|
|
|
|
|
|
2025-12-02 21:09:43 -03:00
|
|
|
let mut conn = self
|
|
|
|
|
.db_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| anyhow::anyhow!("Failed to get database connection: {}", e))?;
|
2025-11-29 16:29:28 -03:00
|
|
|
diesel::delete(
|
|
|
|
|
user_email_accounts::table.filter(user_email_accounts::username.eq(username)),
|
|
|
|
|
)
|
2025-12-02 21:09:43 -03:00
|
|
|
.execute(&mut conn)?;
|
2025-11-29 16:29:28 -03:00
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|