diff --git a/capsulflask/__init__.py b/capsulflask/__init__.py index 55643bb..c5de152 100644 --- a/capsulflask/__init__.py +++ b/capsulflask/__init__.py @@ -142,8 +142,12 @@ app.config['HTTP_CLIENT'] = MyHTTPClient(timeout_seconds=int(app.config['INTERNA app.config['BTCPAY_ENABLED'] = False if app.config['BTCPAY_URL'] != "": try: - app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY']) - app.config['BTCPAY_ENABLED'] = True + response = requests.get(app.config['BTCPAY_URL']) + if response.status_code == 200: + app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY']) + app.config['BTCPAY_ENABLED'] = True + else: + app.logger.warning(f"Can't reach BTCPAY_URL {app.config['BTCPAY_URL']}: Response status code: {response.status_code}. Capsul will work fine except cryptocurrency payments will not work.") except: app.logger.warning("unable to create btcpay client. Capsul will work fine except cryptocurrency payments will not work. The error was: " + my_exec_info_message(sys.exc_info())) diff --git a/capsulflask/cli.py b/capsulflask/cli.py index f13c304..0ab191d 100644 --- a/capsulflask/cli.py +++ b/capsulflask/cli.py @@ -62,6 +62,18 @@ def sql_script(f, c): model.connection.commit() +@bp.cli.command('account-balance') +@click.option('-u', help='users email address') +@with_appcontext +def account_balance(u): + vms = get_model().list_vms_for_account(u) + payments = get_model().list_payments_for_account(u) + click.echo(".") + click.echo(".") + click.echo(get_account_balance(vms, payments, datetime.utcnow())) + click.echo(".") + + @bp.cli.command('cron-task') @with_appcontext diff --git a/capsulflask/db.py b/capsulflask/db.py index 23b3621..0c291a0 100644 --- a/capsulflask/db.py +++ b/capsulflask/db.py @@ -43,7 +43,7 @@ def init_app(app, is_running_server): hasSchemaVersionTable = False actionWasTaken = False schemaVersion = 0 - desiredSchemaVersion = 18 + desiredSchemaVersion = 20 cursor = connection.cursor() diff --git a/capsulflask/hub_model.py b/capsulflask/hub_model.py index 375bb9f..73f60f5 100644 --- a/capsulflask/hub_model.py +++ b/capsulflask/hub_model.py @@ -228,8 +228,8 @@ class CapsulFlaskHub(VirtualizationInterface): # no need to do anything here since if it cant be parsed then generic_operation will handle it. pass + assigned_hosts_string = ", ".join(assigned_hosts) if number_of_assigned != 1: - assigned_hosts_string = ", ".join(assigned_hosts) raise ValueError(f"expected create capsul operation {operation_id} to be assigned to one host, it was assigned to {number_of_assigned} ({assigned_hosts_string})") if error_message != "": raise ValueError(f"create capsul operation {operation_id} on {assigned_hosts_string} failed with {error_message}") diff --git a/capsulflask/payment.py b/capsulflask/payment.py index 3c41cd9..a2e104e 100644 --- a/capsulflask/payment.py +++ b/capsulflask/payment.py @@ -58,14 +58,19 @@ def btcpay_payment(): dollars = result[1] if len(errors) == 0: - invoice = current_app.config['BTCPAY_CLIENT'].create_invoice(dict( - price=float(dollars), - currency="USD", - itemDesc="Capsul Cloud Compute", - transactionSpeed="high", - redirectURL=f"{current_app.config['BASE_URL']}/console/account-balance", - notificationURL=f"{current_app.config['BASE_URL']}/payment/btcpay/webhook" - )) + try: + invoice = current_app.config['BTCPAY_CLIENT'].create_invoice(dict( + price=float(dollars), + currency="USD", + itemDesc="Capsul Cloud Compute", + transactionSpeed="high", + redirectURL=f"{current_app.config['BASE_URL']}/console/account-balance", + notificationURL=f"{current_app.config['BASE_URL']}/payment/btcpay/webhook" + )) + except: + current_app.logger.error(f"An error occurred while attempting to reach BTCPay Server: {my_exec_info_message(sys.exc_info())}") + flash("An error occurred while attempting to reach BTCPay Server.") + return redirect(url_for("console.account_balance")) current_app.logger.info(f"created btcpay invoice: {invoice}") diff --git a/capsulflask/schema_migrations/19_down_os_updates.sql b/capsulflask/schema_migrations/19_down_os_updates.sql new file mode 100644 index 0000000..a9e2083 --- /dev/null +++ b/capsulflask/schema_migrations/19_down_os_updates.sql @@ -0,0 +1,8 @@ +DELETE FROM os_images WHERE id = 'guixsystem130'; +DELETE FROM os_images WHERE id = 'archlinux'; +UPDATE os_images SET deprecated = FALSE WHERE id = 'guixsystem120'; +UPDATE os_images SET deprecated = FALSE WHERE id = 'centos7'; +UPDATE os_images SET deprecated = FALSE WHERE id = 'centos8'; +UPDATE os_images SET description = 'Ubuntu 20.04 LTS (Fossa)' WHERE id = 'ubuntu20'; + +UPDATE schemaversion SET version = 18; diff --git a/capsulflask/schema_migrations/19_up_os_updates.sql b/capsulflask/schema_migrations/19_up_os_updates.sql new file mode 100644 index 0000000..59b1db4 --- /dev/null +++ b/capsulflask/schema_migrations/19_up_os_updates.sql @@ -0,0 +1,12 @@ +INSERT INTO os_images (id, template_image_file_name, description, deprecated) +VALUES ('guixsystem130', 'guixsystem/1.3.0/root.img.qcow2', 'Guix System 1.3.0', FALSE); +INSERT INTO os_images (id, template_image_file_name, description, deprecated) +VALUES ('archlinux', 'archlinux/root.img.qcow2', 'Arch Linux', FALSE); + +UPDATE os_images SET deprecated = TRUE WHERE id = 'guixsystem120'; +UPDATE os_images SET deprecated = TRUE WHERE id = 'centos7'; +UPDATE os_images SET deprecated = TRUE WHERE id = 'centos8'; +UPDATE os_images SET description = 'Ubuntu 20.04 (Focal)' WHERE id = 'ubuntu20'; + + +UPDATE schemaversion SET version = 19; diff --git a/capsulflask/schema_migrations/20_down_deferrable_constraints.sql b/capsulflask/schema_migrations/20_down_deferrable_constraints.sql new file mode 100644 index 0000000..ecd2355 --- /dev/null +++ b/capsulflask/schema_migrations/20_down_deferrable_constraints.sql @@ -0,0 +1,21 @@ + +ALTER TABLE host_network ALTER CONSTRAINT host_network_host_fkey NOT DEFERRABLE; +ALTER TABLE host_operation ALTER CONSTRAINT host_operation_host_fkey NOT DEFERRABLE; +ALTER TABLE host_operation ALTER CONSTRAINT host_operation_operation_fkey NOT DEFERRABLE; +ALTER TABLE login_tokens ALTER CONSTRAINT login_tokens_email_fkey NOT DEFERRABLE; +ALTER TABLE operations ALTER CONSTRAINT operations_email_fkey NOT DEFERRABLE; +ALTER TABLE payment_sessions ALTER CONSTRAINT payment_sessions_email_fkey NOT DEFERRABLE; +ALTER TABLE payments ALTER CONSTRAINT payments_email_fkey NOT DEFERRABLE; +ALTER TABLE ssh_public_keys ALTER CONSTRAINT ssh_public_keys_email_fkey NOT DEFERRABLE; +ALTER TABLE unresolved_btcpay_invoices ALTER CONSTRAINT unresolved_btcpay_invoices_email_fkey NOT DEFERRABLE; +ALTER TABLE unresolved_btcpay_invoices ALTER CONSTRAINT unresolved_btcpay_invoices_email_payment_id_fkey NOT DEFERRABLE; +ALTER TABLE vm_ssh_authorized_key ALTER CONSTRAINT vm_ssh_public_key_email_ssh_public_key_name_fkey NOT DEFERRABLE; +ALTER TABLE vm_ssh_authorized_key ALTER CONSTRAINT vm_ssh_public_key_email_vm_id_fkey NOT DEFERRABLE; +ALTER TABLE vm_ssh_host_key ALTER CONSTRAINT vm_ssh_host_key_email_vm_id_fkey NOT DEFERRABLE; +ALTER TABLE vms ALTER CONSTRAINT vms_email_fkey NOT DEFERRABLE; +ALTER TABLE vms ALTER CONSTRAINT vms_host_network_name_fkey NOT DEFERRABLE; +ALTER TABLE vms ALTER CONSTRAINT vms_host_fkey NOT DEFERRABLE; +ALTER TABLE vms ALTER CONSTRAINT vms_os_fkey NOT DEFERRABLE; +ALTER TABLE vms ALTER CONSTRAINT vms_size_fkey NOT DEFERRABLE; + +UPDATE schemaversion SET version = 19; \ No newline at end of file diff --git a/capsulflask/schema_migrations/20_up_deferrable_constraints.sql b/capsulflask/schema_migrations/20_up_deferrable_constraints.sql new file mode 100644 index 0000000..b4b560a --- /dev/null +++ b/capsulflask/schema_migrations/20_up_deferrable_constraints.sql @@ -0,0 +1,21 @@ + +ALTER TABLE host_network ALTER CONSTRAINT host_network_host_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE host_operation ALTER CONSTRAINT host_operation_host_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE host_operation ALTER CONSTRAINT host_operation_operation_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE login_tokens ALTER CONSTRAINT login_tokens_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE operations ALTER CONSTRAINT operations_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE payment_sessions ALTER CONSTRAINT payment_sessions_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE payments ALTER CONSTRAINT payments_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ssh_public_keys ALTER CONSTRAINT ssh_public_keys_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE unresolved_btcpay_invoices ALTER CONSTRAINT unresolved_btcpay_invoices_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE unresolved_btcpay_invoices ALTER CONSTRAINT unresolved_btcpay_invoices_email_payment_id_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vm_ssh_authorized_key ALTER CONSTRAINT vm_ssh_public_key_email_ssh_public_key_name_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vm_ssh_authorized_key ALTER CONSTRAINT vm_ssh_public_key_email_vm_id_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vm_ssh_host_key ALTER CONSTRAINT vm_ssh_host_key_email_vm_id_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vms ALTER CONSTRAINT vms_email_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vms ALTER CONSTRAINT vms_host_network_name_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vms ALTER CONSTRAINT vms_host_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vms ALTER CONSTRAINT vms_os_fkey DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE vms ALTER CONSTRAINT vms_size_fkey DEFERRABLE INITIALLY DEFERRED; + +UPDATE schemaversion SET version = 20; \ No newline at end of file diff --git a/capsulflask/spoke_api.py b/capsulflask/spoke_api.py index 3ca86bc..f7513aa 100644 --- a/capsulflask/spoke_api.py +++ b/capsulflask/spoke_api.py @@ -182,7 +182,10 @@ def handle_destroy(operation_id, request_body): return abort(400, f"bad request; email is required for destroy") try: - current_app.config['SPOKE_MODEL'].destroy(id=request_body['id'], email=request_body['email']) + vm = current_app.config['SPOKE_MODEL'].get(request_body['id'], False) + current_app.logger.warning(f"destroy {request_body['id']} was called for {request_body['email']}, however the vm does not exist. returning success. ") + if vm is not None: + current_app.config['SPOKE_MODEL'].destroy(id=request_body['id'], email=request_body['email']) except: error_message = my_exec_info_message(sys.exc_info()) params = f"email='{request_body['email'] if 'email' in request_body else 'KeyError'}', " diff --git a/capsulflask/templates/support.html b/capsulflask/templates/support.html index 07888f1..3d4fe7c 100644 --- a/capsulflask/templates/support.html +++ b/capsulflask/templates/support.html @@ -7,18 +7,11 @@

SUPPORT

- support@cyberia.club + support@cyberia.club
{% endblock %} {% block subcontent %} -

- Note: We maintain a searchable archive of all support emails at - https://lists.cyberia.club/~cyberia/support -

-

- If you do not want your mail to appear in a public archive, email capsul@cyberia.club instead. -

Please describe your problem or feature request, and we will do our best to get back to you promptly. Thank you very much.

diff --git a/docs/database.md b/docs/database.md index f192783..a3ef307 100644 --- a/docs/database.md +++ b/docs/database.md @@ -48,3 +48,20 @@ $ pipenv run flask cli sql -c "SELECT id, created, email, dollars, invalidated f ## how to view the logs on the database server (legion.cyberia.club) `sudo -u postgres pg_dump capsul-flask | gzip -9 > capsul-backup-2021-02-15.gz` + + +## changing the email address on an account + +``` +UPDATE accounts SET lower_case_email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE accounts SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE login_tokens SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE operations SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE payment_sessions SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE payments SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE ssh_public_keys SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE unresolved_btcpay_invoices SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE vm_ssh_authorized_key SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE vm_ssh_host_key SET email = 'new@email.address' WHERE email = 'old@email.address' ; +UPDATE vms SET email = 'new@email.address' WHERE email = 'old@email.address' ; +```