5
lnvps_db/migrations/20250305104739_referrals.sql
Normal file
5
lnvps_db/migrations/20250305104739_referrals.sql
Normal 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);
|
@ -14,9 +14,11 @@ pub struct User {
|
|||||||
pub pubkey: Vec<u8>,
|
pub pubkey: Vec<u8>,
|
||||||
/// When this user first started using the service (first login)
|
/// When this user first started using the service (first login)
|
||||||
pub created: DateTime<Utc>,
|
pub created: DateTime<Utc>,
|
||||||
|
/// Users email address for notifications
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub contact_nip4: bool,
|
/// If user should be contacted via NIP-17 for notifications
|
||||||
pub contact_nip17: bool,
|
pub contact_nip17: bool,
|
||||||
|
/// If user should be contacted via email for notifications
|
||||||
pub contact_email: bool,
|
pub contact_email: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +224,8 @@ pub struct Vm {
|
|||||||
pub mac_address: String,
|
pub mac_address: String,
|
||||||
/// Is the VM deleted
|
/// Is the VM deleted
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
|
/// Referral code (recorded during ordering)
|
||||||
|
pub ref_code: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromRow, Clone, Debug, Default)]
|
#[derive(FromRow, Clone, Debug, Default)]
|
||||||
|
@ -69,7 +69,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_user(&self, _id: u64) -> Result<()> {
|
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> {
|
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> {
|
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.host_id)
|
||||||
.bind(vm.user_id)
|
.bind(vm.user_id)
|
||||||
.bind(vm.image_id)
|
.bind(vm.image_id)
|
||||||
@ -257,6 +257,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
|||||||
.bind(vm.expires)
|
.bind(vm.expires)
|
||||||
.bind(vm.disk_id)
|
.bind(vm.disk_id)
|
||||||
.bind(&vm.mac_address)
|
.bind(&vm.mac_address)
|
||||||
|
.bind(&vm.ref_code)
|
||||||
.fetch_one(&self.db)
|
.fetch_one(&self.db)
|
||||||
.await
|
.await
|
||||||
.map_err(Error::new)?
|
.map_err(Error::new)?
|
||||||
|
@ -207,6 +207,7 @@ pub struct CreateVmRequest {
|
|||||||
pub template_id: u64,
|
pub template_id: u64,
|
||||||
pub image_id: u64,
|
pub image_id: u64,
|
||||||
pub ssh_key_id: u64,
|
pub ssh_key_id: u64,
|
||||||
|
pub ref_code: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||||
|
@ -361,14 +361,20 @@ async fn v1_create_vm_order(
|
|||||||
auth: Nip98Auth,
|
auth: Nip98Auth,
|
||||||
db: &State<Arc<dyn LNVpsDb>>,
|
db: &State<Arc<dyn LNVpsDb>>,
|
||||||
provisioner: &State<Arc<LNVpsProvisioner>>,
|
provisioner: &State<Arc<LNVpsProvisioner>>,
|
||||||
req: Json<CreateVmRequest>,
|
req: Json<CreateVmRequest>
|
||||||
) -> ApiResult<ApiVmStatus> {
|
) -> ApiResult<ApiVmStatus> {
|
||||||
let pubkey = auth.event.pubkey.to_bytes();
|
let pubkey = auth.event.pubkey.to_bytes();
|
||||||
let uid = db.upsert_user(&pubkey).await?;
|
let uid = db.upsert_user(&pubkey).await?;
|
||||||
|
|
||||||
let req = req.0;
|
let req = req.0;
|
||||||
let rsp = provisioner
|
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?;
|
.await?;
|
||||||
ApiData::ok(vm_to_status(db, rsp, None).await?)
|
ApiData::ok(vm_to_status(db, rsp, None).await?)
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,6 @@ impl LNVpsDb for MockDb {
|
|||||||
pubkey: pubkey.to_vec(),
|
pubkey: pubkey.to_vec(),
|
||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
email: None,
|
email: None,
|
||||||
contact_nip4: false,
|
|
||||||
contact_nip17: false,
|
contact_nip17: false,
|
||||||
contact_email: false,
|
contact_email: false,
|
||||||
},
|
},
|
||||||
@ -193,7 +192,6 @@ impl LNVpsDb for MockDb {
|
|||||||
u.email = user.email.clone();
|
u.email = user.email.clone();
|
||||||
u.contact_email = user.contact_email;
|
u.contact_email = user.contact_email;
|
||||||
u.contact_nip17 = user.contact_nip17;
|
u.contact_nip17 = user.contact_nip17;
|
||||||
u.contact_nip4 = user.contact_nip4;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -377,6 +375,7 @@ impl LNVpsDb for MockDb {
|
|||||||
disk_id: vm.disk_id,
|
disk_id: vm.disk_id,
|
||||||
mac_address: vm.mac_address.clone(),
|
mac_address: vm.mac_address.clone(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
ref_code: vm.ref_code.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Ok(max_id + 1)
|
Ok(max_id + 1)
|
||||||
|
@ -249,6 +249,7 @@ impl LNVpsProvisioner {
|
|||||||
template_id: u64,
|
template_id: u64,
|
||||||
image_id: u64,
|
image_id: u64,
|
||||||
ssh_key_id: u64,
|
ssh_key_id: u64,
|
||||||
|
ref_code: Option<String>,
|
||||||
) -> Result<Vm> {
|
) -> Result<Vm> {
|
||||||
let user = self.db.get_user(user_id).await?;
|
let user = self.db.get_user(user_id).await?;
|
||||||
let template = self.db.get_vm_template(template_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 client = get_host_client(&pick_host, &self.provisioner_config)?;
|
||||||
let mut new_vm = Vm {
|
let mut new_vm = Vm {
|
||||||
|
id: 0,
|
||||||
host_id: pick_host.id,
|
host_id: pick_host.id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
image_id: image.id,
|
image_id: image.id,
|
||||||
@ -280,7 +282,9 @@ impl LNVpsProvisioner {
|
|||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
expires: Utc::now(),
|
expires: Utc::now(),
|
||||||
disk_id: pick_disk.id,
|
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
|
// 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 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);
|
println!("{:?}", vm);
|
||||||
provisioner.spawn_vm(vm.id).await?;
|
provisioner.spawn_vm(vm.id).await?;
|
||||||
|
|
||||||
@ -477,6 +483,7 @@ mod tests {
|
|||||||
assert_eq!(1, arp.len());
|
assert_eq!(1, arp.len());
|
||||||
let arp = arp.first().unwrap();
|
let arp = arp.first().unwrap();
|
||||||
assert_eq!(&vm.mac_address, &arp.mac_address);
|
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());
|
assert_eq!(ROUTER_BRIDGE, arp.interface.as_ref().unwrap());
|
||||||
println!("{:?}", arp);
|
println!("{:?}", arp);
|
||||||
|
|
||||||
|
@ -241,9 +241,6 @@ impl Worker {
|
|||||||
sender.send(msg).await?;
|
sender.send(msg).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if user.contact_nip4 {
|
|
||||||
// TODO: send nip4 dm
|
|
||||||
}
|
|
||||||
if user.contact_nip17 {
|
if user.contact_nip17 {
|
||||||
if let Some(c) = self.nostr.as_ref() {
|
if let Some(c) = self.nostr.as_ref() {
|
||||||
let sig = c.signer().await?;
|
let sig = c.signer().await?;
|
||||||
|
Reference in New Issue
Block a user