diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index cc72f397..f10909ef 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: 2017-09-23 21:22+0000\n" +"POT-Creation-Date: 2017-09-29 19:59+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -423,30 +423,15 @@ msgstr "Abarbeitung..." msgid "Hold tight, we are processing your request" msgstr "Bitte warten - wir verbeiten Deine Anfrage gerade" +msgid "OK" +msgstr "" + +msgid "Close" +msgstr "" + msgid "Some problem encountered. Please try again later." msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal." -msgid "We are cutting down the costs significantly!" -msgstr "Wir sorgen dafür, dass die Kosten für Dich signifikant abnehmen" - -msgid "Order Now!" -msgstr "Bestelle jetzt!" - -msgid "" -"Our VMs are hosted in Glarus, Switzerland, and our website is currently " -"running in BETA mode. If you want more information that you did not find on " -"our website, or if your order is more detailed, or if you encounter any " -"technical hiccups, please contact us at support@datacenterlight.ch, our team " -"will get in touch with you asap." -msgstr "" -"Unsere VMs werden in der Schweiz im Kanton Glarus gehostet und befinden sich " -"zur Zeit noch in der BETA-Phase. Möchtest du mehr über uns erfahren und hast " -"auf unserer Website nicht genügend Informationen gefunden? Möchtest eine " -"detailliertere Bestellung aufgeben? Bist du auf technische Probleme " -"gestossen, die du uns mitteilen möchtest? Dann zögere nicht und kontaktiere " -"uns unter support@datacenterlight.ch. Unser Team wird sich umgehend um dein " -"Anliegen kümmern!" - 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 mit " @@ -547,6 +532,8 @@ msgid "" "There was a payment related error. On close of this popup, you will be " "redirected back to the payment page." 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." @@ -558,6 +545,27 @@ msgstr "" "Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du " "auf sie zugreifen kannst." +#~ msgid "We are cutting down the costs significantly!" +#~ msgstr "Wir sorgen dafür, dass die Kosten für Dich signifikant abnehmen" + +#~ msgid "Order Now!" +#~ msgstr "Bestelle jetzt!" + +#~ msgid "" +#~ "Our VMs are hosted in Glarus, Switzerland, and our website is currently " +#~ "running in BETA mode. If you want more information that you did not find " +#~ "on our website, or if your order is more detailed, or if you encounter " +#~ "any technical hiccups, please contact us at support@datacenterlight.ch, " +#~ "our team will get in touch with you asap." +#~ msgstr "" +#~ "Unsere VMs werden in der Schweiz im Kanton Glarus gehostet und befinden " +#~ "sich zur Zeit noch in der BETA-Phase. Möchtest du mehr über uns erfahren " +#~ "und hast auf unserer Website nicht genügend Informationen gefunden? " +#~ "Möchtest eine detailliertere Bestellung aufgeben? Bist du auf technische " +#~ "Probleme gestossen, die du uns mitteilen möchtest? Dann zögere nicht und " +#~ "kontaktiere uns unter support@datacenterlight.ch. Unser Team wird sich " +#~ "umgehend um dein Anliegen kümmern!" + #~ msgid "Email Address" #~ msgstr "E-Mail-Adresse" diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 7d589570..1f34c3fe 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -50,15 +50,20 @@ def retry_task(task, exception=None): @app.task(bind=True, max_retries=settings.CELERY_MAX_RETRIES) def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, - billing_address_id, - charge, cc_details): + stripe_subscription_id, cc_details): logger.debug( "Running create_vm_task on {}".format(current_task.request.hostname)) vm_id = None try: final_price = specs.get('price') - billing_address = BillingAddress.objects.filter( - id=billing_address_id).first() + billing_address = BillingAddress( + cardholder_name=billing_address_data['cardholder_name'], + street_address=billing_address_data['street_address'], + city=billing_address_data['city'], + postal_code=billing_address_data['postal_code'], + country=billing_address_data['country'] + ) + billing_address.save() customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() if 'pass' in user: @@ -111,8 +116,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, billing_address_user_form.save() # Associate an order with a stripe subscription - charge_object = DictDotLookup(charge) - order.set_subscription_id(charge_object, cc_details) + order.set_subscription_id(stripe_subscription_id, cc_details) # If the Stripe payment succeeds, set order status approved order.set_approved() @@ -183,7 +187,8 @@ def create_vm_task(self, vm_template_id, user, specs, template, public_keys] if len(keys) > 0: logger.debug( - "Calling configure on {host} for {num_keys} keys".format( + "Calling configure on {host} for " + "{num_keys} keys".format( host=new_host, num_keys=len(keys))) # Let's delay the task by 75 seconds to be sure # that we run the cdist configure after the host @@ -212,32 +217,3 @@ def create_vm_task(self, vm_template_id, user, specs, template, return return vm_id - - -class DictDotLookup(object): - """ - Creates objects that behave much like a dictionaries, but allow nested - key access using object '.' (dot) lookups. - """ - - def __init__(self, d): - for k in d: - if isinstance(d[k], dict): - self.__dict__[k] = DictDotLookup(d[k]) - elif isinstance(d[k], (list, tuple)): - l = [] - for v in d[k]: - if isinstance(v, dict): - l.append(DictDotLookup(v)) - else: - l.append(v) - self.__dict__[k] = l - else: - self.__dict__[k] = d[k] - - def __getitem__(self, name): - if name in self.__dict__: - return self.__dict__[name] - - def __iter__(self): - return iter(self.__dict__.keys()) diff --git a/datacenterlight/tests.py b/datacenterlight/tests.py index edde2db8..19ba4d7e 100644 --- a/datacenterlight/tests.py +++ b/datacenterlight/tests.py @@ -75,21 +75,12 @@ class CeleryTaskTestCase(TestCase): stripe_customer.stripe_id, self.token) card_details_dict = card_details.get('response_object') - billing_address = BillingAddress( - cardholder_name=self.customer_name, - postal_code='1232', - country='CH', - street_address='Monty\'s Street', - city='Hollywood') - billing_address.save() billing_address_data = {'cardholder_name': self.customer_name, 'postal_code': '1231', 'country': 'CH', 'token': self.token, 'street_address': 'Monty\'s Street', 'city': 'Hollywood'} - - billing_address_id = billing_address.id vm_template_id = template_data.get('id', 1) cpu = specs.get('cpu') @@ -125,8 +116,7 @@ class CeleryTaskTestCase(TestCase): template_data, stripe_customer.id, billing_address_data, - billing_address_id, - stripe_subscription_obj, + stripe_subscription_obj.id, card_details_dict) new_vm_id = 0 res = None diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 308913b0..ed840e83 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -348,6 +348,11 @@ class PaymentOrderView(FormView): form_kwargs.update({ 'instance': self.request.user.billing_addresses.first() }) + if 'billing_address_data' in self.request.session: + billing_address_data = self.request.session['billing_address_data'] + form_kwargs.update({ + 'initial': billing_address_data + }) return form_kwargs def get_context_data(self, **kwargs): @@ -379,14 +384,40 @@ class PaymentOrderView(FormView): email=this_user.get('email'), token=token) else: + user_email = form.cleaned_data.get('email') + user_name = form.cleaned_data.get('name') this_user = { - 'email': form.cleaned_data.get('email'), - 'name': form.cleaned_data.get('name') + 'email': user_email, + 'name': user_name } - customer = StripeCustomer.create_stripe_api_customer( - email=this_user.get('email'), - token=token, - customer_name=form.cleaned_data.get('name')) + try: + custom_user = CustomUser.objects.get(email=user_email) + customer = StripeCustomer.objects.filter( + user_id=custom_user.id).first() + if customer is None: + logger.debug( + ("User {email} is already registered with us." + "But, StripeCustomer does not exist for {email}." + "Hence, creating a new StripeCustomer.").format( + email=user_email + ) + ) + customer = StripeCustomer.create_stripe_api_customer( + email=user_email, + token=token, + customer_name=user_name) + except CustomUser.DoesNotExist: + logger.debug( + ("StripeCustomer does not exist for {email}." + "Hence, creating a new StripeCustomer.").format( + email=user_email + ) + ) + customer = StripeCustomer.create_stripe_api_customer( + email=user_email, + token=token, + customer_name=user_name) + request.session['billing_address_data'] = form.cleaned_data request.session['user'] = this_user # Get or create stripe customer @@ -395,8 +426,10 @@ class PaymentOrderView(FormView): return self.render_to_response( self.get_context_data(form=form)) request.session['token'] = token - request.session[ - 'customer'] = customer.id if request.user.is_authenticated() else customer + if type(customer) is StripeCustomer: + request.session['customer'] = customer.stripe_id + else: + request.session['customer'] = customer return HttpResponseRedirect( reverse('datacenterlight:order_confirmation')) else: @@ -415,14 +448,7 @@ class OrderConfirmationView(DetailView): return HttpResponseRedirect(reverse('datacenterlight:index')) if 'token' not in request.session: return HttpResponseRedirect(reverse('datacenterlight:payment')) - stripe_customer_id = request.session.get('customer') - if request.user.is_authenticated(): - customer = StripeCustomer.objects.filter( - id=stripe_customer_id).first() - stripe_api_cus_id = customer.stripe_id - else: - stripe_api_cus_id = stripe_customer_id - + stripe_api_cus_id = request.session.get('customer') stripe_utils = StripeUtils() card_details = stripe_utils.get_card_details(stripe_api_cus_id, request.session.get( @@ -445,15 +471,8 @@ class OrderConfirmationView(DetailView): template = request.session.get('template') specs = request.session.get('specs') user = request.session.get('user') - stripe_customer_id = request.session.get('customer') - if request.user.is_authenticated(): - customer = StripeCustomer.objects.filter( - id=stripe_customer_id).first() - stripe_api_cus_id = customer.stripe_id - else: - stripe_api_cus_id = stripe_customer_id + stripe_api_cus_id = request.session.get('customer') vm_template_id = template.get('id', 1) - stripe_utils = StripeUtils() card_details = stripe_utils.get_card_details(stripe_api_cus_id, request.session.get( @@ -498,8 +517,8 @@ class OrderConfirmationView(DetailView): 'response_object').stripe_plan_id}]) stripe_subscription_obj = subscription_result.get('response_object') # Check if the subscription was approved and is active - if stripe_subscription_obj is None or \ - stripe_subscription_obj.status != 'active': + if (stripe_subscription_obj is None + or stripe_subscription_obj.status != 'active'): msg = subscription_result.get('error') messages.add_message(self.request, messages.ERROR, msg, extra_tags='failed_payment') @@ -546,10 +565,10 @@ class OrderConfirmationView(DetailView): password=password) login(request, new_user) else: - customer = StripeCustomer.objects.filter( - id=stripe_customer_id).first() - custom_user = customer.user - stripe_customer_id = customer.id + # We assume that if the user is here, his/her StripeCustomer + # object already exists + stripe_customer_id = request.user.stripecustomer.id + custom_user = request.user # Save billing address billing_address_data = request.session.get('billing_address_data') @@ -557,12 +576,6 @@ class OrderConfirmationView(DetailView): billing_address_data.update({ 'user': custom_user.id }) - billing_address_user_form = UserBillingAddressForm( - instance=custom_user.billing_addresses.first(), - data=billing_address_data) - billing_address = billing_address_user_form.save() - billing_address_id = billing_address.id - logger.debug("billing address id = {}".format(billing_address_id)) user = { 'name': custom_user.name, 'email': custom_user.email, @@ -574,8 +587,7 @@ class OrderConfirmationView(DetailView): create_vm_task.delay(vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, - billing_address_id, - stripe_subscription_obj, card_details_dict) + stripe_subscription_obj.id, card_details_dict) for session_var in ['specs', 'template', 'billing_address', 'billing_address_data', 'token', 'customer']: diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py index dc2917ea..5af1a6ca 100644 --- a/dynamicweb/settings/base.py +++ b/dynamicweb/settings/base.py @@ -161,6 +161,8 @@ MIDDLEWARE_CLASSES = ( 'cms.middleware.language.LanguageCookieMiddleware', ) +CSRF_FAILURE_VIEW = 'hosting.views.forbidden_view' + ROOT_URLCONF = 'dynamicweb.urls' TEMPLATES = [ diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index c4c644f8..984bafde 100644 --- a/hosting/locale/de/LC_MESSAGES/django.po +++ b/hosting/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: 2017-09-24 12:34+0000\n" +"POT-Creation-Date: 2017-10-01 20:57+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -337,6 +337,9 @@ msgstr "Rechnung Datum" msgid "Status" msgstr "" +msgid "Terminated" +msgstr "Beendet" + msgid "Approved" msgstr "Akzeptiert" @@ -358,6 +361,9 @@ msgstr "Bestellungsübersicht" msgid "Product" msgstr "Produkt" +msgid "Period" +msgstr "" + msgid "Cores" msgstr "Prozessorkerne" @@ -390,6 +396,12 @@ msgstr "Abarbeitung..." msgid "Hold tight, we are processing your request" msgstr "Bitte warten - wir bearbeiten Deine Anfrage gerade" +msgid "OK" +msgstr "" + +msgid "Close" +msgstr "Schliessen" + msgid "Some problem encountered. Please try again later." msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal." @@ -599,16 +611,13 @@ msgstr "Deine Virtuelle Maschine beenden" msgid "Do you want to cancel your Virtual Machine" msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst" -msgid "OK" -msgstr "" - #, python-format msgid "" "Your Virtual Machine %(machine_name)s is successfully " "terminated!" msgstr "" -"Deine Virtuelle Machine (VM) %(machine_name)s wurde erfolgreich " -"beendet!" +"Deine Virtuelle Machine (VM) %(machine_name)s wurde " +"erfolgreich beendet!" msgid "Virtual Machines" msgstr "Virtuelle Maschinen" @@ -616,6 +625,13 @@ msgstr "Virtuelle Maschinen" msgid "To create a new virtual machine, click \"Create VM\"" msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\"" +#, python-format +msgid "" +"To access your VM, add your SSH key here" +msgstr "" +"Um auf Deine VM zuzugreifen, füge Deinen SSH-" +"Key hinzu" + msgid "CREATE VM" msgstr "NEUE VM" @@ -673,6 +689,16 @@ msgid "In order to create a VM, you need to create/upload your SSH KEY first." msgstr "" "Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen." +msgid "Error." +msgstr "Fehler" + +msgid "" +"There was a payment related error. On close of this popup, you will be " +"redirected back to the payment page." +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." @@ -697,8 +723,11 @@ msgid "" "contact Data Center Light Support." msgstr "Kontaktiere den Data Center Light Support." -msgid "Terminated" -msgstr "Beendet" +msgid "" +"We could not find the requested VM. Please contact Data Center Light Support." +msgstr "" +"Wir konnten die gesucht VM nicht finden. Kontaktiere den Data Center Light " +"Support." msgid "Error terminating VM" msgstr "Fehler beenden VM" @@ -706,8 +735,9 @@ msgstr "Fehler beenden VM" msgid "Virtual Machine Cancellation" msgstr "VM Kündigung" -#~ msgid "Close" -#~ msgstr "Schliessen" +msgid "There was an error processing your request. Please try again." +msgstr "Es gab einen Fehler bei der Bearbeitung Deine Anfrage. Bitte" +" versuche es noch einmal." #~ msgid "VM %(VM_ID)s terminated successfully" #~ msgstr "VM %(VM_ID)s erfolgreich beendet" @@ -842,5 +872,5 @@ msgstr "VM Kündigung" #~ "Your SSH private key was already generated and downloaded, if you lost " #~ "it, contact us. " #~ msgstr "" -#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. " -#~ "Falls Du ihn verloren hast, kontaktiere uns." +#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. Falls " +#~ "Du ihn verloren hast, kontaktiere uns." diff --git a/hosting/models.py b/hosting/models.py index 73c082bb..49932f69 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -88,19 +88,19 @@ class HostingOrder(AssignPermissionsMixin, models.Model): self.cc_brand = stripe_charge.source.brand self.save() - def set_subscription_id(self, subscription_object, cc_details): + def set_subscription_id(self, subscription_id, cc_details): """ When creating a Stripe subscription, we have subscription id. We store this in the subscription_id field. - This method sets the subscription id from subscription_object - and also the last4 and credit card brands used for this order. + This method sets the subscription id + and the last4 and credit card brands used for this order. - :param subscription_object: Stripe's subscription object + :param subscription_id: Stripe's subscription id :param cc_details: A dict containing card details {last4, brand} :return: """ - self.subscription_id = subscription_object.id + self.subscription_id = subscription_id self.last4 = cc_details.get('last4') self.cc_brand = cc_details.get('brand') self.save() diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 01a58127..d30ebc83 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -86,23 +86,31 @@ $(document).ready(function() { url: create_vm_form.attr('action'), type: 'POST', data: create_vm_form.serialize(), + init: function(){ + ok_btn = $('#createvm-modal-done-btn'); + close_btn = $('#createvm-modal-close-btn'); + ok_btn.addClass('btn btn-success btn-ok btn-wide hide'); + close_btn.addClass('btn btn-danger btn-ok btn-wide hide'); + }, success: function (data) { + fa_icon = $('.modal-icon > .fa'); + modal_btn = $('#createvm-modal-done-btn'); + $('#createvm-modal-title').text(data.msg_title); + $('#createvm-modal-body').html(data.msg_body); + modal_btn.attr('href', data.redirect) + .removeClass('hide'); if (data.status === true) { - fa_icon = $('.modal-icon > .fa'); fa_icon.attr('class', 'checkmark'); - // $('.modal-header > .close').removeClass('hidden'); - $('#createvm-modal-title').text(data.msg_title); - $('#createvm-modal-body').text(data.msg_body); - $('#createvm-modal-done-btn') - .attr('href', data.redirect) - .removeClass('hide'); + } else { + fa_icon.attr('class', 'fa fa-close'); + modal_btn.attr('class', '').addClass('btn btn-danger btn-ok btn-wide'); } }, error: function (xmlhttprequest, textstatus, message) { fa_icon = $('.modal-icon > .fa'); fa_icon.attr('class', 'fa fa-close'); if (typeof(create_vm_error_message) !== 'undefined') { - $('#createvm-modal-text').text(create_vm_error_message); + $('#createvm-modal-body').text(create_vm_error_message); } $('#btn-create-vm').prop('disabled', false); $('#createvm-modal-close-btn').removeClass('hide'); diff --git a/hosting/templates/hosting/includes/_messages.html b/hosting/templates/hosting/includes/_messages.html new file mode 100644 index 00000000..13500fdb --- /dev/null +++ b/hosting/templates/hosting/includes/_messages.html @@ -0,0 +1,8 @@ +{% if messages %} +
    + {% for message in messages %} +
    {{ message|safe }}
    + {% endfor %} +
+{% endif %} \ No newline at end of file diff --git a/hosting/templates/hosting/login.html b/hosting/templates/hosting/login.html index 82056d2f..eda3fffa 100644 --- a/hosting/templates/hosting/login.html +++ b/hosting/templates/hosting/login.html @@ -16,13 +16,7 @@

{% trans "Login"%}

- {% if messages %} -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} + {% include 'hosting/includes/_messages.html' %}
{% csrf_token %} {% for field in form %} diff --git a/hosting/templates/hosting/resend_activation_link.html b/hosting/templates/hosting/resend_activation_link.html index fffb6e59..c3f76f76 100644 --- a/hosting/templates/hosting/resend_activation_link.html +++ b/hosting/templates/hosting/resend_activation_link.html @@ -17,6 +17,7 @@