Merge branch 'task/5509/improve-asking-ssh-key' into 'master'

Task/5509/improve asking ssh key

See merge request ungleich-public/dynamicweb!709
This commit is contained in:
pcoder116 2019-07-03 16:56:30 +02:00
commit 20a5e51cad
15 changed files with 204 additions and 194 deletions

View file

@ -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 youll 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"

View 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 youll 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%}

View file

@ -134,38 +134,6 @@
</div> </div>
<form id="virtual_machine_create_form" action="" method="POST"> <form id="virtual_machine_create_form" action="" method="POST">
{% csrf_token %} {% 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 %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<div class="dashboard-container-head">
<h2 class="dashboard-title-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "Add your public SSH key" %}</h2>
</div>
<div class="existing-keys">
{% if keys|length > 0 %}
<div class="existing-keys-title">Existing keys</div>
{% endif %}
{% for key in keys %}
<textarea class="form-control input-no-border" style="width: 100%" readonly rows="6">
{{key}}
</textarea>
<br/>
{% endfor %}
</div>
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% endif %}
<div class="row"> <div class="row">
<div class="col-sm-8"> <div class="col-sm-8">
{% if generic_payment_details %} {% if generic_payment_details %}

View file

@ -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'),

View file

@ -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]

View file

@ -17,9 +17,10 @@ from hosting.forms import (
UserHostingKeyForm 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,
@ -522,8 +523,16 @@ 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
@ -588,31 +597,6 @@ class OrderConfirmationView(DetailView, FormView):
return render(request, self.template_name, context) return render(request, self.template_name, context)
def post(self, request, *args, **kwargs): 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': "<br/>".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') user = request.session.get('user')
stripe_api_cus_id = request.session.get('customer') stripe_api_cus_id = request.session.get('customer')
stripe_utils = StripeUtils() stripe_utils = StripeUtils()
@ -864,6 +848,18 @@ class OrderConfirmationView(DetailView, FormView):
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

View file

@ -222,7 +222,7 @@ class UserHostingKeyForm(forms.ModelForm):
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

View 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),
),
]

View file

@ -1,11 +1,11 @@
import json import json
import logging import logging
import os import os
import pytz from datetime import datetime
import pytz
from Crypto.PublicKey import RSA from Crypto.PublicKey import RSA
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from datetime import datetime
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -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)

View file

@ -198,35 +198,6 @@
{% block submit_btn %} {% block submit_btn %}
<form method="post" id="virtual_machine_create_form"> <form method="post" id="virtual_machine_create_form">
{% csrf_token %} {% 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 %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<div class="dashboard-container-head">
<h2 class="dashboard-title-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "Add your public SSH key" %}</h2>
</div>
<div class="existing-keys">
{% if keys|length > 0 %}
<div class="existing-keys-title">Existing keys</div>
{% endif %}
{% for key in keys %}
<textarea class="form-control input-no-border" style="width: 100%" readonly rows="6">
{{key}}
</textarea>
<br/>
{% endfor %}
</div>
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
<div class="row"> <div class="row">
<div class="col-sm-8"> <div class="col-sm-8">
<div class="dcl-place-order-text">{% 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 %}.</div> <div class="dcl-place-order-text">{% 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 %}.</div>

View file

@ -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>&nbsp;{% trans "Add your public SSH key" %}</h1> <h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% 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">

View file

@ -1,6 +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,
@ -8,7 +9,7 @@ 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
) )
@ -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(),

View file

@ -523,67 +523,6 @@ class SSHKeyChoiceView(LoginRequiredMixin, View):
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
)
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') @method_decorator(decorators, name='dispatch')
class SettingsView(LoginRequiredMixin, FormView): class SettingsView(LoginRequiredMixin, FormView):
template_name = "hosting/settings.html" template_name = "hosting/settings.html"
@ -830,10 +769,10 @@ 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)
@ -1002,31 +941,6 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
@method_decorator(decorators) @method_decorator(decorators)
def post(self, request): 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': "<br/>".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') template = request.session.get('template')
specs = request.session.get('specs') specs = request.session.get('specs')
stripe_utils = StripeUtils() stripe_utils = StripeUtils()

View file

@ -376,7 +376,7 @@ class OpenNebulaManager():
""" """
return_value = self.oneadmin_client.call( return_value = self.oneadmin_client.call(
'user.update', 'user.update',
self.opennebula_user.id, 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, '<CONTEXT><SSH_PUBLIC_KEY>%s</SSH_PUBLIC_KEY></CONTEXT>' % ssh_key,
update_type update_type
) )

View file

@ -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)