diff --git a/lnvps_db/migrations/20250305104739_referrals.sql b/lnvps_db/migrations/20250305104739_referrals.sql new file mode 100644 index 0000000..a2da2f8 --- /dev/null +++ b/lnvps_db/migrations/20250305104739_referrals.sql @@ -0,0 +1,5 @@ +-- Add migration script here +alter table users + drop column contact_nip4; +alter table vm + add column ref_code varchar(20); \ No newline at end of file diff --git a/lnvps_db/src/model.rs b/lnvps_db/src/model.rs index a05d020..dff679a 100644 --- a/lnvps_db/src/model.rs +++ b/lnvps_db/src/model.rs @@ -14,9 +14,11 @@ pub struct User { pub pubkey: Vec, /// When this user first started using the service (first login) pub created: DateTime, + /// Users email address for notifications pub email: Option, - pub contact_nip4: bool, + /// If user should be contacted via NIP-17 for notifications pub contact_nip17: bool, + /// If user should be contacted via email for notifications pub contact_email: bool, } @@ -222,6 +224,8 @@ pub struct Vm { pub mac_address: String, /// Is the VM deleted pub deleted: bool, + /// Referral code (recorded during ordering) + pub ref_code: Option, } #[derive(FromRow, Clone, Debug, Default)] diff --git a/lnvps_db/src/mysql.rs b/lnvps_db/src/mysql.rs index 2670f7e..0502a37 100644 --- a/lnvps_db/src/mysql.rs +++ b/lnvps_db/src/mysql.rs @@ -69,7 +69,7 @@ impl LNVpsDb for LNVpsDbMysql { } async fn delete_user(&self, _id: u64) -> Result<()> { - todo!() + bail!("Deleting users is not supported") } async fn insert_user_ssh_key(&self, new_key: &UserSshKey) -> Result { @@ -247,7 +247,7 @@ impl LNVpsDb for LNVpsDbMysql { } async fn insert_vm(&self, vm: &Vm) -> Result { - Ok(sqlx::query("insert into vm(host_id,user_id,image_id,template_id,ssh_key_id,created,expires,disk_id,mac_address) values(?, ?, ?, ?, ?, ?, ?, ?, ?) returning id") + Ok(sqlx::query("insert into vm(host_id,user_id,image_id,template_id,ssh_key_id,created,expires,disk_id,mac_address,ref_code) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) returning id") .bind(vm.host_id) .bind(vm.user_id) .bind(vm.image_id) @@ -257,6 +257,7 @@ impl LNVpsDb for LNVpsDbMysql { .bind(vm.expires) .bind(vm.disk_id) .bind(&vm.mac_address) + .bind(&vm.ref_code) .fetch_one(&self.db) .await .map_err(Error::new)? diff --git a/src/api/model.rs b/src/api/model.rs index e2db237..e70a46f 100644 --- a/src/api/model.rs +++ b/src/api/model.rs @@ -207,6 +207,7 @@ pub struct CreateVmRequest { pub template_id: u64, pub image_id: u64, pub ssh_key_id: u64, + pub ref_code: Option } #[derive(Serialize, Deserialize, JsonSchema)] diff --git a/src/api/routes.rs b/src/api/routes.rs index 8940788..8f8cbfd 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -361,14 +361,20 @@ async fn v1_create_vm_order( auth: Nip98Auth, db: &State>, provisioner: &State>, - req: Json, + req: Json ) -> ApiResult { let pubkey = auth.event.pubkey.to_bytes(); let uid = db.upsert_user(&pubkey).await?; let req = req.0; let rsp = provisioner - .provision(uid, req.template_id, req.image_id, req.ssh_key_id) + .provision( + uid, + req.template_id, + req.image_id, + req.ssh_key_id, + req.ref_code, + ) .await?; ApiData::ok(vm_to_status(db, rsp, None).await?) } diff --git a/src/mocks.rs b/src/mocks.rs index fe04193..b9fc839 100644 --- a/src/mocks.rs +++ b/src/mocks.rs @@ -173,7 +173,6 @@ impl LNVpsDb for MockDb { pubkey: pubkey.to_vec(), created: Utc::now(), email: None, - contact_nip4: false, contact_nip17: false, contact_email: false, }, @@ -193,7 +192,6 @@ impl LNVpsDb for MockDb { u.email = user.email.clone(); u.contact_email = user.contact_email; u.contact_nip17 = user.contact_nip17; - u.contact_nip4 = user.contact_nip4; } Ok(()) } @@ -377,6 +375,7 @@ impl LNVpsDb for MockDb { disk_id: vm.disk_id, mac_address: vm.mac_address.clone(), deleted: false, + ref_code: vm.ref_code.clone(), }, ); Ok(max_id + 1) diff --git a/src/provisioner/lnvps.rs b/src/provisioner/lnvps.rs index 2c7e9ce..6e2025b 100644 --- a/src/provisioner/lnvps.rs +++ b/src/provisioner/lnvps.rs @@ -249,6 +249,7 @@ impl LNVpsProvisioner { template_id: u64, image_id: u64, ssh_key_id: u64, + ref_code: Option, ) -> Result { let user = self.db.get_user(user_id).await?; let template = self.db.get_vm_template(template_id).await?; @@ -272,6 +273,7 @@ impl LNVpsProvisioner { let client = get_host_client(&pick_host, &self.provisioner_config)?; let mut new_vm = Vm { + id: 0, host_id: pick_host.id, user_id: user.id, image_id: image.id, @@ -280,7 +282,9 @@ impl LNVpsProvisioner { created: Utc::now(), expires: Utc::now(), disk_id: pick_disk.id, - ..Default::default() + mac_address: "NOT FILLED YET".to_string(), + deleted: false, + ref_code, }; // ask host client to generate the mac address @@ -468,7 +472,9 @@ mod tests { }; let ssh_key = db.insert_user_ssh_key(&new_key).await?; - let vm = provisioner.provision(user_id, 1, 1, ssh_key).await?; + let vm = provisioner + .provision(user_id, 1, 1, ssh_key, Some("mock-ref".to_string())) + .await?; println!("{:?}", vm); provisioner.spawn_vm(vm.id).await?; @@ -477,6 +483,7 @@ mod tests { assert_eq!(1, arp.len()); let arp = arp.first().unwrap(); assert_eq!(&vm.mac_address, &arp.mac_address); + assert_eq!(vm.ref_code, Some("mock-ref".to_string())); assert_eq!(ROUTER_BRIDGE, arp.interface.as_ref().unwrap()); println!("{:?}", arp); diff --git a/src/worker.rs b/src/worker.rs index 8a2f864..790d9eb 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -241,9 +241,6 @@ impl Worker { sender.send(msg).await?; } } - if user.contact_nip4 { - // TODO: send nip4 dm - } if user.contact_nip17 { if let Some(c) = self.nostr.as_ref() { let sig = c.signer().await?;