Merge branch 'master' into feature/6561/invoices-webhook
This commit is contained in:
commit
8300babead
23 changed files with 434 additions and 252 deletions
|
|
@ -1,3 +1,7 @@
|
||||||
|
2.6.1: 2019-07-09
|
||||||
|
* #6941: [hosting dashboard] Show the card's expiry year & month too in the list of added cards (MR!710)
|
||||||
|
2.6: 2019-07-03
|
||||||
|
* #5509: Getting rid of our key by still supporting multiple user keys (MR!709)
|
||||||
2.5.11: 2019-06-11
|
2.5.11: 2019-06-11
|
||||||
* #6672: [api] Check VM belongs to user in the infrastructure directly (MR!707)
|
* #6672: [api] Check VM belongs to user in the infrastructure directly (MR!707)
|
||||||
* #bugfix: DE translation fix "Learn mehr" -> "Lerne mehr" (MR!708)
|
* #bugfix: DE translation fix "Learn mehr" -> "Lerne mehr" (MR!708)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2018-03-30 23:22+0000\n"
|
||||||
"Last-Translator: b'Anonymous User <coder.purple+25@gmail.com>'\n"
|
"Last-Translator: b'Anonymous User <coder.purple+25@gmail.com>'\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -26,6 +26,22 @@ msgstr ""
|
||||||
msgid "Your New VM %(vm_name)s at Data Center Light"
|
msgid "Your New VM %(vm_name)s at Data Center Light"
|
||||||
msgstr "Deine neue VM %(vm_name)s bei Data Center Light"
|
msgstr "Deine neue VM %(vm_name)s bei Data Center Light"
|
||||||
|
|
||||||
|
msgid "Your VM is almost ready!"
|
||||||
|
msgstr "Deine VM ist fast fertig!"
|
||||||
|
|
||||||
|
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"
|
msgid "All Rights Reserved"
|
||||||
msgstr "Alle Rechte vorbehalten"
|
msgstr "Alle Rechte vorbehalten"
|
||||||
|
|
||||||
|
|
@ -134,6 +150,10 @@ msgstr "Unser Angebot beginnt bei 15 CHF pro Monat. Probier's jetzt aus!"
|
||||||
msgid "ORDER VM"
|
msgid "ORDER VM"
|
||||||
msgstr "VM BESTELLEN"
|
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"
|
msgid "VM hosting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -152,9 +172,6 @@ msgstr "Standort: Schweiz"
|
||||||
msgid "Please enter a value in range 1 - 48."
|
msgid "Please enter a value in range 1 - 48."
|
||||||
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
|
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."
|
msgid "Please enter a value in range 10 - 2000."
|
||||||
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
|
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
|
||||||
|
|
||||||
|
|
@ -413,6 +430,10 @@ msgstr "Zwischensumme"
|
||||||
msgid "VAT"
|
msgid "VAT"
|
||||||
msgstr "Mehrwertsteuer"
|
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 ""
|
msgid ""
|
||||||
"By clicking \"Place order\" this plan will charge your credit card account "
|
"By clicking \"Place order\" this plan will charge your credit card account "
|
||||||
"with %(total_price)s CHF/month"
|
"with %(total_price)s CHF/month"
|
||||||
|
|
@ -420,6 +441,10 @@ msgstr ""
|
||||||
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
|
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
|
||||||
"%(vm_total_price)s CHF pro Monat belastet"
|
"%(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 ""
|
msgid ""
|
||||||
"By clicking \"Place order\" this payment will charge your credit card "
|
"By clicking \"Place order\" this payment will charge your credit card "
|
||||||
"account with a one time amount of %(total_price)s CHF"
|
"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"
|
msgid "Invalid number of cores"
|
||||||
msgstr "Ungültige Anzahle CPU-Kerne"
|
msgstr "Ungültige Anzahle CPU-Kerne"
|
||||||
|
|
||||||
|
msgid "Invalid calculator properties"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid RAM size"
|
msgid "Invalid RAM size"
|
||||||
msgstr "Ungültige RAM-Grösse"
|
msgstr "Ungültige RAM-Grösse"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -186,3 +186,8 @@ footer .dcl-link-separator::before {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.existing-keys-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ from django.core.mail import EmailMessage
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
from dynamicweb.celery import app
|
from dynamicweb.celery import app
|
||||||
from hosting.models import HostingOrder
|
from hosting.models import HostingOrder
|
||||||
|
|
@ -16,7 +15,7 @@ from membership.models import CustomUser
|
||||||
from opennebula_api.models import OpenNebulaManager
|
from opennebula_api.models import OpenNebulaManager
|
||||||
from opennebula_api.serializers import VirtualMachineSerializer
|
from opennebula_api.serializers import VirtualMachineSerializer
|
||||||
from utils.hosting_utils import (
|
from utils.hosting_utils import (
|
||||||
get_all_public_keys, get_or_create_vm_detail, ping_ok
|
get_all_public_keys, get_or_create_vm_detail
|
||||||
)
|
)
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
|
|
@ -79,10 +78,14 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
|
||||||
# Create OpenNebulaManager
|
# Create OpenNebulaManager
|
||||||
manager = OpenNebulaManager(email=on_user, password=on_pass)
|
manager = OpenNebulaManager(email=on_user, password=on_pass)
|
||||||
|
|
||||||
|
custom_user = CustomUser.objects.get(email=user.get('email'))
|
||||||
|
pub_keys = get_all_public_keys(custom_user)
|
||||||
|
if manager.email != settings.OPENNEBULA_USERNAME:
|
||||||
|
manager.save_key_in_opennebula_user('\n'.join(pub_keys))
|
||||||
vm_id = manager.create_vm(
|
vm_id = manager.create_vm(
|
||||||
template_id=vm_template_id,
|
template_id=vm_template_id,
|
||||||
specs=specs,
|
specs=specs,
|
||||||
ssh_key=settings.ONEADMIN_USER_SSH_PUBLIC_KEY,
|
ssh_key='\n'.join(pub_keys),
|
||||||
vm_name=vm_name
|
vm_name=vm_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -188,65 +191,9 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
|
||||||
email = BaseEmail(**email_data)
|
email = BaseEmail(**email_data)
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
# try to see if we have the IPv6 of the new vm and that if the ssh
|
|
||||||
# keys can be configured
|
|
||||||
vm_ipv6 = manager.get_ipv6(vm_id)
|
|
||||||
logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
|
logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
|
||||||
if vm_ipv6 is not None:
|
if vm_id > 0:
|
||||||
custom_user = CustomUser.objects.get(email=user.get('email'))
|
|
||||||
get_or_create_vm_detail(custom_user, manager, vm_id)
|
get_or_create_vm_detail(custom_user, manager, vm_id)
|
||||||
if custom_user is not None:
|
|
||||||
public_keys = get_all_public_keys(custom_user)
|
|
||||||
keys = [{'value': key, 'state': True} for key in
|
|
||||||
public_keys]
|
|
||||||
if len(keys) > 0:
|
|
||||||
logger.debug(
|
|
||||||
"Calling configure on {host} for "
|
|
||||||
"{num_keys} keys".format(
|
|
||||||
host=vm_ipv6, num_keys=len(keys)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# Let's wait until the IP responds to ping before we
|
|
||||||
# run the cdist configure on the host
|
|
||||||
did_manage_public_key = False
|
|
||||||
for i in range(0, 15):
|
|
||||||
if ping_ok(vm_ipv6):
|
|
||||||
logger.debug(
|
|
||||||
"{} is pingable. Doing a "
|
|
||||||
"manage_public_key".format(vm_ipv6)
|
|
||||||
)
|
|
||||||
sleep(10)
|
|
||||||
manager.manage_public_key(
|
|
||||||
keys, hosts=[vm_ipv6]
|
|
||||||
)
|
|
||||||
did_manage_public_key = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
logger.debug(
|
|
||||||
"Can't ping {}. Wait 5 secs".format(
|
|
||||||
vm_ipv6
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sleep(5)
|
|
||||||
if not did_manage_public_key:
|
|
||||||
emsg = ("Waited for over 75 seconds for {} to be "
|
|
||||||
"pingable. But the VM was not reachable. "
|
|
||||||
"So, gave up manage_public_key. Please do "
|
|
||||||
"this manually".format(vm_ipv6))
|
|
||||||
logger.error(emsg)
|
|
||||||
email_data = {
|
|
||||||
'subject': '{} CELERY TASK INCOMPLETE: {} not '
|
|
||||||
'pingable for 75 seconds'.format(
|
|
||||||
settings.DCL_TEXT, vm_ipv6
|
|
||||||
),
|
|
||||||
'from_email': current_task.request.hostname,
|
|
||||||
'to': settings.DCL_ERROR_EMAILS_TO_LIST,
|
|
||||||
'body': emsg
|
|
||||||
}
|
|
||||||
email = EmailMessage(**email_data)
|
|
||||||
email.send()
|
|
||||||
else:
|
|
||||||
logger.debug("VM's ipv6 is None. Hence not created VMDetail")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(str(e))
|
logger.error(str(e))
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
10
datacenterlight/templates/datacenterlight/add_ssh_key.html
Normal file
10
datacenterlight/templates/datacenterlight/add_ssh_key.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
{% load staticfiles bootstrap3 i18n custom_tags humanize %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% block userkey_form %}
|
||||||
|
{% 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%}
|
||||||
|
|
@ -131,6 +131,7 @@
|
||||||
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
||||||
|
<h5 class="membership-lead">{% trans "Expiry" %}: {{card.exp_month}}/{{card.exp_year}}</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 text-right align-bottom">
|
<div class="col-xs-6 text-right align-bottom">
|
||||||
<a class="btn choice-btn choice-btn-faded" href="#" data-id_card="{{card.id}}">{% trans "SELECT" %}</a>
|
<a class="btn choice-btn choice-btn-faded" href="#" data-id_card="{{card.id}}">{% trans "SELECT" %}</a>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
<h4>{% trans "Payment method" %}:</h4>
|
<h4>{% trans "Payment method" %}:</h4>
|
||||||
<p>
|
<p>
|
||||||
{{cc_brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{cc_last4}}<br>
|
{{cc_brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{cc_last4}}<br>
|
||||||
|
{% trans "Expiry" %} {{cc_exp_year}}/{{cc_exp_month}}<br/>
|
||||||
{{request.user.email}}
|
{{request.user.email}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.views.generic import TemplateView, RedirectView
|
from django.views.generic import TemplateView, RedirectView
|
||||||
|
|
||||||
|
from utils.views import AskSSHKeyView
|
||||||
from .views import (
|
from .views import (
|
||||||
IndexView, PaymentOrderView, OrderConfirmationView,
|
IndexView, PaymentOrderView, OrderConfirmationView,
|
||||||
WhyDataCenterLightView, ContactUsView
|
WhyDataCenterLightView, ContactUsView
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', IndexView.as_view(), name='index'),
|
url(r'^$', IndexView.as_view(), name='index'),
|
||||||
url(r'^t/$', IndexView.as_view(), name='index_t'),
|
url(r'^t/$', IndexView.as_view(), name='index_t'),
|
||||||
|
|
@ -20,6 +20,8 @@ urlpatterns = [
|
||||||
url(r'^payment/?$', PaymentOrderView.as_view(), name='payment'),
|
url(r'^payment/?$', PaymentOrderView.as_view(), name='payment'),
|
||||||
url(r'^order-confirmation/?$', OrderConfirmationView.as_view(),
|
url(r'^order-confirmation/?$', OrderConfirmationView.as_view(),
|
||||||
name='order_confirmation'),
|
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'^contact/?$', ContactUsView.as_view(), name='contact_us'),
|
||||||
url(r'glasfaser/?$',
|
url(r'glasfaser/?$',
|
||||||
TemplateView.as_view(template_name='ungleich_page/glasfaser.html'),
|
TemplateView.as_view(template_name='ungleich_page/glasfaser.html'),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pyotp
|
import pyotp
|
||||||
import requests
|
import requests
|
||||||
from django.contrib.sites.models import Site
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
|
||||||
from datacenterlight.tasks import create_vm_task
|
from datacenterlight.tasks import create_vm_task
|
||||||
from hosting.models import HostingOrder, HostingBill, OrderDetail
|
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',
|
for session_var in ['specs', 'template', 'billing_address',
|
||||||
'billing_address_data', 'card_id',
|
'billing_address_data', 'card_id',
|
||||||
'token', 'customer', 'generic_payment_type',
|
'token', 'customer', 'generic_payment_type',
|
||||||
'generic_payment_details', 'product_id']:
|
'generic_payment_details', 'product_id',
|
||||||
|
'order_confirm_url', 'new_user_hosting_key_id']:
|
||||||
if session_var in request.session:
|
if session_var in request.session:
|
||||||
del request.session[session_var]
|
del request.session[session_var]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,20 @@ from django.views.decorators.cache import cache_control
|
||||||
from django.views.generic import FormView, CreateView, DetailView
|
from django.views.generic import FormView, CreateView, DetailView
|
||||||
|
|
||||||
from hosting.forms import (
|
from hosting.forms import (
|
||||||
HostingUserLoginForm, GenericPaymentForm, ProductPaymentForm
|
HostingUserLoginForm, GenericPaymentForm, ProductPaymentForm,
|
||||||
|
UserHostingKeyForm
|
||||||
)
|
)
|
||||||
from hosting.models import (
|
from hosting.models import (
|
||||||
HostingBill, HostingOrder, UserCardDetail, GenericProduct
|
HostingBill, HostingOrder, UserCardDetail, GenericProduct, UserHostingKey
|
||||||
)
|
)
|
||||||
from membership.models import CustomUser, StripeCustomer
|
from membership.models import CustomUser, StripeCustomer
|
||||||
|
from opennebula_api.models import OpenNebulaManager
|
||||||
from opennebula_api.serializers import VMTemplateSerializer
|
from opennebula_api.serializers import VMTemplateSerializer
|
||||||
from utils.forms import (
|
from utils.forms import (
|
||||||
BillingAddressForm, BillingAddressFormSignup, UserBillingAddressForm,
|
BillingAddressForm, BillingAddressFormSignup, UserBillingAddressForm,
|
||||||
BillingAddress
|
BillingAddress
|
||||||
)
|
)
|
||||||
from utils.hosting_utils import get_vm_price_with_vat
|
from utils.hosting_utils import get_vm_price_with_vat, get_all_public_keys
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
from utils.tasks import send_plain_email_task
|
from utils.tasks import send_plain_email_task
|
||||||
from .cms_models import DCLCalculatorPluginModel
|
from .cms_models import DCLCalculatorPluginModel
|
||||||
|
|
@ -521,20 +523,34 @@ class PaymentOrderView(FormView):
|
||||||
request.session['customer'] = customer.stripe_id
|
request.session['customer'] = customer.stripe_id
|
||||||
else:
|
else:
|
||||||
request.session['customer'] = customer
|
request.session['customer'] = customer
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse('datacenterlight:order_confirmation'))
|
# 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'))
|
||||||
|
else:
|
||||||
|
self.request.session['order_confirm_url'] = reverse('datacenterlight:order_confirmation')
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse('datacenterlight:add_ssh_key'))
|
||||||
else:
|
else:
|
||||||
context = self.get_context_data()
|
context = self.get_context_data()
|
||||||
context['billing_address_form'] = address_form
|
context['billing_address_form'] = address_form
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
|
|
||||||
|
|
||||||
class OrderConfirmationView(DetailView):
|
class OrderConfirmationView(DetailView, FormView):
|
||||||
|
form_class = UserHostingKeyForm
|
||||||
template_name = "datacenterlight/order_detail.html"
|
template_name = "datacenterlight/order_detail.html"
|
||||||
payment_template_name = 'datacenterlight/landing_payment.html'
|
payment_template_name = 'datacenterlight/landing_payment.html'
|
||||||
context_object_name = "order"
|
context_object_name = "order"
|
||||||
model = HostingOrder
|
model = HostingOrder
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
kwargs = super(OrderConfirmationView, self).get_form_kwargs()
|
||||||
|
kwargs.update({'request': self.request})
|
||||||
|
return kwargs
|
||||||
|
|
||||||
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
|
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
context = {}
|
context = {}
|
||||||
|
|
@ -552,11 +568,15 @@ class OrderConfirmationView(DetailView):
|
||||||
card_details_response = card_details['response_object']
|
card_details_response = card_details['response_object']
|
||||||
context['cc_last4'] = card_details_response['last4']
|
context['cc_last4'] = card_details_response['last4']
|
||||||
context['cc_brand'] = card_details_response['brand']
|
context['cc_brand'] = card_details_response['brand']
|
||||||
|
context['cc_exp_year'] = card_details_response['exp_year']
|
||||||
|
context['cc_exp_month'] = '{:02d}'.format(card_details_response['exp_month'])
|
||||||
else:
|
else:
|
||||||
card_id = self.request.session.get('card_id')
|
card_id = self.request.session.get('card_id')
|
||||||
card_detail = UserCardDetail.objects.get(id=card_id)
|
card_detail = UserCardDetail.objects.get(id=card_id)
|
||||||
context['cc_last4'] = card_detail.last4
|
context['cc_last4'] = card_detail.last4
|
||||||
context['cc_brand'] = card_detail.brand
|
context['cc_brand'] = card_detail.brand
|
||||||
|
context['cc_exp_year'] = card_detail.exp_year
|
||||||
|
context['cc_exp_month'] ='{:02d}'.format(card_detail.exp_month)
|
||||||
|
|
||||||
if ('generic_payment_type' in request.session and
|
if ('generic_payment_type' in request.session and
|
||||||
self.request.session['generic_payment_type'] == 'generic'):
|
self.request.session['generic_payment_type'] == 'generic'):
|
||||||
|
|
@ -567,6 +587,8 @@ class OrderConfirmationView(DetailView):
|
||||||
else:
|
else:
|
||||||
context.update({
|
context.update({
|
||||||
'vm': request.session.get('specs'),
|
'vm': request.session.get('specs'),
|
||||||
|
'form': UserHostingKeyForm(request=self.request),
|
||||||
|
'keys': get_all_public_keys(self.request.user)
|
||||||
})
|
})
|
||||||
context.update({
|
context.update({
|
||||||
'site_url': reverse('datacenterlight:index'),
|
'site_url': reverse('datacenterlight:index'),
|
||||||
|
|
@ -830,6 +852,18 @@ class OrderConfirmationView(DetailView):
|
||||||
new_user = authenticate(username=custom_user.email,
|
new_user = authenticate(username=custom_user.email,
|
||||||
password=password)
|
password=password)
|
||||||
login(request, new_user)
|
login(request, new_user)
|
||||||
|
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(
|
||||||
|
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:
|
else:
|
||||||
# We assume that if the user is here, his/her StripeCustomer
|
# We assume that if the user is here, his/her StripeCustomer
|
||||||
# object already exists
|
# object already exists
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
|
|
@ -187,7 +187,8 @@ class UserHostingKeyForm(forms.ModelForm):
|
||||||
alerts the user of it.
|
alerts the user of it.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if 'generate' in self.request.POST:
|
if ('generate' in self.request.POST
|
||||||
|
or not self.fields['public_key'].required):
|
||||||
return self.data.get('public_key')
|
return self.data.get('public_key')
|
||||||
KEY_ERROR_MESSAGE = _("Please input a proper SSH key")
|
KEY_ERROR_MESSAGE = _("Please input a proper SSH key")
|
||||||
openssh_pubkey_str = self.data.get('public_key').strip()
|
openssh_pubkey_str = self.data.get('public_key').strip()
|
||||||
|
|
@ -214,10 +215,14 @@ class UserHostingKeyForm(forms.ModelForm):
|
||||||
return openssh_pubkey_str
|
return openssh_pubkey_str
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
|
INVALID_NAME_MESSAGE = _("Comma not accepted in the name of the key")
|
||||||
|
if "," in self.data.get('name'):
|
||||||
|
logger.debug(INVALID_NAME_MESSAGE)
|
||||||
|
raise forms.ValidationError(INVALID_NAME_MESSAGE)
|
||||||
return self.data.get('name')
|
return self.data.get('name')
|
||||||
|
|
||||||
def clean_user(self):
|
def clean_user(self):
|
||||||
return self.request.user
|
return self.request.user if self.request.user.is_authenticated() else None
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = self.cleaned_data
|
cleaned_data = self.cleaned_data
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2018-09-08 08:45+0000\n"
|
"POT-Creation-Date: 2019-07-09 15:21+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -27,6 +27,30 @@ msgstr "Dein Account wurde noch nicht aktiviert."
|
||||||
msgid "User does not exist"
|
msgid "User does not exist"
|
||||||
msgstr "Der Benutzer existiert nicht"
|
msgstr "Der Benutzer existiert nicht"
|
||||||
|
|
||||||
|
msgid "Choose a product"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Amount in CHF"
|
||||||
|
msgstr "Betrag"
|
||||||
|
|
||||||
|
msgid "Recurring monthly"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Amount field does not match"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Recurring field does not match"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Product name"
|
||||||
|
msgstr "Produkt"
|
||||||
|
|
||||||
|
msgid "Monthly subscription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "One time payment"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Confirm Password"
|
msgid "Confirm Password"
|
||||||
msgstr "Passwort Bestätigung"
|
msgstr "Passwort Bestätigung"
|
||||||
|
|
||||||
|
|
@ -52,6 +76,9 @@ msgstr "Bitte verwende einen gültigen SSH-Key"
|
||||||
msgid "This key exists already with the name \"%(name)s\""
|
msgid "This key exists already with the name \"%(name)s\""
|
||||||
msgstr "Der SSH-Key mit dem Name \"%(name)s\" existiert bereits"
|
msgstr "Der SSH-Key mit dem Name \"%(name)s\" existiert bereits"
|
||||||
|
|
||||||
|
msgid "Comma not accepted in the name of the key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "All Rights Reserved"
|
msgid "All Rights Reserved"
|
||||||
msgstr "Alle Rechte vorbehalten"
|
msgstr "Alle Rechte vorbehalten"
|
||||||
|
|
||||||
|
|
@ -209,7 +236,8 @@ msgstr "Du hast eine neue virtuelle Maschine bestellt!"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your order of <strong>%(vm_name)s</strong> has been charged."
|
msgid "Your order of <strong>%(vm_name)s</strong> has been charged."
|
||||||
msgstr "Deine Bestellung von <strong>%(vm_name)s</strong> wurde entgegengenommen."
|
msgstr ""
|
||||||
|
"Deine Bestellung von <strong>%(vm_name)s</strong> wurde entgegengenommen."
|
||||||
|
|
||||||
msgid "You can view your VM detail by clicking the button below."
|
msgid "You can view your VM detail by clicking the button below."
|
||||||
msgstr "Um die Rechnung zu sehen, klicke auf den Button unten."
|
msgstr "Um die Rechnung zu sehen, klicke auf den Button unten."
|
||||||
|
|
@ -305,6 +333,100 @@ msgstr "Dashboard"
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Abmelden"
|
msgstr "Abmelden"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "%(page_header_text)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invoice #"
|
||||||
|
msgstr "Rechnung"
|
||||||
|
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Datum"
|
||||||
|
|
||||||
|
msgid "Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Terminated"
|
||||||
|
msgstr "Beendet"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Akzeptiert"
|
||||||
|
|
||||||
|
msgid "Declined"
|
||||||
|
msgstr "Abgelehnt"
|
||||||
|
|
||||||
|
msgid "Billed to"
|
||||||
|
msgstr "Rechnungsadresse"
|
||||||
|
|
||||||
|
msgid "Payment method"
|
||||||
|
msgstr "Bezahlmethode"
|
||||||
|
|
||||||
|
msgid "ending in"
|
||||||
|
msgstr "endend in"
|
||||||
|
|
||||||
|
msgid "Invoice summary"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Product"
|
||||||
|
msgstr "Produkt"
|
||||||
|
|
||||||
|
msgid "Period"
|
||||||
|
msgstr "Periode"
|
||||||
|
|
||||||
|
msgid "Cores"
|
||||||
|
msgstr "Prozessorkerne"
|
||||||
|
|
||||||
|
msgid "Memory"
|
||||||
|
msgstr "Arbeitsspeicher"
|
||||||
|
|
||||||
|
msgid "Disk space"
|
||||||
|
msgstr "Festplattenkapazität"
|
||||||
|
|
||||||
|
msgid "Subtotal"
|
||||||
|
msgstr "Zwischensumme"
|
||||||
|
|
||||||
|
msgid "VAT"
|
||||||
|
msgstr "Mehrwertsteuer"
|
||||||
|
|
||||||
|
msgid "Discount"
|
||||||
|
msgstr "Rabatt"
|
||||||
|
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Gesamt"
|
||||||
|
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr "Betrag"
|
||||||
|
|
||||||
|
msgid "Description"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Recurring"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "of every month"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BACK TO LIST"
|
||||||
|
msgstr "ZURÜCK ZUR LISTE"
|
||||||
|
|
||||||
|
msgid "Some problem encountered. Please try again later."
|
||||||
|
msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
|
||||||
|
|
||||||
|
msgid "VM ID"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "IP Address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "See Invoice"
|
||||||
|
msgstr "Siehe Rechnung"
|
||||||
|
|
||||||
|
msgid "Page"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "of"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr "Anmelden"
|
msgstr "Anmelden"
|
||||||
|
|
||||||
|
|
@ -338,67 +460,15 @@ msgstr "Als gelesen markieren"
|
||||||
msgid "All notifications"
|
msgid "All notifications"
|
||||||
msgstr "Alle Benachrichtigungen"
|
msgstr "Alle Benachrichtigungen"
|
||||||
|
|
||||||
#, python-format
|
|
||||||
msgid "%(page_header_text)s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Date"
|
|
||||||
msgstr "Datum"
|
|
||||||
|
|
||||||
msgid "Status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Terminated"
|
|
||||||
msgstr "Beendet"
|
|
||||||
|
|
||||||
msgid "Approved"
|
|
||||||
msgstr "Akzeptiert"
|
|
||||||
|
|
||||||
msgid "Declined"
|
|
||||||
msgstr "Abgelehnt"
|
|
||||||
|
|
||||||
msgid "Billed to"
|
|
||||||
msgstr "Rechnungsadresse"
|
|
||||||
|
|
||||||
msgid "Payment method"
|
|
||||||
msgstr "Bezahlmethode"
|
|
||||||
|
|
||||||
msgid "ending in"
|
|
||||||
msgstr "endend in"
|
|
||||||
|
|
||||||
msgid "Credit Card"
|
msgid "Credit Card"
|
||||||
msgstr "Kreditkarte"
|
msgstr "Kreditkarte"
|
||||||
|
|
||||||
|
msgid "Expiry"
|
||||||
|
msgstr "Gültig bis"
|
||||||
|
|
||||||
msgid "Order summary"
|
msgid "Order summary"
|
||||||
msgstr "Bestellungsübersicht"
|
msgstr "Bestellungsübersicht"
|
||||||
|
|
||||||
msgid "Product"
|
|
||||||
msgstr "Produkt"
|
|
||||||
|
|
||||||
msgid "Period"
|
|
||||||
msgstr "Periode"
|
|
||||||
|
|
||||||
msgid "Cores"
|
|
||||||
msgstr "Prozessorkerne"
|
|
||||||
|
|
||||||
msgid "Memory"
|
|
||||||
msgstr "Arbeitsspeicher"
|
|
||||||
|
|
||||||
msgid "Disk space"
|
|
||||||
msgstr "Festplattenkapazität"
|
|
||||||
|
|
||||||
msgid "Subtotal"
|
|
||||||
msgstr "Zwischensumme"
|
|
||||||
|
|
||||||
msgid "VAT"
|
|
||||||
msgstr "Mehrwertsteuer"
|
|
||||||
|
|
||||||
msgid "Discount"
|
|
||||||
msgstr "Rabatt"
|
|
||||||
|
|
||||||
msgid "Total"
|
|
||||||
msgstr "Gesamt"
|
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"By clicking \"Place order\" this plan will charge your credit card account "
|
"By clicking \"Place order\" this plan will charge your credit card account "
|
||||||
|
|
@ -410,9 +480,6 @@ msgstr ""
|
||||||
msgid "Place order"
|
msgid "Place order"
|
||||||
msgstr "Bestellen"
|
msgstr "Bestellen"
|
||||||
|
|
||||||
msgid "BACK TO LIST"
|
|
||||||
msgstr "ZURÜCK ZUR LISTE"
|
|
||||||
|
|
||||||
msgid "Processing..."
|
msgid "Processing..."
|
||||||
msgstr "Abarbeitung..."
|
msgstr "Abarbeitung..."
|
||||||
|
|
||||||
|
|
@ -425,24 +492,9 @@ msgstr ""
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Schliessen"
|
msgstr "Schliessen"
|
||||||
|
|
||||||
msgid "Some problem encountered. Please try again later."
|
|
||||||
msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
|
|
||||||
|
|
||||||
msgid "Order Nr."
|
msgid "Order Nr."
|
||||||
msgstr "Bestellung Nr."
|
msgstr "Bestellung Nr."
|
||||||
|
|
||||||
msgid "Amount"
|
|
||||||
msgstr "Betrag"
|
|
||||||
|
|
||||||
msgid "See Invoice"
|
|
||||||
msgstr "Siehe Rechnung"
|
|
||||||
|
|
||||||
msgid "Page"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "of"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Your Order"
|
msgid "Your Order"
|
||||||
msgstr "Deine Bestellung"
|
msgstr "Deine Bestellung"
|
||||||
|
|
||||||
|
|
@ -539,9 +591,6 @@ msgstr ""
|
||||||
"Wir nutzen <a href=\"https://stripe.com\" target=\"_blank\">Stripe</a> für "
|
"Wir nutzen <a href=\"https://stripe.com\" target=\"_blank\">Stripe</a> für "
|
||||||
"die Bezahlung und speichern keine Informationen in unserer Datenbank."
|
"die Bezahlung und speichern keine Informationen in unserer Datenbank."
|
||||||
|
|
||||||
msgid "Add your public SSH key"
|
|
||||||
msgstr "Füge deinen öffentlichen SSH-Key hinzu"
|
|
||||||
|
|
||||||
msgid "Use your created key to access to the VM"
|
msgid "Use your created key to access to the VM"
|
||||||
msgstr "Benutze deinen erstellten SSH-Key um auf deine VM zugreifen zu können"
|
msgstr "Benutze deinen erstellten SSH-Key um auf deine VM zugreifen zu können"
|
||||||
|
|
||||||
|
|
@ -783,6 +832,9 @@ msgstr ""
|
||||||
msgid "Invalid number of cores"
|
msgid "Invalid number of cores"
|
||||||
msgstr "Ungültige Anzahle CPU-Kerne"
|
msgstr "Ungültige Anzahle CPU-Kerne"
|
||||||
|
|
||||||
|
msgid "Invalid calculator properties"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid RAM size"
|
msgid "Invalid RAM size"
|
||||||
msgstr "Ungültige RAM-Grösse"
|
msgstr "Ungültige RAM-Grösse"
|
||||||
|
|
||||||
|
|
@ -821,6 +873,9 @@ msgstr ""
|
||||||
"Es gab einen Fehler bei der Bearbeitung Deine Anfrage. Bitte versuche es "
|
"Es gab einen Fehler bei der Bearbeitung Deine Anfrage. Bitte versuche es "
|
||||||
"noch einmal."
|
"noch einmal."
|
||||||
|
|
||||||
|
#~ msgid "Add your public SSH key"
|
||||||
|
#~ msgstr "Füge deinen öffentlichen SSH-Key hinzu"
|
||||||
|
|
||||||
#~ msgid "Do you want to cancel your Virtual Machine"
|
#~ msgid "Do you want to cancel your Virtual Machine"
|
||||||
#~ msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst"
|
#~ msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst"
|
||||||
|
|
||||||
|
|
@ -830,9 +885,6 @@ msgstr ""
|
||||||
#~ msgid "My VM page"
|
#~ msgid "My VM page"
|
||||||
#~ msgstr "Meine VM page"
|
#~ msgstr "Meine VM page"
|
||||||
|
|
||||||
#~ msgid "Invoice Date"
|
|
||||||
#~ msgstr "Rechnung Datum"
|
|
||||||
|
|
||||||
#~ msgid "VM %(VM_ID)s terminated successfully"
|
#~ msgid "VM %(VM_ID)s terminated successfully"
|
||||||
#~ msgstr "VM %(VM_ID)s erfolgreich beendet"
|
#~ msgstr "VM %(VM_ID)s erfolgreich beendet"
|
||||||
|
|
||||||
|
|
|
||||||
22
hosting/migrations/0055_auto_20190701_1614.py
Normal file
22
hosting/migrations/0055_auto_20190701_1614.py
Normal file
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -187,7 +187,7 @@ class HostingOrder(AssignPermissionsMixin, models.Model):
|
||||||
|
|
||||||
|
|
||||||
class UserHostingKey(models.Model):
|
class UserHostingKey(models.Model):
|
||||||
user = models.ForeignKey(CustomUser)
|
user = models.ForeignKey(CustomUser, blank=True, null=True)
|
||||||
public_key = models.TextField()
|
public_key = models.TextField()
|
||||||
private_key = models.FileField(upload_to='private_keys', blank=True)
|
private_key = models.FileField(upload_to='private_keys', blank=True)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
@ -613,6 +613,8 @@ class UserCardDetail(AssignPermissionsMixin, models.Model):
|
||||||
for card in user_card_details:
|
for card in user_card_details:
|
||||||
cards_list.append({
|
cards_list.append({
|
||||||
'last4': card.last4, 'brand': card.brand, 'id': card.id,
|
'last4': card.last4, 'brand': card.brand, 'id': card.id,
|
||||||
|
'exp_year': card.exp_year,
|
||||||
|
'exp_month': '{:02d}'.format(card.exp_month),
|
||||||
'preferred': card.preferred
|
'preferred': card.preferred
|
||||||
})
|
})
|
||||||
return cards_list
|
return cards_list
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,11 @@ $(document).ready(function() {
|
||||||
modal_btn = $('#createvm-modal-done-btn');
|
modal_btn = $('#createvm-modal-done-btn');
|
||||||
$('#createvm-modal-title').text(data.msg_title);
|
$('#createvm-modal-title').text(data.msg_title);
|
||||||
$('#createvm-modal-body').html(data.msg_body);
|
$('#createvm-modal-body').html(data.msg_body);
|
||||||
modal_btn.attr('href', data.redirect)
|
if (data.redirect) {
|
||||||
.removeClass('hide');
|
modal_btn.attr('href', data.redirect).removeClass('hide');
|
||||||
|
} else {
|
||||||
|
modal_btn.attr('href', "");
|
||||||
|
}
|
||||||
if (data.status === true) {
|
if (data.status === true) {
|
||||||
fa_icon.attr('class', 'checkmark');
|
fa_icon.attr('class', 'checkmark');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@
|
||||||
{{user.email}}
|
{{user.email}}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{cc_brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{cc_last4}}<br>
|
{{cc_brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{cc_last4}}<br>
|
||||||
|
{% trans "Expiry" %} {{cc_exp_year}}/{{cc_exp_month}}<br/>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{{request.user.email}}
|
{{request.user.email}}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@
|
||||||
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
||||||
|
<h5 class="membership-lead">{% trans "Expiry" %}: {{card.exp_month}}/{{card.exp_year}}</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 text-right align-bottom">
|
<div class="col-xs-6 text-right align-bottom">
|
||||||
<a class="btn choice-btn choice-btn-faded" href="#" data-id_card="{{card.id}}">{% trans "SELECT" %}</a>
|
<a class="btn choice-btn choice-btn-faded" href="#" data-id_card="{{card.id}}">{% trans "SELECT" %}</a>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
<h5 class="membership-lead">{% trans "Last" %} 4: ***** {{card.last4}}</h5>
|
||||||
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
<h5 class="membership-lead">{% trans "Type" %}: {{card.brand}}</h5>
|
||||||
|
<h5 class="membership-lead">{% trans "Expiry" %}: {{card.exp_month}}/{{card.exp_year}}</h5>
|
||||||
<div class="credit-card-details-opt">
|
<div class="credit-card-details-opt">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if card_list_len > 1 %}
|
{% if card_list_len > 1 %}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@
|
||||||
<form method="POST" action="" novalidate class="form-ssh">
|
<form method="POST" action="" novalidate class="form-ssh">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i> {% trans "Add your public SSH key" %}</h1>
|
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i> {% if title %}{% trans title %}{% else %} {% endif %}</h1>
|
||||||
|
{% if sub_title %}<span>{% trans sub_title %}</span>{% else %}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
|
||||||
|
from utils.views import SSHKeyCreateView, AskSSHKeyView
|
||||||
from .views import (
|
from .views import (
|
||||||
DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView,
|
DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView,
|
||||||
LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView,
|
LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView,
|
||||||
|
|
@ -7,12 +9,11 @@ from .views import (
|
||||||
VirtualMachinesPlanListView, VirtualMachineView, OrdersHostingDeleteView,
|
VirtualMachinesPlanListView, VirtualMachineView, OrdersHostingDeleteView,
|
||||||
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
|
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
|
||||||
HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
|
HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
|
||||||
HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView,
|
HostingBillDetailView, SSHKeyDeleteView, SSHKeyListView,
|
||||||
SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView,
|
SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView,
|
||||||
InvoiceListView, InvoiceDetailView, CheckUserVM
|
InvoiceListView, InvoiceDetailView, CheckUserVM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'index/?$', IndexView.as_view(), name='index'),
|
url(r'index/?$', IndexView.as_view(), name='index'),
|
||||||
url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'),
|
url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'),
|
||||||
|
|
@ -27,6 +28,8 @@ urlpatterns = [
|
||||||
url(r'invoices/?$', InvoiceListView.as_view(), name='invoices'),
|
url(r'invoices/?$', InvoiceListView.as_view(), name='invoices'),
|
||||||
url(r'order-confirmation/?$', OrdersHostingDetailView.as_view(),
|
url(r'order-confirmation/?$', OrdersHostingDetailView.as_view(),
|
||||||
name='order-confirmation'),
|
name='order-confirmation'),
|
||||||
|
url(r'^add-ssh-key/?$', AskSSHKeyView.as_view(),
|
||||||
|
name='add_ssh_key'),
|
||||||
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(),
|
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(),
|
||||||
name='orders'),
|
name='orders'),
|
||||||
url(r'invoice/(?P<invoice_id>[-\w]+)/?$', InvoiceDetailView.as_view(),
|
url(r'invoice/(?P<invoice_id>[-\w]+)/?$', InvoiceDetailView.as_view(),
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ from utils.forms import (
|
||||||
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
|
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
|
||||||
ResendActivationEmailForm
|
ResendActivationEmailForm
|
||||||
)
|
)
|
||||||
|
from utils.hosting_utils import get_all_public_keys
|
||||||
from utils.hosting_utils import get_vm_price_with_vat, HostingUtils
|
from utils.hosting_utils import get_vm_price_with_vat, HostingUtils
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
|
|
@ -466,7 +467,9 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
# Get user ssh key
|
# Get user ssh key
|
||||||
public_key = UserHostingKey.objects.get(pk=pk).public_key
|
public_key = UserHostingKey.objects.get(pk=pk).public_key
|
||||||
manager.manage_public_key([{'value': public_key, 'state': False}])
|
keys = UserHostingKey.objects.filter(user=self.request.user)
|
||||||
|
keys_to_save = [k.public_key for k in keys if k.public_key != public_key]
|
||||||
|
manager.save_key_in_opennebula_user('\n'.join(keys_to_save), update_type=0)
|
||||||
|
|
||||||
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
|
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
@ -515,74 +518,11 @@ class SSHKeyChoiceView(LoginRequiredMixin, View):
|
||||||
email=owner.email,
|
email=owner.email,
|
||||||
password=owner.password
|
password=owner.password
|
||||||
)
|
)
|
||||||
public_key_str = public_key.decode()
|
keys = get_all_public_keys(request.user)
|
||||||
manager.manage_public_key([{'value': public_key_str, 'state': True}])
|
manager.save_key_in_opennebula_user('\n'.join(keys))
|
||||||
return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar')
|
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
|
|
||||||
)
|
|
||||||
public_key = form.cleaned_data['public_key']
|
|
||||||
if type(public_key) is bytes:
|
|
||||||
public_key = public_key.decode()
|
|
||||||
manager.manage_public_key([{'value': public_key, 'state': True}])
|
|
||||||
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')
|
@method_decorator(decorators, name='dispatch')
|
||||||
class SettingsView(LoginRequiredMixin, FormView):
|
class SettingsView(LoginRequiredMixin, FormView):
|
||||||
template_name = "hosting/settings.html"
|
template_name = "hosting/settings.html"
|
||||||
|
|
@ -829,21 +769,27 @@ class PaymentVMView(LoginRequiredMixin, FormView):
|
||||||
reverse('hosting:payment') + '#payment_error')
|
reverse('hosting:payment') + '#payment_error')
|
||||||
request.session['token'] = token
|
request.session['token'] = token
|
||||||
request.session['billing_address_data'] = billing_address_data
|
request.session['billing_address_data'] = billing_address_data
|
||||||
return HttpResponseRedirect("{url}?{query_params}".format(
|
self.request.session['order_confirm_url'] = "{url}?{query_params}".format(
|
||||||
url=reverse('hosting:order-confirmation'),
|
url=reverse('hosting:order-confirmation'),
|
||||||
query_params='page=payment')
|
query_params='page=payment')
|
||||||
)
|
return HttpResponseRedirect(reverse('hosting:add_ssh_key'))
|
||||||
else:
|
else:
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
|
||||||
|
form_class = UserHostingKeyForm
|
||||||
template_name = "hosting/order_detail.html"
|
template_name = "hosting/order_detail.html"
|
||||||
context_object_name = "order"
|
context_object_name = "order"
|
||||||
login_url = reverse_lazy('hosting:login')
|
login_url = reverse_lazy('hosting:login')
|
||||||
permission_required = ['view_hostingorder']
|
permission_required = ['view_hostingorder']
|
||||||
model = HostingOrder
|
model = HostingOrder
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
kwargs = super(OrdersHostingDetailView, self).get_form_kwargs()
|
||||||
|
kwargs.update({'request': self.request})
|
||||||
|
return kwargs
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
order_id = self.kwargs.get('pk')
|
order_id = self.kwargs.get('pk')
|
||||||
try:
|
try:
|
||||||
|
|
@ -868,6 +814,8 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
|
||||||
if self.request.GET.get('page') == 'payment':
|
if self.request.GET.get('page') == 'payment':
|
||||||
context['page_header_text'] = _('Confirm Order')
|
context['page_header_text'] = _('Confirm Order')
|
||||||
|
context['form'] = UserHostingKeyForm(request=self.request)
|
||||||
|
context['keys'] = get_all_public_keys(self.request.user)
|
||||||
else:
|
else:
|
||||||
context['page_header_text'] = _('Invoice')
|
context['page_header_text'] = _('Invoice')
|
||||||
if not self.request.user.has_perm(
|
if not self.request.user.has_perm(
|
||||||
|
|
@ -958,11 +906,15 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
card_details_response = card_details['response_object']
|
card_details_response = card_details['response_object']
|
||||||
context['cc_last4'] = card_details_response['last4']
|
context['cc_last4'] = card_details_response['last4']
|
||||||
context['cc_brand'] = card_details_response['brand']
|
context['cc_brand'] = card_details_response['brand']
|
||||||
|
context['cc_exp_year'] = card_details_response['exp_year']
|
||||||
|
context['cc_exp_month'] = card_details_response['exp_month']
|
||||||
else:
|
else:
|
||||||
card_id = self.request.session.get('card_id')
|
card_id = self.request.session.get('card_id')
|
||||||
card_detail = UserCardDetail.objects.get(id=card_id)
|
card_detail = UserCardDetail.objects.get(id=card_id)
|
||||||
context['cc_last4'] = card_detail.last4
|
context['cc_last4'] = card_detail.last4
|
||||||
context['cc_brand'] = card_detail.brand
|
context['cc_brand'] = card_detail.brand
|
||||||
|
context['cc_exp_year'] = card_detail.exp_year
|
||||||
|
context['cc_exp_month'] = '{:02d}'.format(card_detail.exp_month)
|
||||||
context['site_url'] = reverse('hosting:create_virtual_machine')
|
context['site_url'] = reverse('hosting:create_virtual_machine')
|
||||||
context['vm'] = self.request.session.get('specs')
|
context['vm'] = self.request.session.get('specs')
|
||||||
return context
|
return context
|
||||||
|
|
@ -1587,6 +1539,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
'order': HostingOrder.objects.get(
|
'order': HostingOrder.objects.get(
|
||||||
vm_id=serializer.data['vm_id']
|
vm_id=serializer.data['vm_id']
|
||||||
),
|
),
|
||||||
|
'keys': UserHostingKey.objects.filter(user=request.user),
|
||||||
'has_invoices': False
|
'has_invoices': False
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
|
|
@ -1665,7 +1618,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
"manager.delete_vm returned False. Hence, error making "
|
"manager.delete_vm returned False. Hence, error making "
|
||||||
"xml-rpc call to delete vm failed."
|
"xml-rpc call to delete vm failed."
|
||||||
)
|
)
|
||||||
response['text'] = ugettext('Error terminating VM') + vm.id
|
response['text'] = str(_('Error terminating VM')) + str(vm.id)
|
||||||
else:
|
else:
|
||||||
for t in range(15):
|
for t in range(15):
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -207,22 +207,8 @@ class OpenNebulaManager():
|
||||||
else:
|
else:
|
||||||
vm_pool.info()
|
vm_pool.info()
|
||||||
return vm_pool
|
return vm_pool
|
||||||
except AttributeError:
|
except AttributeError as ae:
|
||||||
logger.error(
|
logger.error("AttributeError : %s" % str(ae))
|
||||||
'Could not connect via client, using oneadmin instead')
|
|
||||||
try:
|
|
||||||
vm_pool = oca.VirtualMachinePool(self.oneadmin_client)
|
|
||||||
if infoextended:
|
|
||||||
vm_pool.infoextended(
|
|
||||||
filter=-1, # User's resources and any of his groups
|
|
||||||
vm_state=-1 # Look for VMs in any state, except DONE
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
vm_pool.info(filter=-2)
|
|
||||||
return vm_pool
|
|
||||||
except:
|
|
||||||
raise ConnectionRefusedError
|
|
||||||
|
|
||||||
except ConnectionRefusedError:
|
except ConnectionRefusedError:
|
||||||
logger.error(
|
logger.error(
|
||||||
'Could not connect to host: {host} via protocol {protocol}'.format(
|
'Could not connect to host: {host} via protocol {protocol}'.format(
|
||||||
|
|
@ -377,6 +363,31 @@ class OpenNebulaManager():
|
||||||
|
|
||||||
return vm_terminated
|
return vm_terminated
|
||||||
|
|
||||||
|
def save_key_in_opennebula_user(self, ssh_key, update_type=1):
|
||||||
|
"""
|
||||||
|
Save the given ssh key in OpenNebula user
|
||||||
|
|
||||||
|
# Update type: 0: Replace the whole template.
|
||||||
|
1: Merge new template with the existing one.
|
||||||
|
:param ssh_key: The ssh key to be saved
|
||||||
|
:param update_type: The update type as explained above
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return_value = self.oneadmin_client.call(
|
||||||
|
'user.update',
|
||||||
|
self.opennebula_user if type(self.opennebula_user) == int else self.opennebula_user.id,
|
||||||
|
'<CONTEXT><SSH_PUBLIC_KEY>%s</SSH_PUBLIC_KEY></CONTEXT>' % ssh_key,
|
||||||
|
update_type
|
||||||
|
)
|
||||||
|
if type(return_value) == int:
|
||||||
|
logger.debug(
|
||||||
|
"Saved the key in opennebula successfully : %s" % return_value)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"Could not save the key in opennebula. %s" % return_value)
|
||||||
|
return
|
||||||
|
|
||||||
def _get_template_pool(self):
|
def _get_template_pool(self):
|
||||||
try:
|
try:
|
||||||
template_pool = oca.VmTemplatePool(self.oneadmin_client)
|
template_pool = oca.VmTemplatePool(self.oneadmin_client)
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,25 @@
|
||||||
|
import uuid
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
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.core.urlresolvers import reverse_lazy
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.shortcuts import render
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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.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 membership.models import CustomUser
|
||||||
|
from opennebula_api.models import OpenNebulaManager
|
||||||
|
from utils.hosting_utils import get_all_public_keys
|
||||||
from .forms import SetPasswordForm
|
from .forms import SetPasswordForm
|
||||||
from .mailer import BaseEmail
|
from .mailer import BaseEmail
|
||||||
|
|
||||||
|
|
@ -174,3 +183,87 @@ class PasswordResetConfirmViewMixin(FormView):
|
||||||
form.add_error(None,
|
form.add_error(None,
|
||||||
_('The reset password link is no longer valid.'))
|
_('The reset password link is no longer valid.'))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class SSHKeyCreateView(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),
|
||||||
|
})
|
||||||
|
|
||||||
|
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):
|
||||||
|
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):
|
||||||
|
self.success_url = self.request.session.get("order_confirm_url")
|
||||||
|
return super(AskSSHKeyView, self).post(self, request, *args, **kwargs)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue