feat: ref codes

closes #8
This commit is contained in:
2025-03-05 11:11:57 +00:00
parent b5654a533a
commit 6b909ba5bd
8 changed files with 32 additions and 12 deletions

View File

@ -0,0 +1,5 @@
-- Add migration script here
alter table users
drop column contact_nip4;
alter table vm
add column ref_code varchar(20);

View File

@ -14,9 +14,11 @@ pub struct User {
pub pubkey: Vec<u8>,
/// When this user first started using the service (first login)
pub created: DateTime<Utc>,
/// Users email address for notifications
pub email: Option<String>,
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<String>,
}
#[derive(FromRow, Clone, Debug, Default)]

View File

@ -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<u64> {
@ -247,7 +247,7 @@ impl LNVpsDb for LNVpsDbMysql {
}
async fn insert_vm(&self, vm: &Vm) -> Result<u64> {
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)?

View File

@ -207,6 +207,7 @@ pub struct CreateVmRequest {
pub template_id: u64,
pub image_id: u64,
pub ssh_key_id: u64,
pub ref_code: Option<String>
}
#[derive(Serialize, Deserialize, JsonSchema)]

View File

@ -361,14 +361,20 @@ async fn v1_create_vm_order(
auth: Nip98Auth,
db: &State<Arc<dyn LNVpsDb>>,
provisioner: &State<Arc<LNVpsProvisioner>>,
req: Json<CreateVmRequest>,
req: Json<CreateVmRequest>
) -> ApiResult<ApiVmStatus> {
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?)
}

View File

@ -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)

View File

@ -249,6 +249,7 @@ impl LNVpsProvisioner {
template_id: u64,
image_id: u64,
ssh_key_id: u64,
ref_code: Option<String>,
) -> Result<Vm> {
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);

View File

@ -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?;