From d5d90e0790c70ca11c31a4402c61c9046ca93776 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 06:43:49 +0530 Subject: [PATCH 01/28] Add datacenterlight url: /add-ssh-key --- datacenterlight/urls.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/datacenterlight/urls.py b/datacenterlight/urls.py index 006e7fc3..d20366bf 100644 --- a/datacenterlight/urls.py +++ b/datacenterlight/urls.py @@ -3,10 +3,9 @@ from django.views.generic import TemplateView, RedirectView from .views import ( IndexView, PaymentOrderView, OrderConfirmationView, - WhyDataCenterLightView, ContactUsView + WhyDataCenterLightView, ContactUsView, AskSSHKeyView ) - urlpatterns = [ url(r'^$', IndexView.as_view(), name='index'), url(r'^t/$', IndexView.as_view(), name='index_t'), @@ -20,6 +19,8 @@ urlpatterns = [ url(r'^payment/?$', PaymentOrderView.as_view(), name='payment'), url(r'^order-confirmation/?$', OrderConfirmationView.as_view(), name='order_confirmation'), + url(r'^add-ssh-key/?$', AskSSHKeyView.as_view(), + name='add_ssh_key'), url(r'^contact/?$', ContactUsView.as_view(), name='contact_us'), url(r'glasfaser/?$', TemplateView.as_view(template_name='ungleich_page/glasfaser.html'), From f502e53845b32f7807ed3d71a52c45b826074272 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 06:45:48 +0530 Subject: [PATCH 02/28] Add basic implementation of AskSSHKeyView --- datacenterlight/views.py | 22 +++++++++++++++++++++- hosting/templates/hosting/user_key.html | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 76f50aec..d76303f7 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -523,13 +523,33 @@ class PaymentOrderView(FormView): else: request.session['customer'] = customer return HttpResponseRedirect( - reverse('datacenterlight:order_confirmation')) + reverse('datacenterlight:add_ssh_key')) else: context = self.get_context_data() context['billing_address_form'] = address_form return self.render_to_response(context) +class AskSSHKeyView(FormView): + form_class = UserHostingKeyForm + template_name = "datacenterlight/add_ssh_key.html" + + def get_form_kwargs(self): + kwargs = super(AskSSHKeyView, self).get_form_kwargs() + kwargs.update({'request': self.request}) + return kwargs + + @cache_control(no_cache=True, must_revalidate=True, no_store=True) + def get(self, request, *args, **kwargs): + context = { + 'site_url': reverse('datacenterlight:index'), + 'cms_integration': get_cms_integration('default'), + 'form': UserHostingKeyForm(request=self.request), + 'keys': get_all_public_keys(self.request.user) + } + return render(request, self.template_name, context) + + class OrderConfirmationView(DetailView, FormView): form_class = UserHostingKeyForm template_name = "datacenterlight/order_detail.html" diff --git a/hosting/templates/hosting/user_key.html b/hosting/templates/hosting/user_key.html index 804d661a..247551b5 100644 --- a/hosting/templates/hosting/user_key.html +++ b/hosting/templates/hosting/user_key.html @@ -8,7 +8,8 @@
{% csrf_token %} {% if messages %}
From b6eb72af7d389da94a5c853b3746258a503fdd3d Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:08:43 +0530 Subject: [PATCH 03/28] Refactor SSHKeyCreateView to utils Common between hosting/datacenterlight apps --- utils/views.py | 116 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/utils/views.py b/utils/views.py index 394a9fc2..93d778b4 100644 --- a/utils/views.py +++ b/utils/views.py @@ -1,16 +1,26 @@ +import uuid + from django.conf import settings from django.contrib import messages from django.contrib.auth import authenticate, login +from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.tokens import default_token_generator +from django.core.files.base import ContentFile from django.core.urlresolvers import reverse_lazy from django.http import HttpResponseRedirect +from django.shortcuts import render from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.translation import ugettext_lazy as _ -from django.views.generic import FormView, CreateView from django.views.decorators.cache import cache_control +from django.views.generic import FormView, CreateView +from datacenterlight.utils import get_cms_integration +from hosting.forms import UserHostingKeyForm +from hosting.models import UserHostingKey from membership.models import CustomUser +from opennebula_api.models import OpenNebulaManager +from utils.hosting_utils import get_all_public_keys from .forms import SetPasswordForm from .mailer import BaseEmail @@ -174,3 +184,107 @@ class PasswordResetConfirmViewMixin(FormView): form.add_error(None, _('The reset password link is no longer valid.')) return self.form_invalid(form) + + +class SSHKeyCreateView(LoginRequiredMixin, FormView): + form_class = UserHostingKeyForm + model = UserHostingKey + template_name = 'hosting/user_key.html' + login_url = reverse_lazy('hosting:login') + context_object_name = "virtual_machine" + success_url = reverse_lazy('hosting:ssh_keys') + + def get_form_kwargs(self): + kwargs = super(SSHKeyCreateView, self).get_form_kwargs() + kwargs.update({'request': self.request}) + return kwargs + + def form_valid(self, form): + form.save() + if settings.DCL_SSH_KEY_NAME_PREFIX in form.instance.name: + content = ContentFile(form.cleaned_data.get('private_key')) + filename = form.cleaned_data.get( + 'name') + '_' + str(uuid.uuid4())[:8] + '_private.pem' + form.instance.private_key.save(filename, content) + context = self.get_context_data() + + next_url = self.request.session.get( + 'next', + reverse_lazy('hosting:create_virtual_machine') + ) + + if 'next' in self.request.session: + context.update({ + 'next_url': next_url + }) + del (self.request.session['next']) + + if form.cleaned_data.get('private_key'): + context.update({ + 'private_key': form.cleaned_data.get('private_key'), + 'key_name': form.cleaned_data.get('name'), + 'form': UserHostingKeyForm(request=self.request), + }) + + owner = self.request.user + manager = OpenNebulaManager( + email=owner.email, + password=owner.password + ) + keys_to_save = get_all_public_keys(self.request.user) + manager.save_key_in_opennebula_user('\n'.join(keys_to_save)) + return HttpResponseRedirect(self.success_url) + + def post(self, request, *args, **kwargs): + form = self.get_form() + required = 'add_ssh' in self.request.POST + form.fields['name'].required = required + form.fields['public_key'].required = required + if form.is_valid(): + return self.form_valid(form) + else: + return self.form_invalid(form) + + +class AskSSHKeyView(SSHKeyCreateView): + form_class = UserHostingKeyForm + template_name = "datacenterlight/add_ssh_key.html" + success_url = reverse_lazy('datacenterlight:order_confirmation') + context_object_name = "dcl_vm_buy_add_ssh_key" + + @cache_control(no_cache=True, must_revalidate=True, no_store=True) + def get(self, request, *args, **kwargs): + context = { + 'site_url': reverse_lazy('datacenterlight:index'), + 'cms_integration': get_cms_integration('default'), + 'form': UserHostingKeyForm(request=self.request), + 'keys': get_all_public_keys(self.request.user) + } + return render(request, self.template_name, context) + # + # def post(self, request, *args, **kwargs): + # # Check ssh public key and then proceed + # form = self.get_form() + # required = True + # + # # SSH key validation is required only if the user doesn't have an + # # existing key and user has input some value in the add ssh key fields + # if (len(get_all_public_keys(self.request.user)) > 0 and + # (len(form.data.get('public_key')) == 0 and + # len(form.data.get('name')) == 0)): + # required = False + # form.fields['name'].required = required + # form.fields['public_key'].required = required + # if not form.is_valid(): + # response = { + # 'status': False, + # 'msg_title': str(_('SSH key related error occurred')), + # 'msg_body': "
".join([str(v) for k,v in form.errors.items()]), + # } + # return JsonResponse(response) + # + # if required: + # # We have a valid SSH key from the user, save it in opennebula and + # # db and proceed further + # form.save() + From 47fd9a8f28d85f580bad8947a0aea15435f70ce3 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:09:37 +0530 Subject: [PATCH 04/28] Adjust urls in datacenterlight/hosting apps urls/views after refactor --- datacenterlight/urls.py | 3 +- datacenterlight/views.py | 20 ------------- hosting/urls.py | 5 +++- hosting/views.py | 61 ---------------------------------------- 4 files changed, 6 insertions(+), 83 deletions(-) diff --git a/datacenterlight/urls.py b/datacenterlight/urls.py index d20366bf..13296de7 100644 --- a/datacenterlight/urls.py +++ b/datacenterlight/urls.py @@ -1,9 +1,10 @@ from django.conf.urls import url from django.views.generic import TemplateView, RedirectView +from utils.views import AskSSHKeyView from .views import ( IndexView, PaymentOrderView, OrderConfirmationView, - WhyDataCenterLightView, ContactUsView, AskSSHKeyView + WhyDataCenterLightView, ContactUsView ) urlpatterns = [ diff --git a/datacenterlight/views.py b/datacenterlight/views.py index d76303f7..99ceae8f 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -530,26 +530,6 @@ class PaymentOrderView(FormView): return self.render_to_response(context) -class AskSSHKeyView(FormView): - form_class = UserHostingKeyForm - template_name = "datacenterlight/add_ssh_key.html" - - def get_form_kwargs(self): - kwargs = super(AskSSHKeyView, self).get_form_kwargs() - kwargs.update({'request': self.request}) - return kwargs - - @cache_control(no_cache=True, must_revalidate=True, no_store=True) - def get(self, request, *args, **kwargs): - context = { - 'site_url': reverse('datacenterlight:index'), - 'cms_integration': get_cms_integration('default'), - 'form': UserHostingKeyForm(request=self.request), - 'keys': get_all_public_keys(self.request.user) - } - return render(request, self.template_name, context) - - class OrderConfirmationView(DetailView, FormView): form_class = UserHostingKeyForm template_name = "datacenterlight/order_detail.html" diff --git a/hosting/urls.py b/hosting/urls.py index 4779f67c..5b2b87b0 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -1,6 +1,7 @@ from django.conf.urls import url from django.contrib.auth import views as auth_views +from utils.views import SSHKeyCreateView, AskSSHKeyView from .views import ( DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView, LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView, @@ -8,7 +9,7 @@ from .views import ( VirtualMachinesPlanListView, VirtualMachineView, OrdersHostingDeleteView, MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView, CreateVirtualMachinesView, HostingBillListView, - HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, + HostingBillDetailView, SSHKeyDeleteView, SSHKeyListView, SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView, InvoiceListView, InvoiceDetailView, CheckUserVM ) @@ -27,6 +28,8 @@ urlpatterns = [ url(r'invoices/?$', InvoiceListView.as_view(), name='invoices'), url(r'order-confirmation/?$', OrdersHostingDetailView.as_view(), name='order-confirmation'), + url(r'^add-ssh-key/?$', AskSSHKeyView.as_view(), + name='add_ssh_key'), url(r'orders/(?P\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'), url(r'invoice/(?P[-\w]+)/?$', InvoiceDetailView.as_view(), diff --git a/hosting/views.py b/hosting/views.py index f5146fbf..97b7f42c 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -523,67 +523,6 @@ class SSHKeyChoiceView(LoginRequiredMixin, View): return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar') -@method_decorator(decorators, name='dispatch') -class SSHKeyCreateView(LoginRequiredMixin, FormView): - form_class = UserHostingKeyForm - model = UserHostingKey - template_name = 'hosting/user_key.html' - login_url = reverse_lazy('hosting:login') - context_object_name = "virtual_machine" - success_url = reverse_lazy('hosting:ssh_keys') - - def get_form_kwargs(self): - kwargs = super(SSHKeyCreateView, self).get_form_kwargs() - kwargs.update({'request': self.request}) - return kwargs - - def form_valid(self, form): - form.save() - if settings.DCL_SSH_KEY_NAME_PREFIX in form.instance.name: - content = ContentFile(form.cleaned_data.get('private_key')) - filename = form.cleaned_data.get( - 'name') + '_' + str(uuid.uuid4())[:8] + '_private.pem' - form.instance.private_key.save(filename, content) - context = self.get_context_data() - - next_url = self.request.session.get( - 'next', - reverse('hosting:create_virtual_machine') - ) - - if 'next' in self.request.session: - context.update({ - 'next_url': next_url - }) - del (self.request.session['next']) - - if form.cleaned_data.get('private_key'): - context.update({ - 'private_key': form.cleaned_data.get('private_key'), - 'key_name': form.cleaned_data.get('name'), - 'form': UserHostingKeyForm(request=self.request), - }) - - owner = self.request.user - manager = OpenNebulaManager( - email=owner.email, - password=owner.password - ) - keys_to_save = get_all_public_keys(self.request.user) - manager.save_key_in_opennebula_user('\n'.join(keys_to_save)) - return HttpResponseRedirect(self.success_url) - - def post(self, request, *args, **kwargs): - form = self.get_form() - required = 'add_ssh' in self.request.POST - form.fields['name'].required = required - form.fields['public_key'].required = required - if form.is_valid(): - return self.form_valid(form) - else: - return self.form_invalid(form) - - @method_decorator(decorators, name='dispatch') class SettingsView(LoginRequiredMixin, FormView): template_name = "hosting/settings.html" From 9b73fa71dc1c2018380523574717daf61a9a3e0c Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:10:37 +0530 Subject: [PATCH 05/28] Add datacenterlight add_ssh_key.html template file --- .../templates/datacenterlight/add_ssh_key.html | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 datacenterlight/templates/datacenterlight/add_ssh_key.html diff --git a/datacenterlight/templates/datacenterlight/add_ssh_key.html b/datacenterlight/templates/datacenterlight/add_ssh_key.html new file mode 100644 index 00000000..e083eece --- /dev/null +++ b/datacenterlight/templates/datacenterlight/add_ssh_key.html @@ -0,0 +1,8 @@ + +{% load staticfiles bootstrap3 i18n custom_tags humanize %} + +{% block content %} + {% block userkey_form %} + {% include 'hosting/user_key.html' with title="Your VM is almost ready!" sub_title="You just need to specify your public SSH key." %} + {% endblock userkey_form %} +{%endblock%} \ No newline at end of file From 5fcd0d6b18e08dc2bcc68b118f6d2d1347a42791 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:18:10 +0530 Subject: [PATCH 06/28] Remove add SSH key form in the order confirmation --- .../datacenterlight/order_detail.html | 32 ------------------- hosting/templates/hosting/order_detail.html | 29 ----------------- 2 files changed, 61 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html index e1cc5853..31933e12 100644 --- a/datacenterlight/templates/datacenterlight/order_detail.html +++ b/datacenterlight/templates/datacenterlight/order_detail.html @@ -134,38 +134,6 @@
{% csrf_token %} - {% if generic_payment_details %} - {% else %} - {% comment %} - We are in VM buy flow and we want user to click the "Place order" button. - At this point, we also want the user to input the SSH key for the VM. - {% endcomment %} - - {% if messages %} -
- {% for message in messages %} - {{ message }} - {% endfor %} -
- {% endif %} -
-

 {% trans "Add your public SSH key" %}

-
-
- {% if keys|length > 0 %} -
Existing keys
- {% endif %} - {% for key in keys %} - -
- {% endfor %} -
- {% for field in form %} - {% bootstrap_field field %} - {% endfor %} - {% endif %}
{% if generic_payment_details %} diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 7ab79378..4a62e9fa 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -198,35 +198,6 @@ {% block submit_btn %} {% csrf_token %} - {% comment %} - We are in VM buy flow and we want user to click the "Place order" button. - At this point, we also want the user to input the SSH key for the VM. - {% endcomment %} - - {% if messages %} -
- {% for message in messages %} - {{ message }} - {% endfor %} -
- {% endif %} -
-

 {% trans "Add your public SSH key" %}

-
-
- {% if keys|length > 0 %} -
Existing keys
- {% endif %} - {% for key in keys %} - -
- {% endfor %} -
- {% for field in form %} - {% bootstrap_field field %} - {% endfor %}
{% 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 %}.
From 79eba3b70c80c10d1f1a22713565d50ebd02a8e0 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:28:28 +0530 Subject: [PATCH 07/28] Remove add SSH key form in order confirmation related code --- datacenterlight/views.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 99ceae8f..28372a89 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -588,31 +588,6 @@ class OrderConfirmationView(DetailView, FormView): return render(request, self.template_name, context) def post(self, request, *args, **kwargs): - # Check ssh public key and then proceed - form = self.get_form() - required = True - - # SSH key validation is required only if the user doesn't have an - # existing key and user has input some value in the add ssh key fields - if (len(get_all_public_keys(self.request.user)) > 0 and - (len(form.data.get('public_key')) == 0 and - len(form.data.get('name')) == 0)): - required = False - form.fields['name'].required = required - form.fields['public_key'].required = required - if not form.is_valid(): - response = { - 'status': False, - 'msg_title': str(_('SSH key related error occurred')), - 'msg_body': "
".join([str(v) for k,v in form.errors.items()]), - } - return JsonResponse(response) - - if required: - # We have a valid SSH key from the user, save it in opennebula and - # db and proceed further - form.save() - user = request.session.get('user') stripe_api_cus_id = request.session.get('customer') stripe_utils = StripeUtils() From 2c74eae3f90dc049a15a1186fe007debfb657a5f Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:56:43 +0530 Subject: [PATCH 08/28] Remove commented code --- utils/views.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/utils/views.py b/utils/views.py index 93d778b4..00d97bbd 100644 --- a/utils/views.py +++ b/utils/views.py @@ -261,30 +261,4 @@ class AskSSHKeyView(SSHKeyCreateView): 'keys': get_all_public_keys(self.request.user) } return render(request, self.template_name, context) - # - # def post(self, request, *args, **kwargs): - # # Check ssh public key and then proceed - # form = self.get_form() - # required = True - # - # # SSH key validation is required only if the user doesn't have an - # # existing key and user has input some value in the add ssh key fields - # if (len(get_all_public_keys(self.request.user)) > 0 and - # (len(form.data.get('public_key')) == 0 and - # len(form.data.get('name')) == 0)): - # required = False - # form.fields['name'].required = required - # form.fields['public_key'].required = required - # if not form.is_valid(): - # response = { - # 'status': False, - # 'msg_title': str(_('SSH key related error occurred')), - # 'msg_body': "
".join([str(v) for k,v in form.errors.items()]), - # } - # return JsonResponse(response) - # - # if required: - # # We have a valid SSH key from the user, save it in opennebula and - # # db and proceed further - # form.save() From 207c3a6c6c7930b710eadb351e65b542c5dfc46b Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 08:57:39 +0530 Subject: [PATCH 09/28] Skip SSH key page for generic products page --- datacenterlight/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 28372a89..edc95ee9 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -522,6 +522,12 @@ class PaymentOrderView(FormView): request.session['customer'] = customer.stripe_id else: request.session['customer'] = customer + + # For generic payment we take the user directly to confirmation + if ('generic_payment_type' in request.session and + self.request.session['generic_payment_type'] == 'generic'): + return HttpResponseRedirect( + reverse('datacenterlight:order_confirmation')) return HttpResponseRedirect( reverse('datacenterlight:add_ssh_key')) else: From c35bc79c5c642e2ba6e590a7158c9c45efa24f6c Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 20:28:26 +0530 Subject: [PATCH 10/28] Set success_url based on flow: hosting vs landing --- utils/views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/views.py b/utils/views.py index 00d97bbd..e5eca845 100644 --- a/utils/views.py +++ b/utils/views.py @@ -262,3 +262,6 @@ class AskSSHKeyView(SSHKeyCreateView): } return render(request, self.template_name, context) + def post(self, request, *args, **kwargs): + self.success_url = self.request.get("order_confirm_url") + return super(AskSSHKeyView, self) \ No newline at end of file From c285e1d9eb8df95695bafe6c94e894338ed2ef0d Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 20:30:06 +0530 Subject: [PATCH 11/28] Set respective order_confirm_url for landing vs hosting flows For hosting flow also take the user to add_ssh_key after payment --- datacenterlight/views.py | 6 ++++-- hosting/views.py | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index edc95ee9..7b67acd5 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -528,8 +528,10 @@ class PaymentOrderView(FormView): self.request.session['generic_payment_type'] == 'generic'): return HttpResponseRedirect( reverse('datacenterlight:order_confirmation')) - return HttpResponseRedirect( - reverse('datacenterlight:add_ssh_key')) + else: + self.request.session['order_confirm_url'] = reverse('datacenterlight:order_confirmation') + return HttpResponseRedirect( + reverse('datacenterlight:add_ssh_key')) else: context = self.get_context_data() context['billing_address_form'] = address_form diff --git a/hosting/views.py b/hosting/views.py index 97b7f42c..9f7ce8cc 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -769,10 +769,10 @@ class PaymentVMView(LoginRequiredMixin, FormView): reverse('hosting:payment') + '#payment_error') request.session['token'] = token request.session['billing_address_data'] = billing_address_data - return HttpResponseRedirect("{url}?{query_params}".format( - url=reverse('hosting:order-confirmation'), - query_params='page=payment') - ) + self.request.session['order_confirm_url'] = "{url}?{query_params}".format( + url=reverse('hosting:order-confirmation'), + query_params='page=payment') + return HttpResponseRedirect(reverse('hosting:add_ssh_key')) else: return self.form_invalid(form) From d9a2c5216ce4afbd8031cfb6e165bef3f5725c66 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 20:30:35 +0530 Subject: [PATCH 12/28] Also remove order_confirm_url from session vars --- datacenterlight/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/datacenterlight/utils.py b/datacenterlight/utils.py index 208d39f3..4e56e812 100644 --- a/datacenterlight/utils.py +++ b/datacenterlight/utils.py @@ -1,8 +1,9 @@ import logging + import pyotp import requests -from django.contrib.sites.models import Site from django.conf import settings +from django.contrib.sites.models import Site from datacenterlight.tasks import create_vm_task from hosting.models import HostingOrder, HostingBill, OrderDetail @@ -99,7 +100,8 @@ def clear_all_session_vars(request): for session_var in ['specs', 'template', 'billing_address', 'billing_address_data', 'card_id', 'token', 'customer', 'generic_payment_type', - 'generic_payment_details', 'product_id']: + 'generic_payment_details', 'product_id', + 'order_confirm_url']: if session_var in request.session: del request.session[session_var] From c8c5bb763a9dd46adcfb79548cc41c4d1fad301e Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 20:36:13 +0530 Subject: [PATCH 13/28] Remove Add SSH key form in "Order Confirm" page related code (not needed) --- hosting/views.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index 9f7ce8cc..201d58e7 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -941,31 +941,6 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView): @method_decorator(decorators) def post(self, request): - # Check ssh public key and then proceed - form = self.get_form() - required = True - - # SSH key validation is required only if the user doesn't have an - # existing key and user has input some value in the add ssh key fields - if (len(get_all_public_keys(self.request.user)) > 0 and - (len(form.data.get('public_key')) == 0 and - len(form.data.get('name')) == 0)): - required = False - form.fields['name'].required = required - form.fields['public_key'].required = required - if not form.is_valid(): - response = { - 'status': False, - 'msg_title': str(_('SSH key related error occurred')), - 'msg_body': "
".join([str(v) for k,v in form.errors.items()]), - } - return JsonResponse(response) - - if required: - # We have a valid SSH key from the user, save it in opennebula and - # db and proceed further - form.save() - template = request.session.get('template') specs = request.session.get('specs') stripe_utils = StripeUtils() From 561178e473a78834e2552d103ceae856624ad887 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 20:48:34 +0530 Subject: [PATCH 14/28] Set success_url from session and call super post method --- utils/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/views.py b/utils/views.py index e5eca845..01f4968c 100644 --- a/utils/views.py +++ b/utils/views.py @@ -263,5 +263,5 @@ class AskSSHKeyView(SSHKeyCreateView): return render(request, self.template_name, context) def post(self, request, *args, **kwargs): - self.success_url = self.request.get("order_confirm_url") - return super(AskSSHKeyView, self) \ No newline at end of file + self.success_url = self.request.session.get("order_confirm_url") + return super(AskSSHKeyView, self).post(self, request, *args, **kwargs) \ No newline at end of file From 8efe978b23824cd44abb5eeefab1002d5b5f3b51 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 21:01:41 +0530 Subject: [PATCH 15/28] Don't make SSHKeyCreateView with LoginRequiredMixin --- utils/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/views.py b/utils/views.py index 01f4968c..0429c7db 100644 --- a/utils/views.py +++ b/utils/views.py @@ -3,7 +3,6 @@ import uuid from django.conf import settings from django.contrib import messages from django.contrib.auth import authenticate, login -from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.tokens import default_token_generator from django.core.files.base import ContentFile from django.core.urlresolvers import reverse_lazy @@ -186,7 +185,7 @@ class PasswordResetConfirmViewMixin(FormView): return self.form_invalid(form) -class SSHKeyCreateView(LoginRequiredMixin, FormView): +class SSHKeyCreateView(FormView): form_class = UserHostingKeyForm model = UserHostingKey template_name = 'hosting/user_key.html' From a20dbc1f960ba22a2e1d59a5c8335027800ac4fd Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 23:08:35 +0530 Subject: [PATCH 16/28] Cleanup new_user_hosting_key_id session variable also --- datacenterlight/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/utils.py b/datacenterlight/utils.py index 4e56e812..11d2b82e 100644 --- a/datacenterlight/utils.py +++ b/datacenterlight/utils.py @@ -101,7 +101,7 @@ def clear_all_session_vars(request): 'billing_address_data', 'card_id', 'token', 'customer', 'generic_payment_type', 'generic_payment_details', 'product_id', - 'order_confirm_url']: + 'order_confirm_url', 'new_user_hosting_key_id']: if session_var in request.session: del request.session[session_var] From 670c2b18a903ade0f4e0ccc11d7355658de047e2 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 23:09:42 +0530 Subject: [PATCH 17/28] Set user_hosting_key's user to the newly created user --- datacenterlight/views.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 7b67acd5..22294432 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -17,9 +17,10 @@ from hosting.forms import ( UserHostingKeyForm ) from hosting.models import ( - HostingBill, HostingOrder, UserCardDetail, GenericProduct + HostingBill, HostingOrder, UserCardDetail, GenericProduct, UserHostingKey ) from membership.models import CustomUser, StripeCustomer +from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VMTemplateSerializer from utils.forms import ( BillingAddressForm, BillingAddressFormSignup, UserBillingAddressForm, @@ -847,6 +848,18 @@ class OrderConfirmationView(DetailView, FormView): new_user = authenticate(username=custom_user.email, password=password) login(request, new_user) + if 'new_user_hosting_key_id' in self.request.session: + user_hosting_key = UserHostingKey.objects.get(self.request.session['new_user_hosting_key_id']) + user_hosting_key.user = new_user + user_hosting_key.save() + + owner = new_user + manager = OpenNebulaManager( + email=owner.email, + password=owner.password + ) + keys_to_save = get_all_public_keys(new_user) + manager.save_key_in_opennebula_user('\n'.join(keys_to_save)) else: # We assume that if the user is here, his/her StripeCustomer # object already exists From 32de20aaba11e1899916525db437176ed7ac2292 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 23:11:14 +0530 Subject: [PATCH 18/28] Set unon authenticated user to NONE --- hosting/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/forms.py b/hosting/forms.py index 797bc700..1bc99b8f 100644 --- a/hosting/forms.py +++ b/hosting/forms.py @@ -222,7 +222,7 @@ class UserHostingKeyForm(forms.ModelForm): return self.data.get('name') def clean_user(self): - return self.request.user + return self.request.user if self.request.user.is_authenticated() else None def clean(self): cleaned_data = self.cleaned_data From ddaa3206285b5cf5aa422efb08030568c2bc85e5 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 23:11:49 +0530 Subject: [PATCH 19/28] Set user foreign key to be blank allowing null values --- hosting/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hosting/models.py b/hosting/models.py index aead430c..311ee953 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -1,11 +1,11 @@ import json import logging import os -import pytz +from datetime import datetime +import pytz from Crypto.PublicKey import RSA from dateutil.relativedelta import relativedelta -from datetime import datetime from django.db import models from django.utils import timezone from django.utils.functional import cached_property @@ -187,7 +187,7 @@ class HostingOrder(AssignPermissionsMixin, models.Model): class UserHostingKey(models.Model): - user = models.ForeignKey(CustomUser) + user = models.ForeignKey(CustomUser, blank=True, null=True) public_key = models.TextField() private_key = models.FileField(upload_to='private_keys', blank=True) created_at = models.DateTimeField(auto_now_add=True) From 26fab27c3fb476c255b02f5fec343d2e2d31d9e7 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 1 Jul 2019 23:17:27 +0530 Subject: [PATCH 20/28] Set new_user_hosting_key_id session variable to track newly created key --- utils/views.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/utils/views.py b/utils/views.py index 0429c7db..05d0fdc2 100644 --- a/utils/views.py +++ b/utils/views.py @@ -225,13 +225,16 @@ class SSHKeyCreateView(FormView): 'form': UserHostingKeyForm(request=self.request), }) - owner = self.request.user - manager = OpenNebulaManager( - email=owner.email, - password=owner.password - ) - keys_to_save = get_all_public_keys(self.request.user) - manager.save_key_in_opennebula_user('\n'.join(keys_to_save)) + if self.request.user.is_authenticated(): + owner = self.request.user + manager = OpenNebulaManager( + email=owner.email, + password=owner.password + ) + keys_to_save = get_all_public_keys(self.request.user) + manager.save_key_in_opennebula_user('\n'.join(keys_to_save)) + else: + self.request.session["new_user_hosting_key_id"] = form.instance.id return HttpResponseRedirect(self.success_url) def post(self, request, *args, **kwargs): From dfb16f0c25d0ca9b880efc14467c4d234d905055 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 05:13:02 +0530 Subject: [PATCH 21/28] Save new user's hosting key only in that case --- datacenterlight/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 22294432..3763d465 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -848,10 +848,10 @@ class OrderConfirmationView(DetailView, FormView): new_user = authenticate(username=custom_user.email, password=password) login(request, new_user) - if 'new_user_hosting_key_id' in self.request.session: - user_hosting_key = UserHostingKey.objects.get(self.request.session['new_user_hosting_key_id']) - user_hosting_key.user = new_user - user_hosting_key.save() + if 'new_user_hosting_key_id' in self.request.session: + user_hosting_key = UserHostingKey.objects.get(id=self.request.session['new_user_hosting_key_id']) + user_hosting_key.user = new_user + user_hosting_key.save() owner = new_user manager = OpenNebulaManager( From 921d832f9e9ab553771f3874778174e77ce07b80 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 06:44:31 +0530 Subject: [PATCH 22/28] Make user in UserHostingKey model nullable --- hosting/migrations/0055_auto_20190701_1614.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 hosting/migrations/0055_auto_20190701_1614.py diff --git a/hosting/migrations/0055_auto_20190701_1614.py b/hosting/migrations/0055_auto_20190701_1614.py new file mode 100644 index 00000000..4a2744fb --- /dev/null +++ b/hosting/migrations/0055_auto_20190701_1614.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2019-07-01 16:14 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('hosting', '0054_auto_20190508_2141'), + ] + + operations = [ + migrations.AlterField( + model_name='userhostingkey', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] From 44921014a21d074e9e2510186004d252e278336d Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 07:09:44 +0530 Subject: [PATCH 23/28] Get the correct opennebula user id --- opennebula_api/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 478758fc..f8ef6481 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -376,7 +376,7 @@ class OpenNebulaManager(): """ return_value = self.oneadmin_client.call( 'user.update', - self.opennebula_user.id, + self.opennebula_user if type(self.opennebula_user) == int else self.opennebula_user.id, '%s' % ssh_key, update_type ) From 6f49157ddd81522982f70ede42afe604d22d8411 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 16:27:12 +0530 Subject: [PATCH 24/28] Update add_ssh_key subtitle --- datacenterlight/templates/datacenterlight/add_ssh_key.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/add_ssh_key.html b/datacenterlight/templates/datacenterlight/add_ssh_key.html index e083eece..936bd782 100644 --- a/datacenterlight/templates/datacenterlight/add_ssh_key.html +++ b/datacenterlight/templates/datacenterlight/add_ssh_key.html @@ -3,6 +3,6 @@ {% block content %} {% block userkey_form %} - {% include 'hosting/user_key.html' with title="Your VM is almost ready!" sub_title="You just need to specify your public SSH key." %} + {% include 'hosting/user_key.html' with title="Your VM is almost ready!" sub_title="You need to specify your public SSH key to access your VM. You can either add your existing key, or generate a new key pair by clicking the generate button below. After choosing your public SSH key option you’ll be directed to the order confirmation page." %} {% endblock userkey_form %} {%endblock%} \ No newline at end of file From b0548f4cfa3f4d5b3fa9c86188ed4eae4eeec5c0 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 16:51:29 +0530 Subject: [PATCH 25/28] Translate ssh key form title and subtitles --- datacenterlight/templates/datacenterlight/add_ssh_key.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/add_ssh_key.html b/datacenterlight/templates/datacenterlight/add_ssh_key.html index 936bd782..44048bad 100644 --- a/datacenterlight/templates/datacenterlight/add_ssh_key.html +++ b/datacenterlight/templates/datacenterlight/add_ssh_key.html @@ -3,6 +3,8 @@ {% block content %} {% block userkey_form %} - {% include 'hosting/user_key.html' with title="Your VM is almost ready!" sub_title="You need to specify your public SSH key to access your VM. You can either add your existing key, or generate a new key pair by clicking the generate button below. After choosing your public SSH key option you’ll be directed to the order confirmation page." %} + {% with form_title=_("Your VM is almost ready!") form_sub_title=_("You need to specify your public SSH key to access your VM. You can either add your existing key, or generate a new key pair by clicking the generate button below. After choosing your public SSH key option you’ll be directed to the order confirmation page.") %} + {% include 'hosting/user_key.html' with title=form_title sub_title=form_sub_title %} + {% endwith %} {% endblock userkey_form %} {%endblock%} \ No newline at end of file From 69401a1cc6ee6cca7417b15de47afd38f81f3b3b Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 16:52:08 +0530 Subject: [PATCH 26/28] Make messages for datacenterlight and add some DE translations --- .../locale/de/LC_MESSAGES/django.po | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index d43e91ea..d6a25b53 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: 2018-09-26 20:44+0000\n" +"POT-Creation-Date: 2019-07-03 11:18+0000\n" "PO-Revision-Date: 2018-03-30 23:22+0000\n" "Last-Translator: b'Anonymous User '\n" "Language-Team: LANGUAGE \n" @@ -26,6 +26,22 @@ msgstr "" msgid "Your New VM %(vm_name)s at Data Center Light" msgstr "Deine neue VM %(vm_name)s bei Data Center Light" +msgid "Your VM is almost ready!" +msgstr "" + +msgid "" +"You need to specify your public SSH key to access your VM. You can either " +"add your existing key, or generate a new key pair by clicking the generate " +"button below. After choosing your public SSH key option you’ll be directed " +"to the order confirmation page." +msgstr "" +"Du musst deinen öffentlichen SSH-Schlüssel angeben, um auf deine VM " +"zugreifen zu können. Du kannst entweder deinen vorhandenen Schlüssel " +"hinzufügen oder ein neues Schlüsselpaar generieren, indem du auf die " +"Schaltfläche \"Generieren\" unten klickst. Nachdem du deine öffentliche SSH-" +"Schlüsseloption ausgewählt hast, wirst du zur Bestellbestätigungsseite " +"weitergeleitet. " + msgid "All Rights Reserved" msgstr "Alle Rechte vorbehalten" @@ -134,6 +150,10 @@ msgstr "Unser Angebot beginnt bei 15 CHF pro Monat. Probier's jetzt aus!" msgid "ORDER VM" msgstr "VM BESTELLEN" +#, python-format +msgid "Please enter a value in range %(min_ram)s - 200." +msgstr "Bitte gib einen Wert von %(min_ram)s bis 200 ein." + msgid "VM hosting" msgstr "" @@ -152,9 +172,6 @@ msgstr "Standort: Schweiz" msgid "Please enter a value in range 1 - 48." msgstr "Bitte gib einen Wert von 1 bis 48 ein." -msgid "Please enter a value in range 1 - 200." -msgstr "Bitte gib einen Wert von 1 bis 200 ein." - msgid "Please enter a value in range 10 - 2000." msgstr "Bitte gib einen Wert von 10 bis 2000 ein." @@ -413,6 +430,10 @@ msgstr "Zwischensumme" msgid "VAT" msgstr "Mehrwertsteuer" +#, fuzzy, python-format +#| msgid "" +#| "By clicking \"Place order\" this plan will charge your credit card " +#| "account with %(total_price)s CHF/month" msgid "" "By clicking \"Place order\" this plan will charge your credit card account " "with %(total_price)s CHF/month" @@ -420,6 +441,10 @@ msgstr "" "Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit " "%(vm_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" @@ -535,6 +560,9 @@ msgstr "Tagen sagen mehr als Worte – Teste jetzt unsere VM!" msgid "Invalid number of cores" msgstr "Ungültige Anzahle CPU-Kerne" +msgid "Invalid calculator properties" +msgstr "" + msgid "Invalid RAM size" msgstr "Ungültige RAM-Grösse" From 2a4fb8c8dee0372a9e547c016ff1e57b183eb6d3 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 16:57:00 +0530 Subject: [PATCH 27/28] Add DE translation Your VM is almost ready! => Ihre VM ist fast fertig! --- datacenterlight/locale/de/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index d6a25b53..07361e29 100644 --- a/datacenterlight/locale/de/LC_MESSAGES/django.po +++ b/datacenterlight/locale/de/LC_MESSAGES/django.po @@ -27,7 +27,7 @@ msgid "Your New VM %(vm_name)s at Data Center Light" msgstr "Deine neue VM %(vm_name)s bei Data Center Light" msgid "Your VM is almost ready!" -msgstr "" +msgstr "Ihre VM ist fast fertig!" msgid "" "You need to specify your public SSH key to access your VM. You can either " From d3e2074b1616020debbb7cca69b3fe709ddb19cc Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 3 Jul 2019 17:29:42 +0530 Subject: [PATCH 28/28] Update DE translation Your VM is almost ready! => Deine VM ist fast fertig! --- datacenterlight/locale/de/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index 07361e29..b5ff3ca5 100644 --- a/datacenterlight/locale/de/LC_MESSAGES/django.po +++ b/datacenterlight/locale/de/LC_MESSAGES/django.po @@ -27,7 +27,7 @@ msgid "Your New VM %(vm_name)s at Data Center Light" msgstr "Deine neue VM %(vm_name)s bei Data Center Light" msgid "Your VM is almost ready!" -msgstr "Ihre VM ist fast fertig!" +msgstr "Deine VM ist fast fertig!" msgid "" "You need to specify your public SSH key to access your VM. You can either "