From 07aaa20efe2223414eeafd67067a7e33b0f09cf9 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 14:46:56 +0200 Subject: [PATCH 01/37] Fix issue : stripe user created every time for unauthenticated user --- datacenterlight/views.py | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 308913b0..f29d4087 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -379,14 +379,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 @@ -499,7 +525,7 @@ class OrderConfirmationView(DetailView): 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': + stripe_subscription_obj.status != 'active': msg = subscription_result.get('error') messages.add_message(self.request, messages.ERROR, msg, extra_tags='failed_payment') From 4add1af933f18fba48c420c17eb2dbf2fdc68c85 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 14:49:17 +0200 Subject: [PATCH 02/37] Fix flake8 warnings --- membership/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/membership/models.py b/membership/models.py index d3f6372a..73804008 100644 --- a/membership/models.py +++ b/membership/models.py @@ -184,9 +184,9 @@ class StripeCustomer(models.Model): customer_name=None): """ This method creates a Stripe API customer with the given - email, token and customer_name. This is different from - get_or_create method below in that it does not create a - CustomUser and associate the customer created in stripe + email, token and customer_name. This is different from + get_or_create method below in that it does not create a + CustomUser and associate the customer created in stripe with it, while get_or_create does that before creating the stripe user. """ From 46925c29c4bc6d2785d5fc74b9704d3b3dc07443 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 14:57:03 +0200 Subject: [PATCH 03/37] Add error detail to the message --- datacenterlight/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index f29d4087..863eb80c 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -536,9 +536,10 @@ class OrderConfirmationView(DetailView): section='payment_error'), 'msg_title': str(_('Error.')), 'msg_body': str( - _('There was a payment related error.' - ' On close of this popup, you will be redirected back to' - ' the payment page.')) + _('There was a payment related error.
' + 'Details: {error_detail}
' + 'On close of this popup, you will be redirected back to' + ' the payment page.'.format(error_detail=msg))) } return HttpResponse(json.dumps(response), content_type="application/json") From 57f0757fa32b9c2639653521154c750a5f8cef4d Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 15:00:44 +0200 Subject: [PATCH 04/37] Update datacenterlight django.po --- .../locale/de/LC_MESSAGES/django.po | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index cc72f397..03b5bee0 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-28 12:57+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 " @@ -548,6 +533,12 @@ msgid "" "redirected back to the payment page." msgstr "" +#, python-brace-format +msgid "" +"There was a payment related error.
Details: {error_detail}
On close " +"of this popup, you will be redirected back to the payment page." +msgstr "" + msgid "Thank you for the order." msgstr "Danke für Deine Bestellung." @@ -558,6 +549,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" From c13015eabd71de843f3f7d47548f5371286c1ab3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 15:56:09 +0200 Subject: [PATCH 05/37] Refactor and correct some logic --- datacenterlight/views.py | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 863eb80c..a5fd54f0 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -421,8 +421,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: @@ -441,14 +443,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( @@ -471,15 +466,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( @@ -537,7 +525,7 @@ class OrderConfirmationView(DetailView): 'msg_title': str(_('Error.')), 'msg_body': str( _('There was a payment related error.
' - 'Details: {error_detail}
' + 'Details: {error_detail}
' 'On close of this popup, you will be redirected back to' ' the payment page.'.format(error_detail=msg))) } @@ -573,10 +561,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') From 03442398c2a2b87dee9a881e5978688549b127ca Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 17:31:29 +0200 Subject: [PATCH 06/37] Handle message create vm request in js --- .../static/hosting/js/virtual_machine_detail.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 01a58127..2c97542f 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -87,15 +87,16 @@ $(document).ready(function() { type: 'POST', data: create_vm_form.serialize(), success: function (data) { + fa_icon = $('.modal-icon > .fa'); + $('#createvm-modal-title').text(data.msg_title); + $('#createvm-modal-body').text(data.msg_body); + $('#createvm-modal-done-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-cross'); } }, error: function (xmlhttprequest, textstatus, message) { From fcda0b5637e56d18acfb33e51192eccded03cb31 Mon Sep 17 00:00:00 2001 From: PCoder Date: Fri, 29 Sep 2017 01:25:22 +0530 Subject: [PATCH 07/37] DCL payment page: Get form data from session on error --- datacenterlight/views.py | 4 ++++ utils/forms.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index a5fd54f0..a6732d83 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -348,6 +348,10 @@ class PaymentOrderView(FormView): form_kwargs.update({ 'instance': self.request.user.billing_addresses.first() }) + if 'billing_address_data' in self.request.session: + form_kwargs.update({ + 'billing_address_data': self.request.session['billing_address_data'] + }) return form_kwargs def get_context_data(self, **kwargs): diff --git a/utils/forms.py b/utils/forms.py index f8a6d103..a856eb8d 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -118,6 +118,12 @@ class EditCreditCardForm(forms.Form): class BillingAddressForm(forms.ModelForm): token = forms.CharField(widget=forms.HiddenInput(), required=False) + def __init__(self, *args, **kwargs): + billing_address_data = kwargs.get('billing_address_data', {}) + kwargs['initial'] = billing_address_data + super(BillingAddressForm, self).__init__(*args, **kwargs) + + class Meta: model = BillingAddress fields = ['cardholder_name', 'street_address', @@ -136,6 +142,11 @@ class BillingAddressFormSignup(BillingAddressForm): email = forms.EmailField(label=_('Email Address')) field_order = ['name', 'email'] + def __init__(self, *args, **kwargs): + billing_address_data = kwargs.get('billing_address_data', {}) + kwargs['initial'] = billing_address_data + super(BillingAddressFormSignup, self).__init__(*args, **kwargs) + class UserBillingAddressForm(forms.ModelForm): user = forms.ModelChoiceField(queryset=CustomUser.objects.all(), From 0202d5ba93074de0c62736e03baf3300ddb1ff5d Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 22:56:33 +0200 Subject: [PATCH 08/37] Add initial values for dcl billing form --- datacenterlight/views.py | 3 ++- utils/forms.py | 11 ----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index a6732d83..c45aea61 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -349,8 +349,9 @@ class PaymentOrderView(FormView): '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({ - 'billing_address_data': self.request.session['billing_address_data'] + 'initial': billing_address_data }) return form_kwargs diff --git a/utils/forms.py b/utils/forms.py index a856eb8d..f8a6d103 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -118,12 +118,6 @@ class EditCreditCardForm(forms.Form): class BillingAddressForm(forms.ModelForm): token = forms.CharField(widget=forms.HiddenInput(), required=False) - def __init__(self, *args, **kwargs): - billing_address_data = kwargs.get('billing_address_data', {}) - kwargs['initial'] = billing_address_data - super(BillingAddressForm, self).__init__(*args, **kwargs) - - class Meta: model = BillingAddress fields = ['cardholder_name', 'street_address', @@ -142,11 +136,6 @@ class BillingAddressFormSignup(BillingAddressForm): email = forms.EmailField(label=_('Email Address')) field_order = ['name', 'email'] - def __init__(self, *args, **kwargs): - billing_address_data = kwargs.get('billing_address_data', {}) - kwargs['initial'] = billing_address_data - super(BillingAddressFormSignup, self).__init__(*args, **kwargs) - class UserBillingAddressForm(forms.ModelForm): user = forms.ModelChoiceField(queryset=CustomUser.objects.all(), From 9cab43f051beb5081bf36ea816b576888428f431 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 23:03:22 +0200 Subject: [PATCH 09/37] Update modal with html from server --- hosting/static/hosting/js/virtual_machine_detail.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 2c97542f..8838bb8c 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -89,21 +89,21 @@ $(document).ready(function() { success: function (data) { fa_icon = $('.modal-icon > .fa'); $('#createvm-modal-title').text(data.msg_title); - $('#createvm-modal-body').text(data.msg_body); + $('#createvm-modal-body').html(data.msg_body); $('#createvm-modal-done-btn') .attr('href', data.redirect) .removeClass('hide'); if (data.status === true) { fa_icon.attr('class', 'checkmark'); } else { - fa_icon.attr('class', 'fa fa-cross'); + fa_icon.attr('class', 'fa fa-close'); } }, 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'); From f60a2c3482470844bfa0f5ff207d6ea03d6c1b9c Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 23:20:43 +0200 Subject: [PATCH 10/37] Make correct icons load on dcl createvm error modal --- datacenterlight/views.py | 6 +++--- hosting/static/hosting/js/virtual_machine_detail.js | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index c45aea61..57a400e1 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -529,9 +529,9 @@ class OrderConfirmationView(DetailView): section='payment_error'), 'msg_title': str(_('Error.')), 'msg_body': str( - _('There was a payment related error.
' - 'Details: {error_detail}
' - 'On close of this popup, you will be redirected back to' + _('There was a payment related error.' + ' Details: {error_detail}.' + ' On close of this popup, you will be redirected back to' ' the payment page.'.format(error_detail=msg))) } return HttpResponse(json.dumps(response), diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 8838bb8c..7f9eff95 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -88,15 +88,16 @@ $(document).ready(function() { data: create_vm_form.serialize(), 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); - $('#createvm-modal-done-btn') - .attr('href', data.redirect) + modal_btn.attr('href', data.redirect) .removeClass('hide'); if (data.status === true) { fa_icon.attr('class', 'checkmark'); } 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) { From 4ce1ff073a4842930e2147acaa71917b4b6b7431 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Thu, 28 Sep 2017 23:31:29 +0200 Subject: [PATCH 11/37] Some more modal styles --- hosting/static/hosting/js/virtual_machine_detail.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 7f9eff95..d30ebc83 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -86,6 +86,12 @@ $(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'); From 5783e4217197a9444c123028ffd27f6d72271869 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:37:25 +0200 Subject: [PATCH 12/37] Refactor code and add following fixes - create_vm_task receiving stripe_subscription_id instead of object - Fix: use BillingAddress instead of UserBillingAddress in HostingOrder, HostingPlan - Remove DictDotLookup class --- datacenterlight/tasks.py | 47 ++++++++++------------------------------ 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 7d589570..96eb415d 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -51,14 +51,20 @@ def retry_task(task, exception=None): 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 +117,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 +188,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 +218,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()) From f29a3ad0e6b5adb95c288ba90e39f68a33c672d3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:39:20 +0200 Subject: [PATCH 13/37] Pass subscription_id to create_vm_task instead of the object --- datacenterlight/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/tests.py b/datacenterlight/tests.py index edde2db8..28e15fca 100644 --- a/datacenterlight/tests.py +++ b/datacenterlight/tests.py @@ -126,7 +126,7 @@ class CeleryTaskTestCase(TestCase): 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 From caad79304bb5c9ad23267a1e2e38498632648743 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:40:43 +0200 Subject: [PATCH 14/37] Pass subscription_id instead of subscription object --- datacenterlight/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 57a400e1..32d2862b 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -595,7 +595,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']: From 313ba9d50200f40689b9dda5c29ba39240ef68b4 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:42:17 +0200 Subject: [PATCH 15/37] Refactor set_subscription_id - use stripe subscription id instead of obj --- hosting/models.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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() From ac37349aefd4b25a972bdfb6ba3531e33beef90a Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:50:03 +0200 Subject: [PATCH 16/37] Refactor code and pass subscription_id instead of obj --- hosting/views.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index facc8c01..3804cb0b 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -80,8 +80,6 @@ class DjangoHostingView(ProcessVMSelectionMixin, View): templates = OpenNebulaManager().get_templates() data = VirtualMachineTemplateSerializer(templates, many=True).data configuration_options = HostingPlan.get_serialized_configs() - - # configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING) context = { 'hosting': HOSTING, 'hosting_long': "Django", @@ -134,7 +132,6 @@ class NodeJSHostingView(ProcessVMSelectionMixin, View): def get_context_data(self, **kwargs): HOSTING = 'nodejs' - # configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING) templates = OpenNebulaManager().get_templates() configuration_options = HostingPlan.get_serialized_configs() @@ -249,7 +246,8 @@ class SignupValidateView(TemplateView):
{go_back} {hurl}.'.format( signup_success_message=_( 'Thank you for signing up. We have sent an email to you. ' - 'Please follow the instructions in it to activate your account. Once activated, you can login using'), + 'Please follow the instructions in it to activate your ' + 'account. Once activated, you can login using'), go_back=_('Go back to'), lurl=login_url, hurl=home_url @@ -269,7 +267,8 @@ class SignupValidatedView(SignupValidateView): reverse('hosting:login') + '">' + str(_('login')) + '' section_title = _('Account activation') if validated: - message = '{account_activation_string}
{login_string} {lurl}.'.format( + message = ('{account_activation_string}
' + ' {login_string} {lurl}.').format( account_activation_string=_( "Your account has been activated."), login_string=_("You can now"), @@ -687,7 +686,8 @@ class OrdersHostingDetailView(LoginRequiredMixin, try: vm_detail = VMDetail.objects.get(vm_id=obj.vm_id) context['vm'] = vm_detail.__dict__ - context['vm']['name'] = '{}-{}'.format(context['vm']['configuration'], context['vm']['vm_id']) + context['vm']['name'] = '{}-{}'.format( + context['vm']['configuration'], context['vm']['vm_id']) except VMDetail.DoesNotExist: try: manager = OpenNebulaManager( @@ -788,7 +788,8 @@ class OrdersHostingDetailView(LoginRequiredMixin, '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') @@ -805,7 +806,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, 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', From 483aa493bb93ca266c9fa9d9de09044d15b888a8 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:51:58 +0200 Subject: [PATCH 17/37] Remove billing_address_id as it is no more used --- datacenterlight/tasks.py | 1 - 1 file changed, 1 deletion(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 96eb415d..1f34c3fe 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -50,7 +50,6 @@ 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, stripe_subscription_id, cc_details): logger.debug( "Running create_vm_task on {}".format(current_task.request.hostname)) From 61a4060e1086fe6ceaec6e5b4d833cd8abd9dc4e Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:55:30 +0200 Subject: [PATCH 18/37] datacenterlight/tests: remove billing_address_id in call to create_vm_task --- datacenterlight/tests.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/datacenterlight/tests.py b/datacenterlight/tests.py index 28e15fca..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,7 +116,6 @@ class CeleryTaskTestCase(TestCase): template_data, stripe_customer.id, billing_address_data, - billing_address_id, stripe_subscription_obj.id, card_details_dict) new_vm_id = 0 From d06f5ffb0048387f45b7ba4c121b113245c05c8e Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 08:58:45 +0200 Subject: [PATCH 19/37] datacenterlight/views: remove billing_address_id in call to create_vm_task --- datacenterlight/views.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 32d2862b..2539a179 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -577,12 +577,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, @@ -594,7 +588,6 @@ 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.id, card_details_dict) for session_var in ['specs', 'template', 'billing_address', 'billing_address_data', From 5c99dd4da7b561fb3d204cf415efb75b318c64bf Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 09:07:38 +0200 Subject: [PATCH 20/37] hosting/views: remove billing_address_id in call to create_vm_task --- hosting/views.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index 3804cb0b..dd06e283 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -635,10 +635,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): return HttpResponseRedirect( reverse('hosting:payment') + '#payment_error') - # Create Billing Address - billing_address = form.save() request.session['billing_address_data'] = billing_address_data - request.session['billing_address'] = billing_address.id request.session['token'] = token request.session['customer'] = customer.id return HttpResponseRedirect("{url}?{query_params}".format( @@ -750,7 +747,6 @@ class OrdersHostingDetailView(LoginRequiredMixin, stripe_customer_id = request.session.get('customer') customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() billing_address_data = request.session.get('billing_address_data') - billing_address_id = request.session.get('billing_address') vm_template_id = template.get('id', 1) # Make stripe charge to a customer @@ -805,7 +801,6 @@ class OrdersHostingDetailView(LoginRequiredMixin, } create_vm_task.delay(vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, - billing_address_id, stripe_subscription_obj.id, card_details_dict) for session_var in ['specs', 'template', 'billing_address', From 5393ffa10ddcf3c7001050199faaf01e95e62cb3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 09:16:00 +0200 Subject: [PATCH 21/37] Small code reorganizing --- datacenterlight/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 2539a179..e95e0411 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -517,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') From 4b8d68fc8e086dd0d6dfa8c12c863d74348f147f Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 09:35:45 +0200 Subject: [PATCH 22/37] Reuse price parameter --- hosting/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index dd06e283..c0a4cb15 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -764,8 +764,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, cpu = specs.get('cpu') memory = specs.get('memory') disk_size = specs.get('disk_size') - amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, - disk_size=disk_size) + amount_to_be_charged = specs.get('price') plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, memory=memory, disk_size=disk_size) From e6869612d838741554ff046b4846b9994ea6f186 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 21:45:30 +0200 Subject: [PATCH 23/37] Update resend activation link email text --- utils/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/views.py b/utils/views.py index 4ec39bce..a7d8c1c1 100644 --- a/utils/views.py +++ b/utils/views.py @@ -66,7 +66,7 @@ class LoginViewMixin(FormView): class ResendActivationLinkViewMixin(FormView): success_message = _( - "An email with the activation link has been sent to your email") + "An email with the activation link has been sent to you") def generate_email_context(self, user): context = { From 1dfe1d7cf83a3d4575ab4ab2aa589ebf1c690f3e Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 21:53:02 +0200 Subject: [PATCH 24/37] Redirect to my virtual machines page if any error --- hosting/views.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hosting/views.py b/hosting/views.py index c0a4cb15..ca215a4d 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1003,6 +1003,7 @@ class VirtualMachineView(LoginRequiredMixin, View): return redirect(reverse('hosting:virtual_machines')) elif self.request.is_ajax(): return HttpResponse() + context = None try: serializer = VirtualMachineSerializer(vm) context = { @@ -1012,7 +1013,11 @@ class VirtualMachineView(LoginRequiredMixin, View): } except Exception as ex: logger.debug("Exception generated {}".format(str(ex))) - pass + messages.error(self.request, + _('We could not find the requested VM. Please ' + 'contact Data Center Light Support.') + ) + return redirect(reverse('hosting:virtual_machines')) return render(request, self.template_name, context) From 5bbfb54b79df27bdbd749665764eac79da74c1b3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 21:54:31 +0200 Subject: [PATCH 25/37] Revert back to simple error message --- datacenterlight/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index e95e0411..ed840e83 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -530,9 +530,8 @@ class OrderConfirmationView(DetailView): 'msg_title': str(_('Error.')), 'msg_body': str( _('There was a payment related error.' - ' Details: {error_detail}.' ' On close of this popup, you will be redirected back to' - ' the payment page.'.format(error_detail=msg))) + ' the payment page.')) } return HttpResponse(json.dumps(response), content_type="application/json") From 4bf73db14f7b8fee15c3da50ca2a5ec4d72521a6 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 22:01:28 +0200 Subject: [PATCH 26/37] Update datacenterlight django.po --- datacenterlight/locale/de/LC_MESSAGES/django.po | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index 03b5bee0..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-28 12:57+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" @@ -532,12 +532,8 @@ msgid "" "There was a payment related error. On close of this popup, you will be " "redirected back to the payment page." msgstr "" - -#, python-brace-format -msgid "" -"There was a payment related error.
Details: {error_detail}
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." From 00341e014ce1b30611c1efff8fa15d46c4bfeb26 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 22:02:53 +0200 Subject: [PATCH 27/37] Update hosting django.po --- hosting/locale/de/LC_MESSAGES/django.po | 38 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index c4c644f8..93494428 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-09-29 19:54+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,11 @@ 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 "" + msgid "CREATE VM" msgstr "NEUE VM" @@ -697,8 +711,9 @@ 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 "Kontaktiere den Data Center Light Support." msgid "Error terminating VM" msgstr "Fehler beenden VM" @@ -706,9 +721,6 @@ msgstr "Fehler beenden VM" msgid "Virtual Machine Cancellation" msgstr "VM Kündigung" -#~ msgid "Close" -#~ msgstr "Schliessen" - #~ msgid "VM %(VM_ID)s terminated successfully" #~ msgstr "VM %(VM_ID)s erfolgreich beendet" @@ -842,5 +854,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." From b04f9ea1ecb049ff28ee31bf25c311816984817f Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 22:12:02 +0200 Subject: [PATCH 28/37] Update hosting django.po --- hosting/locale/de/LC_MESSAGES/django.po | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index 93494428..a35cf5b5 100644 --- a/hosting/locale/de/LC_MESSAGES/django.po +++ b/hosting/locale/de/LC_MESSAGES/django.po @@ -629,6 +629,7 @@ msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\"" msgid "" "To access your VM, add your SSH key here" msgstr "" +"" msgid "CREATE VM" msgstr "NEUE VM" @@ -713,7 +714,9 @@ msgstr "Kontaktiere den Data Center Light Support." msgid "" "We could not find the requested VM. Please contact Data Center Light Support." -msgstr "Kontaktiere den Data Center Light Support." +msgstr "" +"Wir konnten die gesucht VM nicht fdnden. Kontaktiere den Data Center " +"Light Support." msgid "Error terminating VM" msgstr "Fehler beenden VM" From 43e6fc45e2c52672a910854f0b8359facdbeaf9c Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 22:19:26 +0200 Subject: [PATCH 29/37] Add de translations --- hosting/locale/de/LC_MESSAGES/django.po | 10 +++++----- hosting/templates/hosting/virtual_machines.html | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index a35cf5b5..f51e23f8 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-29 19:54+0000\n" +"POT-Creation-Date: 2017-09-29 20:14+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -627,9 +627,9 @@ msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\"" #, python-format msgid "" -"To access your VM, add your SSH key here" +"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" @@ -715,8 +715,8 @@ msgstr "Kontaktiere den Data Center Light Support." msgid "" "We could not find the requested VM. Please contact Data Center Light Support." msgstr "" -"Wir konnten die gesucht VM nicht fdnden. Kontaktiere den Data Center " -"Light Support." +"Wir konnten die gesucht VM nicht finden. Kontaktiere den Data Center Light " +"Support." msgid "Error terminating VM" msgstr "Fehler beenden VM" diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index aac241e3..6329cc10 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -16,7 +16,7 @@

{% trans 'To create a new virtual machine, click "Create VM"' %} {% if show_create_ssh_key_msg %} {% url 'hosting:create_ssh_key' as create_ssh_url %} -
{% blocktrans %}To access your VM, add your SSH key here{% endblocktrans %} +
{% blocktrans %}To access your VM, add your SSH key here{% endblocktrans %} {% endif %}

From 4334dfaa44cc70a98668aff2170ccd5af1f768a9 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Fri, 29 Sep 2017 22:36:38 +0200 Subject: [PATCH 30/37] Update utils django.po --- utils/locale/de/LC_MESSAGES/django.po | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/utils/locale/de/LC_MESSAGES/django.po b/utils/locale/de/LC_MESSAGES/django.po index f8374e4e..e8d6fd0c 100644 --- a/utils/locale/de/LC_MESSAGES/django.po +++ b/utils/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-25 20:11+0000\n" +"POT-Creation-Date: 2017-09-29 20:33+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -771,10 +771,13 @@ msgstr "" msgid "Country" msgstr "" -msgid "Street Building" +msgid "Name" msgstr "" -msgid "Name" +msgid "Email Address" +msgstr "" + +msgid "Street Building" msgstr "" msgid "Email" @@ -786,9 +789,9 @@ msgstr "Telefon" msgid "Message" msgstr "Nachricht" -msgid "An email with the activation link has been sent to your email" +msgid "An email with the activation link has been sent to you" msgstr "" -"Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet" +"Es wurde eine E-Mail mit dem Aktivierungslink an Dich gesendet." msgid "Account Activation" msgstr "Accountaktivierung" From 6ef8a03de70d90d952c4ee3b584624ccfca58dde Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sat, 30 Sep 2017 01:02:59 +0200 Subject: [PATCH 31/37] Respond with JSON --- hosting/views.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index ca215a4d..c39a2bcd 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -788,8 +788,19 @@ class OrdersHostingDetailView(LoginRequiredMixin, msg = subscription_result.get('error') messages.add_message(self.request, messages.ERROR, msg, extra_tags='failed_payment') - return HttpResponseRedirect( - reverse('hosting:payment') + '#payment_error') + response = { + 'status': False, + 'redirect': "{url}#{section}".format( + url=reverse('hosting:payment'), + section='payment_error'), + 'msg_title': str(_('Error.')), + 'msg_body': str( + _('There was a payment related error.' + ' On close of this popup, you will be redirected back to' + ' the payment page.')) + } + return HttpResponse(json.dumps(response), + content_type="application/json") user = { 'name': self.request.user.name, 'email': self.request.user.email, From 3a33dd2035818faf78a3f850504147c8428490af Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 1 Oct 2017 20:14:46 +0200 Subject: [PATCH 32/37] Add CSRF_FAILURE_VIEW --- dynamicweb/settings/base.py | 2 ++ 1 file changed, 2 insertions(+) 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 = [ From 9e8d930a3bab1c9ae7177002419dba11345788c3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 1 Oct 2017 20:16:05 +0200 Subject: [PATCH 33/37] Refactor messages to includes/_messages.html --- hosting/templates/hosting/includes/_messages.html | 8 ++++++++ hosting/templates/hosting/login.html | 8 +------- 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 hosting/templates/hosting/includes/_messages.html 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 %} From 167eaf2a0cffd6ac6d0e1775095129141fcbf35e Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 1 Oct 2017 20:17:03 +0200 Subject: [PATCH 34/37] Add forbidden_view method adds the message and redirects to the same path --- hosting/views.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hosting/views.py b/hosting/views.py index c39a2bcd..ae1efe2b 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1136,3 +1136,15 @@ class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, bill.total_price += vm['price'] context['vms'] = vms return context + + +def forbidden_view(request, exception=None, reason=''): + """ + Handle 403 error + """ + logger.error(str(exception) if exception else None) + all_messages = messages.get_messages(request) + messages.add_message(request, messages.ERROR, reason) + return HttpResponseRedirect( + request.get_full_path() + ) From 06b1ce9e7261ce8ca50e15e06e7990d04a8f5364 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 1 Oct 2017 20:32:51 +0200 Subject: [PATCH 35/37] Update error message --- hosting/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index ae1efe2b..77c7a108 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1143,8 +1143,9 @@ def forbidden_view(request, exception=None, reason=''): Handle 403 error """ logger.error(str(exception) if exception else None) - all_messages = messages.get_messages(request) - messages.add_message(request, messages.ERROR, reason) + err_msg = _('There was an error processing your request. Please try ' + 'again. Details: {reason}'.format(reason=reason)) + messages.add_message(request, messages.ERROR, err_msg) return HttpResponseRedirect( request.get_full_path() ) From cf45a9ac75c6878eee382e8a4862d73a7f3cb5d3 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 1 Oct 2017 20:39:40 +0200 Subject: [PATCH 36/37] Add messages to some hosting templates --- hosting/templates/hosting/resend_activation_link.html | 1 + hosting/templates/hosting/reset_password.html | 1 + hosting/templates/hosting/signup.html | 1 + hosting/templates/hosting/signup_validate.html | 1 + 4 files changed, 4 insertions(+) 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 @@