diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index 6b8710a7..00000000
--- a/.dockerignore
+++ /dev/null
@@ -1 +0,0 @@
-.git
diff --git a/Changelog b/Changelog
index 44c4dee4..e636bc66 100644
--- a/Changelog
+++ b/Changelog
@@ -1,49 +1,3 @@
-3.2: 2021-02-07
- * 8816: Update order confirmation text to better prepared for payment dispute
- * supportticket#22990: Fix: can't add a deleted card
-3.1: 2021-01-11
- * 8781: Fix error is setting a default card (MR!746)
-3.0: 2021-01-07
- * 8393: Implement SCA for stripe payments (MR!745)
- * 8691: Implment check_vm_templates management command (MR!744)
-2.14: 2020-12-07
- * 8692: Create a script that fixes django db for the order after celery error (MR!743)
-2.13: 2020-12-02
- * 8654: Fix 500 error on invoices list for the user contact+devuanhosting.com@virus.media (MR!742)
- * 8593: Escape user's ssh key in xml-rpc call to create VM (MR!741)
-2.12.1: 2020-07-21
- * 8307: Introduce "Exclude vat calculations" for Generic Products (MR!740)
- * Change DE VAT rate to 16% from 19% (MR!739)
-2.12: 2020-06-23
- * 7894: Show one time payment invoices (MR!738)
-2.11: 2020-06-11
- * Bugfix: Correct the wrong constant name (caused payment to go thru and showing error and VMs not instantiated)
-2.10.8: 2020-06-10
- * #8102: Refactor MAX_TIME_TO_WAIT_FOR_VM_TERMINATE to increase time to poll whether VM has been terminated or not (MR!737)
-2.10.7: 2020-05-25
- * Bugfix: Handle VM templates deleted in OpenNebula but VM instances still existing (MR!736)
- Notes for deployment:
- When deploying define a UPDATED_TEMPLATES string represented dictionary value in .env
-```
- # Represents Template Ids that were
- # deleted and the new template Id to look for the template
- # definition
- UPDATED_TEMPLATES="{1: 100}"
-```
-2.10.6: 2020-03-25
- * Bugfix: Handle Nonetype for discount's name (MR!735)
-2.10.5: 2020-03-17
- * Introduce base price for VMs and let admins add stripe_coupon_id (MR!730)
- Notes for deployment:
- 1. Add env variable `VM_BASE_PRICE`
- 2. Migrate datacenterlight app. This introduces the stripe_coupon_code field in the VMPricing.
- 3. Create a coupon in stripe with the desired value and note down the stripe's coupon id
- 4. Update the discount amount and set the corresponding coupon id in the admin
-2.10.3b: 2020-03-05
- * #7773: Use username for communicating with opennebula all the time
-2.10.2b: 2020-02-25
- * #7764: Fix uid represented as bytestring
- * #7769: [hosting] ssh private key download feature does not work well on Firefox
2.10.1: 2020-02-02:
* Changes the pricing structure of generic products into the pre vat and with vat (like that for VM)
* Shows product name (if exists) in the invoices list if it belongs to a generic product
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 50b81cbb..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,18 +0,0 @@
-FROM python:3.10.0-alpine3.15
-
-WORKDIR /usr/src/app
-
-RUN apk add --update --no-cache \
- git \
- build-base \
- openldap-dev \
- python3-dev \
- libpq-dev \
- && rm -rf /var/cache/apk/*
-
-# FIX https://github.com/python-ldap/python-ldap/issues/432
-RUN echo 'INPUT ( libldap.so )' > /usr/lib/libldap_r.so
-
-COPY requirements.txt ./
-RUN pip install --no-cache-dir -r requirements.txt
-COPY ./ .
diff --git a/Makefile b/Makefile
index 68ff014e..67c0c15b 100644
--- a/Makefile
+++ b/Makefile
@@ -14,12 +14,6 @@ help:
@echo ' make rsync_upload '
@echo ' make install_debian_packages '
-buildimage:
- docker build -t dynamicweb:$$(git describe) .
-
-releaseimage: buildimage
- ./release.sh
-
collectstatic:
$(PY?) $(BASEDIR)/manage.py collectstatic
diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po
index cd7fab99..1a1a2a26 100644
--- a/datacenterlight/locale/de/LC_MESSAGES/django.po
+++ b/datacenterlight/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-02-07 11:10+0000\n"
+"POT-Creation-Date: 2020-02-01 09:42+0000\n"
"PO-Revision-Date: 2018-03-30 23:22+0000\n"
"Last-Translator: b'Anonymous User '\n"
"Language-Team: LANGUAGE \n"
@@ -144,8 +144,8 @@ msgid ""
"the heart of Switzerland."
msgstr "Bei uns findest Du die günstiges VMs aus der Schweiz."
-msgid "Try now, order a VM. VM price starts from only 11.5 CHF per month."
-msgstr "Unser Angebot beginnt bei 11.5 CHF pro Monat. Probier's jetzt aus!"
+msgid "Try now, order a VM. VM price starts from only 10.5 CHF per month."
+msgstr "Unser Angebot beginnt bei 10.5 CHF pro Monat. Probier's jetzt aus!"
msgid "ORDER VM"
msgstr "VM BESTELLEN"
@@ -415,9 +415,8 @@ msgstr "Deine MwSt-Nummer wurde überprüft"
msgid ""
"Your VAT number is under validation. VAT will be adjusted, once the "
"validation is complete."
-msgstr ""
-"Deine MwSt-Nummer wird derzeit validiert. Die MwSt. wird angepasst, sobald "
-"die Validierung abgeschlossen ist."
+msgstr "Deine MwSt-Nummer wird derzeit validiert. Die MwSt. wird angepasst, "
+"sobald die Validierung abgeschlossen ist."
msgid "Payment method"
msgstr "Bezahlmethode"
@@ -431,6 +430,18 @@ msgstr "Bestellungsübersicht"
msgid "Product"
msgstr "Produkt"
+msgid "Price"
+msgstr "Preise"
+
+msgid "VAT for"
+msgstr "MwSt für"
+
+msgid "Total Amount"
+msgstr "Gesamtsumme"
+
+msgid "Amount"
+msgstr "Betrag"
+
msgid "Description"
msgstr "Beschreibung"
@@ -443,51 +454,42 @@ msgstr "Preis ohne MwSt."
msgid "Pre VAT"
msgstr "Exkl. MwSt."
-msgid "VAT for"
-msgstr "MwSt für"
-
msgid "Your Price in Total"
msgstr "Dein Gesamtpreis"
-#, python-format
msgid ""
-" By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(total_price)s CHF/year"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(total_price)s CHF/year"
msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF/Jahr belastet."
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(total_price)s "
+"CHF pro Jahr belastet"
#, python-format
msgid ""
-"\n"
-" By clicking \"Place order\" you agree to "
-"our Terms "
-"of Service and this plan will charge your credit card account with "
-"%(total_price)s CHF/month"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(total_price)s CHF/month"
msgstr ""
-"\n"
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF/Monat belastet."
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(total_price)s "
+"CHF pro Monat belastet"
+
+#, fuzzy, python-format
+#| msgid ""
+#| "By clicking \"Place order\" this payment will charge your credit card "
+#| "account with a one time amount of %(total_price)s CHF"
+msgid ""
+"By clicking \"Place order\" this payment will charge your credit card "
+"account with a one time amount of %(total_price)s CHF"
+msgstr ""
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
+"%(vm_total_price)s CHF pro Monat belastet"
#, python-format
msgid ""
-"By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(total_price)s CHF"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(vm_total_price)s CHF/month"
msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF belastet."
-
-#, python-format
-msgid ""
-"By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(vm_total_price)s CHF/"
-"month"
-msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(vm_total_price)s CHF/Monat belastet"
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
+"%(vm_total_price)s CHF pro Monat belastet"
msgid "Place order"
msgstr "Bestellen"
@@ -606,22 +608,16 @@ msgid "Incorrect pricing name. Please contact support{support_email}"
msgstr ""
"Ungültige Preisbezeichnung. Bitte kontaktiere den Support{support_email}"
+#, python-brace-format
+msgid "{user} does not have permission to access the card"
+msgstr "{user} hat keine Erlaubnis auf diese Karte zuzugreifen"
+
+msgid "An error occurred. Details: {}"
+msgstr "Ein Fehler ist aufgetreten. Details: {}"
+
msgid "Confirm Order"
msgstr "Bestellung Bestätigen"
-#, fuzzy
-#| msgid "Thank you!"
-msgid "Thank you !"
-msgstr "Vielen Dank!"
-
-msgid "Your product will be provisioned as soon as we receive the payment."
-msgstr ""
-
-#, python-brace-format
-msgid "An error occurred while associating the card. Details: {details}"
-msgstr ""
-"Beim Verbinden der Karte ist ein Fehler aufgetreten. Details: {details}"
-
msgid "Error."
msgstr ""
@@ -632,21 +628,10 @@ msgstr ""
"Es ist ein Fehler bei der Zahlung betreten. Du wirst nach dem Schliessen vom "
"Popup zur Bezahlseite weitergeleitet."
-msgid "Thank you for the order."
-msgstr "Danke für Deine Bestellung."
-
-msgid ""
-"Your product will be provisioned as soon as we receive a payment "
-"confirmation from Stripe. We will send you a confirmation email. You can "
-"always contact us at support@datacenterlight.ch"
+#, python-brace-format
+msgid "An error occurred while associating the card. Details: {details}"
msgstr ""
-
-msgid ""
-"Your VM will be up and running in a few moments. We will send you a "
-"confirmation email as soon as it is ready."
-msgstr ""
-"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
-"auf sie zugreifen kannst."
+"Beim Verbinden der Karte ist ein Fehler aufgetreten. Details: {details}"
msgid " This is a monthly recurring plan."
msgstr "Dies ist ein monatlich wiederkehrender Plan."
@@ -686,40 +671,15 @@ msgstr ""
"Du wirst bald eine Bestätigungs-E-Mail über die Zahlung erhalten. Du kannst "
"jederzeit unter info@ungleich.ch kontaktieren."
-#, python-format
-#~ msgid ""
-#~ "By clicking \"Place order\" this plan will charge your credit card "
-#~ "account with %(total_price)s CHF/month"
-#~ msgstr ""
-#~ "Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
-#~ "%(total_price)s CHF pro Monat belastet"
+msgid "Thank you for the order."
+msgstr "Danke für Deine Bestellung."
-#, fuzzy, python-format
-#~| msgid ""
-#~| "By clicking \"Place order\" this payment will charge your credit card "
-#~| "account with a one time amount of %(total_price)s CHF"
-#~ msgid ""
-#~ "By clicking \"Place order\" this payment will charge your credit card "
-#~ "account with a one time amount of %(total_price)s CHF"
-#~ msgstr ""
-#~ "Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
-#~ "%(vm_total_price)s CHF pro Monat belastet"
-
-#, python-brace-format
-#~ msgid "{user} does not have permission to access the card"
-#~ msgstr "{user} hat keine Erlaubnis auf diese Karte zuzugreifen"
-
-#~ msgid "An error occurred. Details: {}"
-#~ msgstr "Ein Fehler ist aufgetreten. Details: {}"
-
-#~ msgid "Price"
-#~ msgstr "Preise"
-
-#~ msgid "Total Amount"
-#~ msgstr "Gesamtsumme"
-
-#~ msgid "Amount"
-#~ msgstr "Betrag"
+msgid ""
+"Your VM will be up and running in a few moments. We will send you a "
+"confirmation email as soon as it is ready."
+msgstr ""
+"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
+"auf sie zugreifen kannst."
#~ msgid "Subtotal"
#~ msgstr "Zwischensumme"
@@ -786,6 +746,9 @@ msgstr ""
#~ "Wir werden dann sobald als möglich Ihren Beta-Zugang erstellen und Sie "
#~ "daraufhin kontaktieren.Bis dahin bitten wir Sie um etwas Geduld."
+#~ msgid "Thank you!"
+#~ msgstr "Vielen Dank!"
+
#~ msgid "Thank you for order! Our team will contact you via email"
#~ msgstr ""
#~ "Vielen Dank für die Bestellung. Unser Team setzt sich sobald wie möglich "
diff --git a/datacenterlight/management/commands/check_vm_templates.py b/datacenterlight/management/commands/check_vm_templates.py
deleted file mode 100644
index db36fde8..00000000
--- a/datacenterlight/management/commands/check_vm_templates.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from django.core.management.base import BaseCommand
-from opennebula_api.models import OpenNebulaManager
-from datacenterlight.models import VMTemplate
-from membership.models import CustomUser
-
-from django.conf import settings
-from time import sleep
-import datetime
-import json
-import logging
-import os
-
-logger = logging.getLogger(__name__)
-
-
-class Command(BaseCommand):
- help = '''Checks all VM templates to find if they can be instantiated'''
-
- def add_arguments(self, parser):
- parser.add_argument('user_email', type=str)
-
- def handle(self, *args, **options):
- result_dict = {}
- user_email = options['user_email'] if 'user_email' in options else ""
-
- if user_email:
- cu = CustomUser.objects.get(email=user_email)
- specs = {'cpu': 1, 'memory': 1, 'disk_size': 10}
- manager = OpenNebulaManager(email=user_email, password=cu.password)
- pub_keys = [settings.TEST_MANAGE_SSH_KEY_PUBKEY]
- PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))
- if not os.path.exists("%s/outputs" % PROJECT_PATH):
- os.mkdir("%s/outputs" % PROJECT_PATH)
- for vm_template in VMTemplate.objects.all():
- vm_name = 'test-%s' % vm_template.name
- vm_id = manager.create_vm(
- template_id=vm_template.opennebula_vm_template_id,
- specs=specs,
- ssh_key='\n'.join(pub_keys),
- vm_name=vm_name
- )
- if vm_id and vm_id > 0:
- result_dict[vm_name] = "%s OK, created VM %s" % (
- '%s %s %s' % (vm_template.opennebula_vm_template_id,
- vm_template.name, vm_template.vm_type),
- vm_id
- )
- self.stdout.write(self.style.SUCCESS(result_dict[vm_name]))
- manager.delete_vm(vm_id)
- else:
- result_dict[vm_name] = '''Error creating VM %s, template_id
- %s %s''' % (vm_name,
- vm_template.opennebula_vm_template_id,
- vm_template.vm_type)
- self.stdout.write(self.style.ERROR(result_dict[vm_name]))
- sleep(1)
- date_str = datetime.datetime.strftime(
- datetime.datetime.now(), '%Y%m%d%H%M%S'
- )
- with open("%s/outputs/check_vm_templates_%s.txt" %
- (PROJECT_PATH, date_str),
- 'w',
- encoding='utf-8') as f:
- f.write(json.dumps(result_dict))
- self.stdout.write(self.style.SUCCESS("Done"))
diff --git a/datacenterlight/management/commands/fix_vm_after_celery_error.py b/datacenterlight/management/commands/fix_vm_after_celery_error.py
deleted file mode 100644
index 0cfdb423..00000000
--- a/datacenterlight/management/commands/fix_vm_after_celery_error.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from django.core.management.base import BaseCommand
-from datacenterlight.tasks import handle_metadata_and_emails
-from opennebula_api.models import OpenNebulaManager
-from membership.models import CustomUser
-import logging
-import json
-
-logger = logging.getLogger(__name__)
-
-
-class Command(BaseCommand):
- help = '''Updates the DB after manual creation of VM'''
-
- def add_arguments(self, parser):
- parser.add_argument('vm_id', type=int)
- parser.add_argument('order_id', type=int)
- parser.add_argument('user', type=str)
- parser.add_argument('specs', type=str)
- parser.add_argument('template', type=str)
-
- def handle(self, *args, **options):
- vm_id = options['vm_id']
- order_id = options['order_id']
- user_str = options['user']
- specs_str = options['specs']
- template_str = options['template']
-
- json_acceptable_string = user_str.replace("'", "\"")
- user_dict = json.loads(json_acceptable_string)
-
- json_acceptable_string = specs_str.replace("'", "\"")
- specs = json.loads(json_acceptable_string)
-
- json_acceptable_string = template_str.replace("'", "\"")
- template = json.loads(json_acceptable_string)
- if vm_id <= 0:
- self.stdout.write(self.style.ERROR(
- 'vm_id can\'t be less than or 0. Given: %s' % vm_id))
- return
- if vm_id <= 0:
- self.stdout.write(self.style.ERROR(
- 'order_id can\'t be less than or 0. Given: %s' % vm_id))
- return
- if specs_str is None or specs_str == "":
- self.stdout.write(
- self.style.ERROR('specs can\'t be empty or None'))
- return
-
- user = {
- 'name': user_dict['name'],
- 'email': user_dict['email'],
- 'username': user_dict['username'],
- 'pass': user_dict['pass'],
- 'request_scheme': user_dict['request_scheme'],
- 'request_host': user_dict['request_host'],
- 'language': user_dict['language'],
- }
- cu = CustomUser.objects.get(username=user.get('username'))
- # Create OpenNebulaManager
- self.stdout.write(
- self.style.SUCCESS(
- 'Connecting using %s' % (cu.username)
- )
- )
- manager = OpenNebulaManager(email=cu.username, password=cu.password)
- handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template)
- self.stdout.write(
- self.style.SUCCESS(
- 'Done handling metadata and emails for %s %s %s' % (
- order_id,
- vm_id,
- str(user)
- )
- )
- )
diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index 899b506f..55be8099 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -56,8 +56,13 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
"Running create_vm_task on {}".format(current_task.request.hostname))
vm_id = None
try:
+ final_price = (
+ specs.get('total_price') if 'total_price' in specs
+ else specs.get('price')
+ )
+
if 'pass' in user:
- on_user = user.get('username')
+ on_user = user.get('email')
on_pass = user.get('pass')
logger.debug("Using user {user} to create VM".format(user=on_user))
vm_name = None
@@ -87,8 +92,107 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
if vm_id is None:
raise Exception("Could not create VM")
- handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template)
+ # Update HostingOrder with the created vm_id
+ hosting_order = HostingOrder.objects.filter(id=order_id).first()
+ error_msg = None
+
+ try:
+ hosting_order.vm_id = vm_id
+ hosting_order.save()
+ logger.debug(
+ "Updated hosting_order {} with vm_id={}".format(
+ hosting_order.id, vm_id
+ )
+ )
+ except Exception as ex:
+ error_msg = (
+ "HostingOrder with id {order_id} not found. This means that "
+ "the hosting order was not created and/or it is/was not "
+ "associated with VM with id {vm_id}. Details {details}".format(
+ order_id=order_id, vm_id=vm_id, details=str(ex)
+ )
+ )
+ logger.error(error_msg)
+
+ stripe_utils = StripeUtils()
+ result = stripe_utils.set_subscription_metadata(
+ subscription_id=hosting_order.subscription_id,
+ metadata={"VM_ID": str(vm_id)}
+ )
+
+ if result.get('error') is not None:
+ emsg = "Could not update subscription metadata for {sub}".format(
+ sub=hosting_order.subscription_id
+ )
+ logger.error(emsg)
+ if error_msg:
+ error_msg += ". " + emsg
+ else:
+ error_msg = emsg
+
+ vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
+
+ context = {
+ 'name': user.get('name'),
+ 'email': user.get('email'),
+ 'cores': specs.get('cpu'),
+ 'memory': specs.get('memory'),
+ 'storage': specs.get('disk_size'),
+ 'price': final_price,
+ 'template': template.get('name'),
+ 'vm_name': vm.get('name'),
+ 'vm_id': vm['vm_id'],
+ 'order_id': order_id
+ }
+
+ if error_msg:
+ context['errors'] = error_msg
+ if 'pricing_name' in specs:
+ context['pricing'] = str(VMPricing.get_vm_pricing_by_name(
+ name=specs['pricing_name']
+ ))
+ email_data = {
+ 'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
+ 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
+ 'to': ['info@ungleich.ch'],
+ 'body': "\n".join(
+ ["%s=%s" % (k, v) for (k, v) in context.items()]),
+ 'reply_to': [context['email']],
+ }
+ email = EmailMessage(**email_data)
+ email.send()
+
+ if 'pass' in user:
+ lang = 'en-us'
+ if user.get('language') is not None:
+ logger.debug(
+ "Language is set to {}".format(user.get('language')))
+ lang = user.get('language')
+ translation.activate(lang)
+ # Send notification to the user as soon as VM has been booked
+ context = {
+ 'base_url': "{0}://{1}".format(user.get('request_scheme'),
+ user.get('request_host')),
+ 'order_url': reverse('hosting:invoices'),
+ 'page_header': _(
+ 'Your New VM %(vm_name)s at Data Center Light') % {
+ 'vm_name': vm.get('name')},
+ 'vm_name': vm.get('name')
+ }
+ email_data = {
+ 'subject': context.get('page_header'),
+ 'to': user.get('email'),
+ 'context': context,
+ 'template_name': 'new_booked_vm',
+ 'template_path': 'hosting/emails/',
+ 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
+ }
+ email = BaseEmail(**email_data)
+ email.send()
+
+ logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
+ if vm_id > 0:
+ get_or_create_vm_detail(custom_user, manager, vm_id)
except Exception as e:
logger.error(str(e))
try:
@@ -110,127 +214,3 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
return
return vm_id
-
-
-def handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template):
- """
- Handle's setting up of the metadata in Stripe and database and sending of
- emails to the user after VM creation
-
- :param order_id: the hosting order id
- :param vm_id: the id of the vm created
- :param manager: the OpenNebula Manager instance
- :param user: the user's dict passed to the celery task
- :param specs: the specification's dict passed to the celery task
- :param template: the template dict passed to the celery task
-
- :return:
- """
-
- custom_user = CustomUser.objects.get(email=user.get('email'))
- final_price = (
- specs.get('total_price') if 'total_price' in specs
- else specs.get('price')
- )
- # Update HostingOrder with the created vm_id
- hosting_order = HostingOrder.objects.filter(id=order_id).first()
- error_msg = None
-
- try:
- hosting_order.vm_id = vm_id
- hosting_order.save()
- logger.debug(
- "Updated hosting_order {} with vm_id={}".format(
- hosting_order.id, vm_id
- )
- )
- except Exception as ex:
- error_msg = (
- "HostingOrder with id {order_id} not found. This means that "
- "the hosting order was not created and/or it is/was not "
- "associated with VM with id {vm_id}. Details {details}".format(
- order_id=order_id, vm_id=vm_id, details=str(ex)
- )
- )
- logger.error(error_msg)
-
- stripe_utils = StripeUtils()
- result = stripe_utils.set_subscription_metadata(
- subscription_id=hosting_order.subscription_id,
- metadata={"VM_ID": str(vm_id)}
- )
-
- if result.get('error') is not None:
- emsg = "Could not update subscription metadata for {sub}".format(
- sub=hosting_order.subscription_id
- )
- logger.error(emsg)
- if error_msg:
- error_msg += ". " + emsg
- else:
- error_msg = emsg
-
- vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
-
- context = {
- 'name': user.get('name'),
- 'email': user.get('email'),
- 'cores': specs.get('cpu'),
- 'memory': specs.get('memory'),
- 'storage': specs.get('disk_size'),
- 'price': final_price,
- 'template': template.get('name'),
- 'vm_name': vm.get('name'),
- 'vm_id': vm['vm_id'],
- 'order_id': order_id
- }
-
- if error_msg:
- context['errors'] = error_msg
- if 'pricing_name' in specs:
- context['pricing'] = str(VMPricing.get_vm_pricing_by_name(
- name=specs['pricing_name']
- ))
- email_data = {
- 'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': ['dcl-orders@ungleich.ch'],
- 'body': "\n".join(
- ["%s=%s" % (k, v) for (k, v) in context.items()]),
- 'reply_to': [context['email']],
- }
- email = EmailMessage(**email_data)
- email.send()
-
- if 'pass' in user:
- lang = 'en-us'
- if user.get('language') is not None:
- logger.debug(
- "Language is set to {}".format(user.get('language')))
- lang = user.get('language')
- translation.activate(lang)
- # Send notification to the user as soon as VM has been booked
- context = {
- 'base_url': "{0}://{1}".format(user.get('request_scheme'),
- user.get('request_host')),
- 'order_url': reverse('hosting:invoices'),
- 'page_header': _(
- 'Your New VM %(vm_name)s at Data Center Light') % {
- 'vm_name': vm.get('name')},
- 'vm_name': vm.get('name')
- }
- email_data = {
- 'subject': context.get('page_header'),
- 'to': user.get('email'),
- 'context': context,
- 'template_name': 'new_booked_vm',
- 'template_path': 'hosting/emails/',
- 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
- }
- email = BaseEmail(**email_data)
- email.send()
-
- logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
- if vm_id > 0:
- get_or_create_vm_detail(custom_user, manager, vm_id)
diff --git a/datacenterlight/templates/datacenterlight/emails/welcome_user.html b/datacenterlight/templates/datacenterlight/emails/welcome_user.html
index 2044b2ee..25185618 100644
--- a/datacenterlight/templates/datacenterlight/emails/welcome_user.html
+++ b/datacenterlight/templates/datacenterlight/emails/welcome_user.html
@@ -28,7 +28,7 @@
{% blocktrans %}Thanks for joining us! We provide the most affordable virtual machines from the heart of Switzerland.{% endblocktrans %}
- {% blocktrans %}Try now, order a VM. VM price starts from only 11.5 CHF per month.{% endblocktrans %}
+ {% blocktrans %}Try now, order a VM. VM price starts from only 10.5 CHF per month.{% endblocktrans %}
diff --git a/datacenterlight/templates/datacenterlight/emails/welcome_user.txt b/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
index 06e8aa33..772e51a5 100644
--- a/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
+++ b/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
@@ -3,7 +3,7 @@
{% trans "Welcome to Data Center Light!" %}
{% blocktrans %}Thanks for joining us! We provide the most affordable virtual machines from the heart of Switzerland.{% endblocktrans %}
-{% blocktrans %}Try now, order a VM. VM price starts from only 11.5 CHF per month.{% endblocktrans %}
+{% blocktrans %}Try now, order a VM. VM price starts from only 10.5 CHF per month.{% endblocktrans %}
{{ base_url }}{% url 'hosting:create_virtual_machine' %}
diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html
index 1f7a3cda..02bce0ed 100644
--- a/datacenterlight/templates/datacenterlight/order_detail.html
+++ b/datacenterlight/templates/datacenterlight/order_detail.html
@@ -2,14 +2,6 @@
{% load staticfiles bootstrap3 i18n custom_tags humanize %}
{% block content %}
-
{% if messages %}
@@ -111,61 +103,58 @@
{% endif %}
- {% if generic_payment_details.exclude_vat_calculations %}
- {% else %}
-
-
+
+
+
+
+
+ {% trans "Price Before VAT" %}
+ {{generic_payment_details.amount_before_vat|floatformat:2|intcomma}} CHF
+
+
+
+
+
+
+
+
+
+
+
+
{% trans "Pre VAT" %}
+
+
+
{% trans "VAT for" %} {{generic_payment_details.vat_country}} ({{generic_payment_details.vat_rate}}%)
+
-
-
- {% trans "Price Before VAT" %}
- {{generic_payment_details.amount_before_vat|floatformat:2|intcomma}} CHF
-
@@ -278,16 +267,15 @@
{% if generic_payment_details %}
{% if generic_payment_details.recurring %}
{% if generic_payment_details.recurring_interval == 'year' %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %} By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF/year{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{total_price}} CHF/year{% endblocktrans %}.
{% else %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}
- By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF/month{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{total_price}} CHF/month{% endblocktrans %}.
{% endif %}
{% else %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this payment will charge your credit card account with a one time amount of {{total_price}} CHF{% endblocktrans %}.
{% endif %}
{% else %}
-
{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_total_price }} CHF/month{% endblocktrans %}.
+
{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{vm_total_price}} CHF/month{% endblocktrans %}.
{% endif %}
@@ -330,14 +318,5 @@
{%endblock%}
diff --git a/datacenterlight/templatetags/custom_tags.py b/datacenterlight/templatetags/custom_tags.py
index 120cabbf..0cb18e5b 100644
--- a/datacenterlight/templatetags/custom_tags.py
+++ b/datacenterlight/templatetags/custom_tags.py
@@ -6,7 +6,7 @@ from django.core.urlresolvers import resolve, reverse
from django.utils.safestring import mark_safe
from django.utils.translation import activate, get_language, ugettext_lazy as _
-from hosting.models import GenericProduct, HostingOrder
+from hosting.models import GenericProduct
from utils.hosting_utils import get_ip_addresses
logger = logging.getLogger(__name__)
@@ -63,41 +63,6 @@ def escaped_line_break(value):
return value.replace("\\n", "\n")
-@register.filter('get_line_item_from_hosting_order_charge')
-def get_line_item_from_hosting_order_charge(hosting_order_id):
- """
- Returns ready-to-use "html" line item to be shown for a charge in the
- invoice list page
-
- :param hosting_order_id: the HostingOrder id
- :return:
- """
- try:
- hosting_order = HostingOrder.objects.get(id = hosting_order_id)
- if hosting_order.stripe_charge_id:
- return mark_safe("""
-
{% blocktrans with vm_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_price }} CHF/month.{% endblocktrans %}.
+
{% blocktrans with vm_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{ vm_price }} CHF/month{% endblocktrans %}.
diff --git a/hosting/urls.py b/hosting/urls.py
index e34d27d6..5b2b87b0 100644
--- a/hosting/urls.py
+++ b/hosting/urls.py
@@ -51,7 +51,7 @@ urlpatterns = [
name='choice_ssh_keys'),
url(r'delete_ssh_key/(?P\d+)/?$', SSHKeyDeleteView.as_view(),
name='delete_ssh_key'),
- url(r'delete_card/(?P[\w\-]+)/$', SettingsView.as_view(),
+ url(r'delete_card/(?P\d+)/?$', SettingsView.as_view(),
name='delete_card'),
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),
name='create_ssh_key'),
diff --git a/hosting/views.py b/hosting/views.py
index e2f6e13b..17af51fd 100644
--- a/hosting/views.py
+++ b/hosting/views.py
@@ -1,7 +1,6 @@
import logging
import uuid
from datetime import datetime
-from urllib.parse import quote
from time import sleep
import stripe
@@ -14,7 +13,6 @@ from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse_lazy, reverse
-from django.db.models import Q
from django.http import (
Http404, HttpResponseRedirect, HttpResponse, JsonResponse
)
@@ -388,7 +386,7 @@ class PasswordResetConfirmView(HostingContextMixin,
user = CustomUser.objects.get(pk=uid)
opennebula_client = OpenNebulaManager(
- email=user.username,
+ email=user.email,
password=user.password,
)
@@ -480,7 +478,7 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
def delete(self, request, *args, **kwargs):
owner = self.request.user
manager = OpenNebulaManager(
- email=owner.username,
+ email=owner.email,
password=owner.password
)
pk = self.kwargs.get('pk')
@@ -534,7 +532,7 @@ class SSHKeyChoiceView(LoginRequiredMixin, View):
ssh_key.private_key.save(filename, content)
owner = self.request.user
manager = OpenNebulaManager(
- email=owner.username,
+ email=owner.email,
password=owner.password
)
keys = get_all_public_keys(request.user)
@@ -565,11 +563,9 @@ class SettingsView(LoginRequiredMixin, FormView):
stripe_customer = None
if hasattr(user, 'stripecustomer'):
stripe_customer = user.stripecustomer
- stripe_utils = StripeUtils()
- cards_list_request = stripe_utils.get_available_payment_methods(
- stripe_customer
+ cards_list = UserCardDetail.get_all_cards_list(
+ stripe_customer=stripe_customer
)
- cards_list = cards_list_request.get('response_object')
context.update({
'cards_list': cards_list,
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
@@ -580,38 +576,48 @@ class SettingsView(LoginRequiredMixin, FormView):
def post(self, request, *args, **kwargs):
if 'card' in request.POST and request.POST['card'] is not '':
card_id = escape(request.POST['card'])
+ user_card_detail = UserCardDetail.objects.get(id=card_id)
UserCardDetail.set_default_card(
stripe_api_cus_id=request.user.stripecustomer.stripe_id,
- stripe_source_id=card_id
+ stripe_source_id=user_card_detail.card_id
)
- stripe_utils = StripeUtils()
- card_details = stripe_utils.get_cards_details_from_payment_method(
- card_id
- )
- if not card_details.get('response_object'):
- logger.debug("Could not find card %s in stripe" % card_id)
- messages.add_message(request, messages.ERROR,
- _("Could not set a default card."))
- return HttpResponseRedirect(reverse_lazy('hosting:settings'))
- card_details_response = card_details['response_object']
msg = _(
("Your {brand} card ending in {last4} set as "
"default card").format(
- brand=card_details_response['brand'],
- last4=card_details_response['last4']
+ brand=user_card_detail.brand,
+ last4=user_card_detail.last4
)
)
messages.add_message(request, messages.SUCCESS, msg)
return HttpResponseRedirect(reverse_lazy('hosting:settings'))
if 'delete_card' in request.POST:
- card = self.kwargs.get('pk')
- stripe_utils = StripeUtils()
- stripe_utils.dissociate_customer_card(
- request.user.stripecustomer.stripe_id,
- card
- )
- msg = _("Card deassociation successful")
- messages.add_message(request, messages.SUCCESS, msg)
+ try:
+ card = UserCardDetail.objects.get(pk=self.kwargs.get('pk'))
+ if (request.user.has_perm(self.permission_required[0], card)
+ and
+ request.user
+ .stripecustomer
+ .usercarddetail_set
+ .count() > 1):
+ if card.card_id is not None:
+ stripe_utils = StripeUtils()
+ stripe_utils.dissociate_customer_card(
+ request.user.stripecustomer.stripe_id,
+ card.card_id
+ )
+ if card.preferred:
+ UserCardDetail.set_default_card_from_stripe(
+ request.user.stripecustomer.stripe_id
+ )
+ card.delete()
+ msg = _("Card deassociation successful")
+ messages.add_message(request, messages.SUCCESS, msg)
+ else:
+ msg = _("You are not permitted to do this operation")
+ messages.add_message(request, messages.ERROR, msg)
+ except UserCardDetail.DoesNotExist:
+ msg = _("The selected card does not exist")
+ messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(reverse_lazy('hosting:settings'))
form = self.get_form()
if form.is_valid():
@@ -686,49 +692,51 @@ class SettingsView(LoginRequiredMixin, FormView):
msg = _("Billing address updated successfully")
messages.add_message(request, messages.SUCCESS, msg)
else:
- id_payment_method = request.POST.get('id_payment_method', None)
+ token = form.cleaned_data.get('token')
stripe_utils = StripeUtils()
- card_details = stripe_utils.get_cards_details_from_payment_method(
- id_payment_method
+ card_details = stripe_utils.get_cards_details_from_token(
+ token
)
if not card_details.get('response_object'):
form.add_error("__all__", card_details.get('error'))
return self.render_to_response(self.get_context_data())
stripe_customer = StripeCustomer.get_or_create(
- email=request.user.email, id_payment_method=id_payment_method
+ email=request.user.email, token=token
)
card = card_details['response_object']
- acc_result = stripe_utils.associate_customer_card(
- request.user.stripecustomer.stripe_id,
- id_payment_method,
- set_as_default=True
- )
- if acc_result['response_object'] is None:
- msg = _(
- 'An error occurred while associating the card.'
- ' Details: {details}'.format(
- details=acc_result['error']
- )
- )
+ if UserCardDetail.get_user_card_details(stripe_customer, card):
+ msg = _('You seem to have already added this card')
messages.add_message(request, messages.ERROR, msg)
- return self.render_to_response(self.get_context_data())
- preferred = False
- if stripe_customer.usercarddetail_set.count() == 0:
- preferred = True
- UserCardDetail.create(
- stripe_customer=stripe_customer,
- last4=card['last4'],
- brand=card['brand'],
- fingerprint=card['fingerprint'],
- exp_month=card['exp_month'],
- exp_year=card['exp_year'],
- card_id=card['card_id'],
- preferred=preferred
- )
- msg = _(
- "Successfully associated the card with your account"
- )
- messages.add_message(request, messages.SUCCESS, msg)
+ else:
+ acc_result = stripe_utils.associate_customer_card(
+ request.user.stripecustomer.stripe_id, token
+ )
+ if acc_result['response_object'] is None:
+ msg = _(
+ 'An error occurred while associating the card.'
+ ' Details: {details}'.format(
+ details=acc_result['error']
+ )
+ )
+ messages.add_message(request, messages.ERROR, msg)
+ return self.render_to_response(self.get_context_data())
+ preferred = False
+ if stripe_customer.usercarddetail_set.count() == 0:
+ preferred = True
+ UserCardDetail.create(
+ stripe_customer=stripe_customer,
+ last4=card['last4'],
+ brand=card['brand'],
+ fingerprint=card['fingerprint'],
+ exp_month=card['exp_month'],
+ exp_year=card['exp_year'],
+ card_id=card['card_id'],
+ preferred=preferred
+ )
+ msg = _(
+ "Successfully associated the card with your account"
+ )
+ messages.add_message(request, messages.SUCCESS, msg)
return self.render_to_response(self.get_context_data())
else:
billing_address_data = form.cleaned_data
@@ -944,7 +952,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
except VMDetail.DoesNotExist:
try:
manager = OpenNebulaManager(
- email=owner.username, password=owner.password
+ email=owner.email, password=owner.password
)
vm = manager.get_vm(obj.vm_id)
context['vm'] = VirtualMachineSerializer(vm).data
@@ -1069,13 +1077,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
billing_address_data = request.session.get('billing_address_data')
vm_template_id = template.get('id', 1)
stripe_api_cus_id = request.user.stripecustomer.stripe_id
- logger.debug("template=%s specs=%s stripe_customer_id=%s "
- "billing_address_data=%s vm_template_id=%s "
- "stripe_api_cus_id=%s" % (
- template, specs, stripe_customer_id, billing_address_data,
- vm_template_id, stripe_api_cus_id)
- )
- if 'id_payment_method' in self.request.session:
+ if 'token' in self.request.session:
card_details = stripe_utils.get_cards_details_from_token(
request.session['token']
)
@@ -1092,7 +1094,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
)
if not ucd:
acc_result = stripe_utils.associate_customer_card(
- stripe_api_cus_id, request.session['id_payment_method'],
+ stripe_api_cus_id, request.session['token'],
set_as_default=True
)
if acc_result['response_object'] is None:
@@ -1185,29 +1187,12 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
[{"plan": stripe_plan.get('response_object').stripe_plan_id}],
coupon=(discount['stripe_coupon_id']
if 'name' in discount and
- discount['name'] is not None and
'ipv6' in discount['name'].lower() and
discount['stripe_coupon_id']
else ""),
tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [],
- default_payment_method=request.session['id_payment_method']
)
stripe_subscription_obj = subscription_result.get('response_object')
- latest_invoice = stripe.Invoice.retrieve(stripe_subscription_obj.latest_invoice)
- ret = stripe.PaymentIntent.confirm(
- latest_invoice.payment_intent
- )
- if ret.status == 'requires_source_action' or ret.status == 'requires_action':
- pi = stripe.PaymentIntent.retrieve(
- latest_invoice.payment_intent
- )
- context = {
- 'sid': stripe_subscription_obj.id,
- 'payment_intent_secret': pi.client_secret,
- 'STRIPE_PUBLISHABLE_KEY': settings.STRIPE_API_PUBLIC_KEY,
- 'showSCA': True
- }
- return JsonResponse(context)
# Check if the subscription was approved and is active
if (stripe_subscription_obj is None or
stripe_subscription_obj.status != 'active'):
@@ -1246,7 +1231,6 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
user = {
'name': self.request.user.name,
'email': self.request.user.email,
- 'username': self.request.user.username,
'pass': self.request.user.password,
'request_scheme': request.scheme,
'request_host': request.get_host(),
@@ -1301,11 +1285,10 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
page = self.request.GET.get('page', 1)
context = super(InvoiceListView, self).get_context_data(**kwargs)
invs_page = None
- invs_page_charges = None
if ('user_email' in self.request.GET
and self.request.user.email == settings.ADMIN_EMAIL):
user_email = self.request.GET['user_email']
- context['user_email'] = '%s' % quote(user_email)
+ context['user_email'] = user_email
logger.debug(
"user_email = {}".format(user_email)
)
@@ -1315,8 +1298,7 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
logger.debug("User does not exist")
cu = self.request.user
invs = stripe.Invoice.list(customer=cu.stripecustomer.stripe_id,
- count=100,
- status='paid')
+ count=100)
paginator = Paginator(invs.data, 10)
try:
invs_page = paginator.page(page)
@@ -1324,21 +1306,6 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
invs_page = paginator.page(1)
except EmptyPage:
invs_page = paginator.page(paginator.num_pages)
- hosting_orders = HostingOrder.objects.filter(
- customer=cu.stripecustomer).filter(
- Q(subscription_id=None) | Q(subscription_id='')
- ).order_by('-created_at')
- stripe_chgs = []
- for ho in hosting_orders:
- stripe_chgs.append({ho.id: stripe.Charge.retrieve(ho.stripe_charge_id)})
-
- paginator_charges = Paginator(stripe_chgs, 10)
- try:
- invs_page_charges = paginator_charges.page(page)
- except PageNotAnInteger:
- invs_page_charges = paginator_charges.page(1)
- except EmptyPage:
- invs_page_charges = paginator_charges.page(paginator_charges.num_pages)
else:
try:
invs = stripe.Invoice.list(
@@ -1352,27 +1319,10 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
invs_page = paginator.page(1)
except EmptyPage:
invs_page = paginator.page(paginator.num_pages)
- hosting_orders = HostingOrder.objects.filter(
- customer=self.request.user.stripecustomer).filter(
- Q(subscription_id=None) | Q(subscription_id='')
- ).order_by('-created_at')
- stripe_chgs = []
- for ho in hosting_orders:
- stripe_chgs.append(
- {ho: stripe.Charge.retrieve(ho.stripe_charge_id)})
- paginator_charges = Paginator(stripe_chgs, 10)
- try:
- invs_page_charges = paginator_charges.page(page)
- except PageNotAnInteger:
- invs_page_charges = paginator_charges.page(1)
- except EmptyPage:
- invs_page_charges = paginator_charges.page(
- paginator_charges.num_pages)
except Exception as ex:
logger.error(str(ex))
invs_page = None
context["invs"] = invs_page
- context["invs_charge"] = invs_page_charges
return context
@method_decorator(decorators)
@@ -1453,7 +1403,7 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
# fallback to get it from the infrastructure
try:
manager = OpenNebulaManager(
- email=self.request.user.username,
+ email=self.request.user.email,
password=self.request.user.password
)
vm = manager.get_vm(vm_id)
@@ -1536,7 +1486,7 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
def get_queryset(self):
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
try:
queryset = manager.get_vms()
@@ -1697,7 +1647,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
owner = self.request.user
vm = None
manager = OpenNebulaManager(
- email=owner.username,
+ email=owner.email,
password=owner.password
)
vm_id = self.kwargs.get('pk')
@@ -1781,7 +1731,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
vm = self.get_object()
manager = OpenNebulaManager(
- email=owner.username,
+ email=owner.email,
password=owner.password
)
try:
@@ -1809,7 +1759,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
error_msg = result.get('error')
logger.error(
'Error canceling subscription for {user} and vm id '
- '{vm_id}'.format(user=owner.username, vm_id=vm.id)
+ '{vm_id}'.format(user=owner.email, vm_id=vm.id)
)
logger.error(error_msg)
admin_email_body['stripe_error_msg'] = error_msg
@@ -1831,7 +1781,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
response['text'] = str(_('Error terminating VM')) + str(vm.id)
else:
- for t in range(settings.MAX_TIME_TO_WAIT_FOR_VM_TERMINATE):
+ for t in range(15):
try:
manager.get_vm(vm.id)
except WrongIdError:
@@ -1854,10 +1804,6 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
break
else:
- logger.debug(
- 'Sleeping 2 seconds for terminate action on VM %s' %
- vm.id
- )
sleep(2)
if not response['status']:
response['text'] = str(_("VM terminate action timed out. "
@@ -1885,7 +1831,6 @@ class VirtualMachineView(LoginRequiredMixin, View):
email.send()
admin_email_body.update(response)
admin_email_body["customer_email"] = owner.email
- admin_email_body["customer_username"] = owner.username
admin_email_body["VM_ID"] = vm.id
admin_email_body["VM_created_at"] = (str(hosting_order.created_at) if
hosting_order is not None
@@ -1903,15 +1848,15 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
admin_email_body["subscription_amount"] = total_amount/100
admin_email_body["subscription_detail"] = content
- admin_msg_sub = "VM and Subscription for VM {} and user: {}, {}".format(
+ admin_msg_sub = "VM and Subscription for VM {} and user: {}".format(
vm.id,
- owner.email, owner.username
+ owner.email
)
email_to_admin_data = {
'subject': ("Deleted " if response['status']
else "ERROR deleting ") + admin_msg_sub,
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': ['dcl-orders@ungleich.ch'],
+ 'to': ['info@ungleich.ch'],
'body': "\n".join(
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
}
@@ -1951,7 +1896,7 @@ class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin,
context = super(DetailView, self).get_context_data(**kwargs)
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# Get vms
queryset = manager.get_vms()
diff --git a/membership/models.py b/membership/models.py
index 81054fb9..80aaf408 100644
--- a/membership/models.py
+++ b/membership/models.py
@@ -233,17 +233,8 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
ldap_manager.create_user(self.username, password=password,
firstname=first_name, lastname=last_name,
email=self.email)
- else:
- # User exists already in LDAP, but with a dummy credential
- # We are here implies that the user has successfully
- # authenticated against Django db, and a corresponding user
- # exists in LDAP.
- # We just update the LDAP credentials once again, assuming it
- # was set to a dummy value while migrating users from Django to
- # LDAP
- ldap_manager.change_password(self.username, password)
- self.in_ldap = True
- self.save()
+ self.in_ldap = True
+ self.save()
def __str__(self): # __unicode__ on Python 2
return self.email
@@ -277,7 +268,7 @@ class StripeCustomer(models.Model):
return "%s - %s" % (self.stripe_id, self.user.email)
@classmethod
- def create_stripe_api_customer(cls, email=None, id_payment_method=None,
+ def create_stripe_api_customer(cls, email=None, token=None,
customer_name=None):
"""
This method creates a Stripe API customer with the given
@@ -288,8 +279,7 @@ class StripeCustomer(models.Model):
stripe user.
"""
stripe_utils = StripeUtils()
- stripe_data = stripe_utils.create_customer(
- id_payment_method, email, customer_name)
+ stripe_data = stripe_utils.create_customer(token, email, customer_name)
if stripe_data.get('response_object'):
stripe_cus_id = stripe_data.get('response_object').get('id')
return stripe_cus_id
@@ -297,7 +287,7 @@ class StripeCustomer(models.Model):
return None
@classmethod
- def get_or_create(cls, email=None, token=None, id_payment_method=None):
+ def get_or_create(cls, email=None, token=None):
"""
Check if there is a registered stripe customer with that email
or create a new one
diff --git a/opennebula_api/models.py b/opennebula_api/models.py
index 2f76f423..19e3e4f7 100644
--- a/opennebula_api/models.py
+++ b/opennebula_api/models.py
@@ -154,8 +154,6 @@ class OpenNebulaManager():
protocol=settings.OPENNEBULA_PROTOCOL)
)
raise ConnectionRefusedError
- except Exception as ex:
- logger.error(str(ex))
def _get_user_pool(self):
try:
@@ -429,12 +427,8 @@ class OpenNebulaManager():
template_id = int(template_id)
try:
template_pool = self._get_template_pool()
- if template_id in settings.UPDATED_TEMPLATES_DICT.keys():
- template_id = settings.UPDATED_TEMPLATES_DICT[template_id]
return template_pool.get_by_id(template_id)
- except Exception as ex:
- logger.debug("Template Id we are looking for : %s" % template_id)
- logger.error(str(ex))
+ except:
raise ConnectionRefusedError
def create_template(self, name, cores, memory, disk_size, core_price,
diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py
index 34cdde7c..c7418aa5 100644
--- a/opennebula_api/serializers.py
+++ b/opennebula_api/serializers.py
@@ -86,7 +86,7 @@ class VirtualMachineSerializer(serializers.Serializer):
}
try:
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password,
)
opennebula_id = manager.create_vm(template_id=template_id,
diff --git a/opennebula_api/views.py b/opennebula_api/views.py
index 318fa32e..9bf03a74 100644
--- a/opennebula_api/views.py
+++ b/opennebula_api/views.py
@@ -19,7 +19,7 @@ class VmCreateView(generics.ListCreateAPIView):
def get_queryset(self):
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
@@ -42,7 +42,7 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
def get_queryset(self):
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
@@ -54,7 +54,7 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
def get_object(self):
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
@@ -66,7 +66,7 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
def perform_destroy(self, instance):
owner = self.request.user
- manager = OpenNebulaManager(email=owner.username,
+ manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
diff --git a/release.sh b/release.sh
deleted file mode 100755
index 535cc7d4..00000000
--- a/release.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-# Nico Schottelius, 2021-12-17
-
-current=$(git describe --dirty)
-last_tag=$(git describe --tags --abbrev=0)
-registry=harbor.ungleich.svc.p10.k8s.ooo/ungleich-public
-image_url=$registry/dynamicweb:${current}
-
-if echo $current | grep -q -e 'dirty$'; then
- echo Refusing to release a dirty tree build
- exit 1
-fi
-
-if [ "$current" != "$last_tag" ]; then
- echo "Last tag ($last_tag) is not current version ($current)"
- echo "Only release proper versions"
- exit 1
-fi
-
-docker tag dynamicweb:${current} ${image_url}
-docker push ${image_url}
diff --git a/requirements.txt b/requirements.txt
index 8d04a189..e7769a7e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -25,7 +25,7 @@ django-compressor==2.0
django-debug-toolbar==1.4
python-dotenv==0.10.3
django-extensions==1.6.7
-django-filer==2.1.2
+django-filer==1.2.0
django-filter==0.13.0
django-formtools==1.0
django-guardian==1.4.4
@@ -83,7 +83,7 @@ stripe==2.41.0
wheel==0.29.0
django-admin-honeypot==1.0.0
coverage==4.3.4
-git+https://github.com/ungleich/python-oca.git#egg=oca
+git+https://github.com/ungleich/python-oca.git#egg=python-oca
djangorestframework==3.6.3
flake8==3.3.0
python-memcached==1.58
diff --git a/templates/gdpr/gdpr_banner.html b/templates/gdpr/gdpr_banner.html
index f927f8ee..7e9f5c7f 100644
--- a/templates/gdpr/gdpr_banner.html
+++ b/templates/gdpr/gdpr_banner.html
@@ -134,6 +134,8 @@
digitalglarus.ch
hack4lgarus.ch
ipv6onlyhosting.com
+ ipv6onlyhosting.ch
+ ipv6onlyhosting.net
django-hosting.ch
rails-hosting.ch
node-hosting.ch
diff --git a/utils/ldap_manager.py b/utils/ldap_manager.py
index d40e931f..fd039ad5 100644
--- a/utils/ldap_manager.py
+++ b/utils/ldap_manager.py
@@ -3,7 +3,6 @@ import hashlib
import random
import ldap3
import logging
-import unicodedata
from django.conf import settings
@@ -88,7 +87,7 @@ class LdapManager:
logger.debug("{uid} does not exist. Using it".format(uid=uidNumber))
self._set_max_uid(uidNumber)
try:
- uid = user
+ uid = user.encode("utf-8")
conn.add("uid={uid},{customer_dn}".format(
uid=uid, customer_dn=settings.LDAP_CUSTOMER_DN
),
@@ -102,7 +101,7 @@ class LdapManager:
"uidNumber": [str(uidNumber)],
"gidNumber": [str(settings.LDAP_CUSTOMER_GROUP_ID)],
"loginShell": ["/bin/bash"],
- "homeDirectory": ["/home/{}".format(unicodedata.normalize('NFKD', user).encode('ascii','ignore'))],
+ "homeDirectory": ["/home/{}".format(user).encode("utf-8")],
"mail": email.encode("utf-8"),
"userPassword": [self._ssha_password(
password.encode("utf-8")
@@ -267,7 +266,7 @@ class LdapManager:
logger.error(
"Error reading int value from {}. {}"
"Returning default value {} instead".format(
- settings.LDAP_MAX_UID_FILE_PATH,
+ settings.LDAP_MAX_UID_PATH,
str(ve),
settings.LDAP_DEFAULT_START_UID
)
diff --git a/utils/stripe_utils.py b/utils/stripe_utils.py
index 875a174e..ade06dd3 100644
--- a/utils/stripe_utils.py
+++ b/utils/stripe_utils.py
@@ -34,7 +34,6 @@ def handleStripeError(f):
logger.error(str(e))
return response
except stripe.error.RateLimitError as e:
- logger.error(str(e))
response.update(
{'error': "Too many requests made to the API too quickly"})
return response
@@ -70,7 +69,7 @@ class StripeUtils(object):
CURRENCY = 'chf'
INTERVAL = 'month'
SUCCEEDED_STATUS = 'succeeded'
- RESOURCE_ALREADY_EXISTS_ERROR_CODE = 'resource_already_exists'
+ STRIPE_PLAN_ALREADY_EXISTS = 'Plan already exists'
STRIPE_NO_SUCH_PLAN = 'No such plan'
PLAN_EXISTS_ERROR_MSG = 'Plan {} exists already.\nCreating a local StripePlan now.'
PLAN_DOES_NOT_EXIST_ERROR_MSG = 'Plan {} does not exist.'
@@ -83,31 +82,20 @@ class StripeUtils(object):
customer.save()
@handleStripeError
- def associate_customer_card(self, stripe_customer_id, id_payment_method,
+ def associate_customer_card(self, stripe_customer_id, token,
set_as_default=False):
customer = stripe.Customer.retrieve(stripe_customer_id)
- stripe.PaymentMethod.attach(
- id_payment_method,
- customer=stripe_customer_id,
- )
+ card = customer.sources.create(source=token)
if set_as_default:
- customer.invoice_settings.default_payment_method = id_payment_method
+ customer.default_source = card.id
customer.save()
return True
@handleStripeError
def dissociate_customer_card(self, stripe_customer_id, card_id):
customer = stripe.Customer.retrieve(stripe_customer_id)
- if card_id.startswith("pm"):
- logger.debug("PaymentMethod %s detached %s" % (card_id,
- stripe_customer_id))
- pm = stripe.PaymentMethod.retrieve(card_id)
- stripe.PaymentMethod.detach(card_id)
- pm.delete()
- else:
- logger.debug("card %s detached %s" % (card_id, stripe_customer_id))
- card = customer.sources.retrieve(card_id)
- card.delete()
+ card = customer.sources.retrieve(card_id)
+ card.delete()
@handleStripeError
def update_customer_card(self, customer_id, token):
@@ -199,24 +187,6 @@ class StripeUtils(object):
}
return card_details
- @handleStripeError
- def get_cards_details_from_payment_method(self, payment_method_id):
- payment_method = stripe.PaymentMethod.retrieve(payment_method_id)
- # payment_method does not always seem to have a card with id
- # if that is the case, fallback to payment_method_id for card_id
- card_id = payment_method_id
- if hasattr(payment_method.card, 'id'):
- card_id = payment_method.card.id
- card_details = {
- 'last4': payment_method.card.last4,
- 'brand': payment_method.card.brand,
- 'exp_month': payment_method.card.exp_month,
- 'exp_year': payment_method.card.exp_year,
- 'fingerprint': payment_method.card.fingerprint,
- 'card_id': card_id
- }
- return card_details
-
def check_customer(self, stripe_cus_api_id, user, token):
try:
customer = stripe.Customer.retrieve(stripe_cus_api_id)
@@ -236,11 +206,11 @@ class StripeUtils(object):
return customer
@handleStripeError
- def create_customer(self, id_payment_method, email, name=None):
+ def create_customer(self, token, email, name=None):
if name is None or name.strip() == "":
name = email
customer = self.stripe.Customer.create(
- payment_method=id_payment_method,
+ source=token,
description=name,
email=email
)
@@ -297,17 +267,11 @@ class StripeUtils(object):
stripe_plan_db_obj = StripePlan.objects.create(
stripe_plan_id=stripe_plan_id)
except stripe.error.InvalidRequestError as e:
- logger.error(str(e))
- logger.error("error_code = %s" % str(e.__dict__))
- if self.RESOURCE_ALREADY_EXISTS_ERROR_CODE in e.error.code:
+ if self.STRIPE_PLAN_ALREADY_EXISTS in str(e):
logger.debug(
self.PLAN_EXISTS_ERROR_MSG.format(stripe_plan_id))
- stripe_plan_db_obj, c = StripePlan.objects.get_or_create(
+ stripe_plan_db_obj = StripePlan.objects.create(
stripe_plan_id=stripe_plan_id)
- if c:
- logger.debug("Created stripe plan %s" % stripe_plan_id)
- else:
- logger.debug("Plan %s exists already" % stripe_plan_id)
return stripe_plan_db_obj
@handleStripeError
@@ -336,14 +300,10 @@ class StripeUtils(object):
@handleStripeError
def subscribe_customer_to_plan(self, customer, plans, trial_end=None,
- coupon="", tax_rates=list(),
- default_payment_method=""):
+ coupon="", tax_rates=list()):
"""
Subscribes the given customer to the list of given plans
- :param default_payment_method:
- :param tax_rates:
- :param coupon:
:param customer: The stripe customer identifier
:param plans: A list of stripe plans.
:param trial_end: An integer representing when the Stripe subscription
@@ -357,17 +317,12 @@ class StripeUtils(object):
]
:return: The subscription StripeObject
"""
- logger.debug("Subscribing %s to plan %s : coupon = %s" % (
- customer, str(plans), str(coupon)
- ))
+
subscription_result = self.stripe.Subscription.create(
customer=customer, items=plans, trial_end=trial_end,
coupon=coupon,
default_tax_rates=tax_rates,
- payment_behavior='allow_incomplete',
- default_payment_method=default_payment_method
)
- logger.debug("Done subscribing")
return subscription_result
@handleStripeError
@@ -525,49 +480,7 @@ class StripeUtils(object):
)
return tax_id_obj
- @handleStripeError
- def get_payment_intent(self, amount, customer):
- """ Create a stripe PaymentIntent of the given amount and return it
- :param amount: the amount of payment_intent
- :return:
- """
- payment_intent_obj = stripe.PaymentIntent.create(
- amount=amount,
- currency='chf',
- customer=customer,
- setup_future_usage='off_session'
- )
- return payment_intent_obj
-
- @handleStripeError
- def get_available_payment_methods(self, customer):
- """ Retrieves all payment methods of the given customer
- :param customer: StripeCustomer object
- :return: a list of available payment methods
- """
- return_list = []
- if customer is None:
- return return_list
- cu = stripe.Customer.retrieve(customer.stripe_id)
- pms = stripe.PaymentMethod.list(
- customer=customer.stripe_id,
- type="card",
- )
- default_source = None
- if cu.default_source:
- default_source = cu.default_source
- else:
- default_source = cu.invoice_settings.default_payment_method
- for pm in pms.data:
- return_list.append({
- 'last4': pm.card.last4, 'brand': pm.card.brand, 'id': pm.id,
- 'exp_year': pm.card.exp_year,
- 'exp_month': '{:02d}'.format(pm.card.exp_month),
- 'preferred': pm.id == default_source
- })
- return return_list
-
def compare_vat_numbers(self, vat1, vat2):
_vat1 = vat1.replace(" ", "").replace(".", "").replace("-","")
_vat2 = vat2.replace(" ", "").replace(".", "").replace("-","")
- return True if _vat1 == _vat2 else False
+ return True if _vat1 == _vat2 else False
\ No newline at end of file
diff --git a/utils/views.py b/utils/views.py
index f30a349a..05d0fdc2 100644
--- a/utils/views.py
+++ b/utils/views.py
@@ -228,7 +228,7 @@ class SSHKeyCreateView(FormView):
if self.request.user.is_authenticated():
owner = self.request.user
manager = OpenNebulaManager(
- email=owner.username,
+ email=owner.email,
password=owner.password
)
keys_to_save = get_all_public_keys(self.request.user)
diff --git a/vat_rates.csv b/vat_rates.csv
index 72870530..17bdb997 100644
--- a/vat_rates.csv
+++ b/vat_rates.csv
@@ -321,4 +321,5 @@ IM",GBP,0.1,standard,
2019-12-17,,IS,EUR,0.24,standard,Iceland standard VAT (added manually)
2019-12-17,,FX,EUR,0.20,standard,France metropolitan standard VAT (added manually)
2020-01-04,,CY,EUR,0.19,standard,Cyprus standard VAT (added manually)
+2019-01-04,,IL,EUR,0.23,standard,Ireland standard VAT (added manually)
2019-01-04,,LI,EUR,0.077,standard,Liechtenstein standard VAT (added manually)
diff --git a/webhook/views.py b/webhook/views.py
index 0a96d0b6..516d1afc 100644
--- a/webhook/views.py
+++ b/webhook/views.py
@@ -1,17 +1,14 @@
import datetime
import logging
-import json
-import stripe
+import stripe
# Create your views here.
from django.conf import settings
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
-from datacenterlight.views import do_provisioning, do_provisioning_generic
from membership.models import StripeCustomer
-from hosting.models import IncompleteSubscriptions, IncompletePaymentIntents
from utils.models import BillingAddress, UserBillingAddress
from utils.tasks import send_plain_email_task
@@ -114,193 +111,8 @@ def handle_webhook(request):
'to': settings.DCL_ERROR_EMAILS_TO_LIST,
'body': "Response = %s" % str(tax_id_obj),
}
+
send_plain_email_task.delay(email_data)
- elif event.type == 'invoice.paid':
- #More info: https://stripe.com/docs/billing/migration/strong-customer-authentication#scenario-1-handling-fulfillment
- invoice_obj = event.data.object
- logger.debug("Webhook Event: invoice.paid")
- logger.debug("invoice_obj %s " % str(invoice_obj))
- logger.debug("invoice_obj.paid = %s %s" % (invoice_obj.paid, type(invoice_obj.paid)))
- logger.debug("invoice_obj.billing_reason = %s %s" % (invoice_obj.billing_reason, type(invoice_obj.billing_reason)))
- # We should check for billing_reason == "subscription_create" but we
- # check for "subscription_update"
- # because we are using older api.
- # See https://stripe.com/docs/upgrades?since=2015-07-13
-
- # The billing_reason attribute of the invoice object now can take the
- # value of subscription_create, indicating that it is the first
- # invoice of a subscription. For older API versions,
- # billing_reason=subscription_create is represented as
- # subscription_update.
-
- if (invoice_obj.paid and
- invoice_obj.billing_reason == "subscription_update"):
- logger.debug("""invoice_obj.paid and
- invoice_obj.billing_reason == subscription_update""")
- logger.debug("Start provisioning")
- try:
- logger.debug("Looking for subscription %s" %
- invoice_obj.subscription)
- stripe_subscription_obj = stripe.Subscription.retrieve(
- invoice_obj.subscription)
- try:
- incomplete_sub = IncompleteSubscriptions.objects.get(
- subscription_id=invoice_obj.subscription)
- request = ""
- soc = ""
- card_details_response = ""
- gp_details = ""
- template = ""
- specs = ""
- billing_address_data = ""
- if incomplete_sub.request:
- request = json.loads(incomplete_sub.request)
- if incomplete_sub.specs:
- specs = json.loads(incomplete_sub.specs)
- if incomplete_sub.stripe_onetime_charge:
- soc = json.loads(incomplete_sub.stripe_onetime_charge)
- if incomplete_sub.gp_details:
- gp_details = json.loads(incomplete_sub.gp_details)
- if incomplete_sub.card_details_response:
- card_details_response = json.loads(
- incomplete_sub.card_details_response)
- if incomplete_sub.template:
- template = json.loads(
- incomplete_sub.template)
- if incomplete_sub.billing_address_data:
- billing_address_data = json.loads(
- incomplete_sub.billing_address_data)
- logger.debug("*******")
- logger.debug(str(incomplete_sub))
- logger.debug("*******")
- logger.debug("1*******")
- logger.debug(request)
- logger.debug("2*******")
- logger.debug(card_details_response)
- logger.debug("3*******")
- logger.debug(soc)
- logger.debug("4*******")
- logger.debug(gp_details)
- logger.debug("5*******")
- logger.debug(template)
- logger.debug("6*******")
- do_provisioning(
- request=request,
- stripe_api_cus_id=incomplete_sub.stripe_api_cus_id,
- card_details_response=card_details_response,
- stripe_subscription_obj=stripe_subscription_obj,
- stripe_onetime_charge=soc,
- gp_details=gp_details,
- specs=specs,
- vm_template_id=incomplete_sub.vm_template_id,
- template=template,
- billing_address_data=billing_address_data,
- real_request=None
- )
- except IncompleteSubscriptions.DoesNotExist as ex:
- logger.error(str(ex))
- except IncompleteSubscriptions.MultipleObjectsReturned as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "IncompleteSubscriptions error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
- except Exception as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "invoice.paid Webhook error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
- elif event.type == 'invoice.payment_failed':
- invoice_obj = event.data.object
- logger.debug("Webhook Event: invoice.payment_failed")
- logger.debug("invoice_obj %s " % str(invoice_obj))
- if (invoice_obj.payment_failed and
- invoice_obj.billing_reason == "subscription_update"):
- logger.debug("Payment failed, inform the users")
- elif event.type == 'payment_intent.succeeded':
- payment_intent_obj = event.data.object
- logger.debug("Webhook Event: payment_intent.succeeded")
- logger.debug("payment_intent_obj %s " % str(payment_intent_obj))
- try:
- logger.debug("Looking for IncompletePaymentIntents %s " %
- payment_intent_obj.id)
- incomplete_pm = IncompletePaymentIntents.objects.get(
- payment_intent_id=payment_intent_obj.id)
- logger.debug("incomplete_pm = %s" % str(incomplete_pm.__dict__))
- request = ""
- soc = ""
- card_details_response = ""
- gp_details = ""
- template = ""
- billing_address_data = ""
- if incomplete_pm.request:
- request = json.loads(incomplete_pm.request)
- logger.debug("request = %s" % str(request))
- if incomplete_pm.stripe_charge_id:
- soc = incomplete_pm.stripe_charge_id
- logger.debug("stripe_onetime_charge = %s" % str(soc))
- if incomplete_pm.gp_details:
- gp_details = json.loads(incomplete_pm.gp_details)
- logger.debug("gp_details = %s" % str(gp_details))
- if incomplete_pm.card_details_response:
- card_details_response = json.loads(
- incomplete_pm.card_details_response)
- logger.debug("card_details_response = %s" % str(card_details_response))
- if incomplete_pm.billing_address_data:
- billing_address_data = json.loads(
- incomplete_pm.billing_address_data)
- logger.debug("billing_address_data = %s" % str(billing_address_data))
- logger.debug("1*******")
- logger.debug(request)
- logger.debug("2*******")
- logger.debug(card_details_response)
- logger.debug("3*******")
- logger.debug(soc)
- logger.debug("4*******")
- logger.debug(gp_details)
- logger.debug("5*******")
- logger.debug(template)
- logger.debug("6*******")
- logger.debug(billing_address_data)
- incomplete_pm.completed_at = datetime.datetime.now()
- charges = ""
- if len(payment_intent_obj.charges.data) > 0:
- for d in payment_intent_obj.charges.data:
- if charges == "":
- charges = "%s" % d.id
- else:
- charges = "%s,%s" % (charges, d.id)
- logger.debug("Charge ids = %s" % charges)
- incomplete_pm.stripe_charge_id=charges
- do_provisioning_generic(
- request=request,
- stripe_api_cus_id=incomplete_pm.stripe_api_cus_id,
- card_details_response=card_details_response,
- stripe_subscription_id=None,
- stripe_charge_id=charges,
- gp_details=gp_details,
- billing_address_data=billing_address_data
- )
- incomplete_pm.save()
- except IncompletePaymentIntents.DoesNotExist as ex:
- logger.error(str(ex))
- except (IncompletePaymentIntents.MultipleObjectsReturned,
- Exception) as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "IncompletePaymentIntents error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
else:
logger.error("Unhandled event : " + event.type)
return HttpResponse(status=200)