from nanoid import generate class DBModel: def __init__(self, connection, cursor): self.connection = connection self.cursor = cursor def login(self, email): self.cursor.execute("SELECT * FROM accounts WHERE email = %s", (email, )) if len(self.cursor.fetchall()) == 0: self.cursor.execute("INSERT INTO accounts (email) VALUES (%s)", (email, )) self.cursor.execute("SELECT token FROM login_tokens WHERE email = %s", (email, )) if len(self.cursor.fetchall()) > 2: return None token = generate() self.cursor.execute("INSERT INTO login_tokens (email, token) VALUES (%s, %s)", (email, token)) self.connection.commit() return token def consume_token(self, token): self.cursor.execute("SELECT email FROM login_tokens WHERE token = %s and created > (NOW() - INTERVAL '20 min')", (token, )) rows = self.cursor.fetchall() if len(rows) > 0: email = rows[0][0] self.cursor.execute("DELETE FROM login_tokens WHERE email = %s", (email, )) self.connection.commit() return email return None def all_vm_ids(self,): self.cursor.execute("SELECT id FROM vms") return list(map(lambda x: x[0], self.cursor.fetchall())) def operating_systems_dict(self,): self.cursor.execute("SELECT id, template_image_file_name, description FROM os_images") operatingSystems = dict() for row in self.cursor.fetchall(): operatingSystems[row[0]] = dict(template_image_file_name=row[1], description=row[2]) return operatingSystems def vm_sizes_dict(self,): self.cursor.execute("SELECT id, dollars_per_month, vcpus, memory_mb, bandwidth_gb_per_month FROM vm_sizes") vmSizes = dict() for row in self.cursor.fetchall(): vmSizes[row[0]] = dict(dollars_per_month=row[1], vcpus=row[2], memory_mb=row[3], bandwidth_gb_per_month=row[4]) return vmSizes def list_ssh_public_keys_for_account(self, email): self.cursor.execute("SELECT name, content, created FROM ssh_public_keys WHERE email = %s", (email, )) return list(map( lambda x: dict(name=x[0], content=x[1], created=x[2]), self.cursor.fetchall() )) def ssh_public_key_name_exists(self, email, name): self.cursor.execute( "SELECT name FROM ssh_public_keys where email = %s AND name = %s", (email, name) ) return len(self.cursor.fetchall()) > 0 def create_ssh_public_key(self, email, name, content): self.cursor.execute(""" INSERT INTO ssh_public_keys (email, name, content) VALUES (%s, %s, %s) """, (email, name, content) ) self.connection.commit() def delete_ssh_public_key(self, email, name): self.cursor.execute( "DELETE FROM ssh_public_keys where email = %s AND name = %s", (email, name) ) self.connection.commit() def list_vms_for_account(self, email): self.cursor.execute(""" SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, vms.size, vms.os, vms.created, vms.deleted, vm_sizes.dollars_per_month FROM vms JOIN vm_sizes on vms.size = vm_sizes.id WHERE vms.email = %s""", (email, ) ) return list(map( lambda x: dict(id=x[0], ipv4=x[1], ipv6=x[2], size=x[3], os=x[4], created=x[5], deleted=x[6], dollars_per_month=x[7]), self.cursor.fetchall() )) def updateVm(self, email, id, ipv4): self.cursor.execute("UPDATE vms SET last_seen_ipv4 = %s WHERE email = %s AND id = %s", (ipv4, email, id)) self.connection.commit() def create_vm(self, email, id, size, os, ssh_public_keys): self.cursor.execute(""" INSERT INTO vms (email, id, size, os) VALUES (%s, %s, %s, %s) """, (email, id, size, os) ) for ssh_public_key in ssh_public_keys: self.cursor.execute(""" INSERT INTO vm_ssh_public_key (email, vm_id, ssh_public_key_name) VALUES (%s, %s, %s) """, (email, id, ssh_public_key) ) self.connection.commit() # def vm_exists(self, email, id): # self.cursor.execute("SELECT id FROM vms WHERE email = %s AND id = %s ", (email, id)) # return len(self.cursor.fetchall()) > 0 def get_vm_detail(self, email, id): self.cursor.execute(""" SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, os_images.description, vms.created, vms.deleted, vm_sizes.id, vm_sizes.dollars_per_month, vm_sizes.vcpus, vm_sizes.memory_mb, vm_sizes.bandwidth_gb_per_month FROM vms JOIN os_images on vms.os = os_images.id JOIN vm_sizes on vms.size = vm_sizes.id WHERE vms.email = %s AND vms.id = %s""", (email, id) ) rows = self.cursor.fetchall() if len(rows) == 0: return None x = rows[0] vm = dict( id=x[0], ipv4=x[1], ipv6=x[2], os_description=x[3], created=x[4], deleted=x[5], size=x[6], dollars_per_month=x[7], vcpus=x[8], memory_mb=x[9], bandwidth_gb_per_month=x[10] ) self.cursor.execute(""" SELECT ssh_public_key_name FROM vm_ssh_public_key WHERE vm_ssh_public_key.email = %s AND vm_ssh_public_key.vm_id = %s""", (email, id) ) vm["ssh_public_keys"] = list(map( lambda x: x[0], self.cursor.fetchall() )) return vm def list_payments_for_account(self, email): self.cursor.execute(""" SELECT dollars, invalidated, created FROM payments WHERE payments.email = %s""", (email, ) ) return list(map( lambda x: dict(dollars=x[0], invalidated=x[1], created=x[2]), self.cursor.fetchall() )) def create_payment_session(self, payment_type, id, email, dollars): self.cursor.execute(""" INSERT INTO payment_sessions (id, type, email, dollars) VALUES (%s, %s, %s, %s) """, (id, payment_type, email, dollars) ) self.connection.commit() def consume_payment_session(self, payment_type, id, dollars): self.cursor.execute("SELECT email, dollars FROM payment_sessions WHERE id = %s AND type = %s", (id, payment_type)) rows = self.cursor.fetchall() if len(rows) > 0: if int(rows[0][1]) != int(dollars): print(f""" {payment_type} gave us a completed payment session with a different dollar amount than what we had recorded!! id: {id} account: {rows[0][0]} Recorded amount: {int(rows[0][1])} {payment_type} sent: {int(dollars)} """) # not sure what to do here. For now just log and do nothing. self.cursor.execute( "DELETE FROM payment_sessions WHERE id = %s AND type = %s", (id, payment_type) ) self.cursor.execute( "INSERT INTO payments (email, dollars) VALUES (%s, %s)", (rows[0][0], rows[0][1]) ) self.connection.commit() return rows[0][0] else: return None