Merge pull request #428 from tiwariav/task/3620/ssh_keys

task/3620 ssh_keys_choice page new design
This commit is contained in:
Pcoder 2017-08-03 22:53:12 +02:00 committed by GitHub
commit 3d051aee14
16 changed files with 857 additions and 369 deletions

View file

@ -19,7 +19,6 @@ from hosting.models import HostingOrder, HostingBill
from utils.stripe_utils import StripeUtils
from datetime import datetime
from membership.models import CustomUser, StripeCustomer
from opennebula_api.models import OpenNebulaManager
from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
@ -34,6 +33,7 @@ class SuccessView(TemplateView):
def get(self, request, *args, **kwargs):
if 'specs' not in request.session or 'user' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:index'))
elif 'token' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:payment'))
elif 'order_confirmation' not in request.session:
@ -79,7 +79,8 @@ class PricingView(TemplateView):
manager = OpenNebulaManager()
template = manager.get_template(template_id)
request.session['template'] = VirtualMachineTemplateSerializer(template).data
request.session['template'] = VirtualMachineTemplateSerializer(
template).data
if not request.user.is_authenticated():
request.session['next'] = reverse('hosting:payment')
@ -131,7 +132,8 @@ class BetaAccessView(FormView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'datacenterlight/beta_success.html', {})
@ -183,7 +185,8 @@ class BetaProgramView(CreateView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return HttpResponseRedirect(self.get_success_url())
@ -227,7 +230,8 @@ class IndexView(CreateView):
storage_field = forms.IntegerField(validators=[self.validate_storage])
price = request.POST.get('total')
template_id = int(request.POST.get('config'))
template = VMTemplate.objects.filter(opennebula_vm_template_id=template_id).first()
template = VMTemplate.objects.filter(
opennebula_vm_template_id=template_id).first()
template_data = VMTemplateSerializer(template).data
name = request.POST.get('name')
@ -239,35 +243,40 @@ class IndexView(CreateView):
cores = cores_field.clean(cores)
except ValidationError as err:
msg = '{} : {}.'.format(cores, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='cores')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='cores')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
memory = memory_field.clean(memory)
except ValidationError as err:
msg = '{} : {}.'.format(memory, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='memory')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='memory')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
storage = storage_field.clean(storage)
except ValidationError as err:
msg = '{} : {}.'.format(storage, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='storage')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='storage')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
name = name_field.clean(name)
except ValidationError as err:
msg = '{} {}.'.format(name, _('is not a proper name'))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='name')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='name')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
email = email_field.clean(email)
except ValidationError as err:
msg = '{} {}.'.format(email, _('is not a proper email'))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='email')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='email')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
specs = {
@ -332,7 +341,8 @@ class IndexView(CreateView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return super(IndexView, self).form_valid(form)
@ -401,6 +411,7 @@ class PaymentOrderView(FormView):
# Create Billing Address
billing_address = form.save()
request.session['billing_address_data'] = billing_address_data
request.session['billing_address'] = billing_address.id
request.session['token'] = token
@ -425,7 +436,8 @@ class OrderConfirmationView(DetailView):
stripe_customer_id = request.session.get('customer')
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
stripe_utils = StripeUtils()
card_details = stripe_utils.get_card_details(customer.stripe_id, request.session.get('token'))
card_details = stripe_utils.get_card_details(
customer.stripe_id, request.session.get('token'))
context = {
'site_url': reverse('datacenterlight:index'),
'cc_last4': card_details.get('response_object').get('last4'),
@ -441,7 +453,8 @@ class OrderConfirmationView(DetailView):
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
billing_address_data = request.session.get('billing_address_data')
billing_address_id = request.session.get('billing_address')
billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
billing_address = BillingAddress.objects.filter(
id=billing_address_id).first()
vm_template_id = template.get('id', 1)
final_price = specs.get('price')

View file

@ -195,7 +195,7 @@ CMS_TEMPLATES = (
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'app'
'NAME': 'app',
}
}

View file

@ -1,4 +1,4 @@
from .base import * # flake8: noqa
from .base import * # flake8: noqa
# List of people that get admin messages
ADMINS = ((x, x + "@ungleich.ch") for x in ["web-team"])

View file

@ -1,3 +1,5 @@
import datetime
from django import forms
from membership.models import CustomUser
from django.contrib.auth import authenticate
@ -7,6 +9,10 @@ from django.utils.translation import ugettext_lazy as _
from .models import UserHostingKey
def generate_ssh_key_name():
return 'dcl-generated-key-' + datetime.datetime.now().strftime('%m%d%y%H%M')
class HostingUserLoginForm(forms.Form):
email = forms.CharField(widget=forms.EmailInput())
@ -20,9 +26,11 @@ class HostingUserLoginForm(forms.Form):
password = self.cleaned_data.get('password')
is_auth = authenticate(email=email, password=password)
if not is_auth:
raise forms.ValidationError("Your username and/or password were incorrect.")
raise forms.ValidationError(
_("Your username and/or password were incorrect."))
elif is_auth.validated == 0:
raise forms.ValidationError(_("Your account is not activated yet."))
raise forms.ValidationError(
_("Your account is not activated yet."))
return self.cleaned_data
def clean_email(self):
@ -58,15 +66,19 @@ class HostingUserSignupForm(forms.ModelForm):
class UserHostingKeyForm(forms.ModelForm):
private_key = forms.CharField(widget=forms.HiddenInput(), required=False)
public_key = forms.CharField(widget=forms.Textarea(), required=False,
help_text=_('Paste here your public key'))
public_key = forms.CharField(widget=forms.Textarea(
attrs={'class': 'form_public_key', 'placeholder': _('Paste here your public key')}),
required=False,
)
user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(),
required=False, widget=forms.HiddenInput())
name = forms.CharField(required=True)
name = forms.CharField(required=False, widget=forms.TextInput(
attrs={'class': 'form_key_name', 'placeholder': _('Give a name to your key')}))
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UserHostingKeyForm, self).__init__(*args, **kwargs)
self.fields['name'].label = _('Key name')
def clean_name(self):
return self.data.get('name')
@ -76,7 +88,8 @@ class UserHostingKeyForm(forms.ModelForm):
def clean(self):
cleaned_data = self.cleaned_data
if not self.cleaned_data.get('name', ''):
self.cleaned_data['name'] = generate_ssh_key_name()
if not cleaned_data.get('public_key'):
private_key, public_key = UserHostingKey.generate_keys()
cleaned_data.update({

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-17 00:53+0530\n"
"POT-Creation-Date: 2017-08-03 03:31+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,359 +18,271 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: forms.py:25
msgid "Your username and/or password were incorrect."
msgstr "Dein Benutzername und/oder Dein Passwort ist falsch."
msgid "Your account is not activated yet."
msgstr "Dein Account wurde noch nicht aktiviert."
#: forms.py:62
msgid "Paste here your public key"
msgstr "Fügen Sie Ihren public key ein"
msgstr "Füge deinen Public Key ein"
msgid "Give a name to your key"
msgstr "Gebe deinem SSH-Key einen Name"
msgid "Key name"
msgstr "Key-Name"
#: templates/hosting/base_short.html:71
msgid "My Virtual Machines"
msgstr "Meine virtuellen Maschinen"
#: templates/hosting/base_short.html:76 templates/hosting/orders.html.py:12
msgid "My Orders"
msgstr "Meine Bestellungen"
#: templates/hosting/base_short.html:85
msgid "Keys"
msgstr "Schlüssel"
#: templates/hosting/base_short.html:90
msgid "Notifications "
msgstr "Benachrichtigungen"
#: templates/hosting/base_short.html:93
msgid "Logout"
msgstr "Abmelden"
#: templates/hosting/base_short.html:98
msgid "How it works"
msgstr "So funktioniert es"
#: templates/hosting/base_short.html:101
msgid "Your infrastructure"
msgstr "deine Infrastruktur"
#: templates/hosting/base_short.html:104
msgid "Our inftrastructure"
msgstr "Unsere Infrastruktur"
#: templates/hosting/base_short.html:107
msgid "Pricing"
msgstr "Preise"
#: templates/hosting/base_short.html:110
msgid "Contact"
msgstr "Kontakt"
#: templates/hosting/base_short.html:113
#: templates/hosting/confirm_reset_password.html:38
#: templates/hosting/login.html:17 templates/hosting/login.html.py:26
#: templates/hosting/reset_password.html:32 templates/hosting/signup.html:30
msgid "Login"
msgstr "Anmelden"
#: templates/hosting/bill_detail.html:11
msgid "Invoice"
msgstr "Rechnung"
#: templates/hosting/bill_detail.html:11 templates/hosting/order_detail.html:23
msgid "Order #"
msgstr "Bestellung #"
#: templates/hosting/bill_detail.html:25
msgid "ungleich GmbH"
msgstr ""
#: templates/hosting/bill_detail.html:26
msgid "buchhaltung@ungleich.ch"
msgstr ""
#: templates/hosting/bill_detail.html:27
msgid "Hauptstrasse 14"
msgstr ""
#: templates/hosting/bill_detail.html:28
msgid "CH-8775 Luchsingen"
msgstr ""
#: templates/hosting/bill_detail.html:29
msgid "Mwst-Nummer: CHE-109.549.333 MWST"
msgstr ""
#: templates/hosting/bill_detail.html:60
msgid "Total:"
msgstr ""
#: templates/hosting/bill_detail.html:68
#, python-format
msgid "Alles Preise in CHF mit 8%% Mehrwertsteuer."
msgstr "All prices in CHF including 8%% VAT"
#: templates/hosting/bill_detail.html:69
msgid "Betrag zahlbar innerhalb von 30 Tagen ab Rechnungseingang."
msgstr ""
#: templates/hosting/bill_detail.html:70
msgid "Kontoverbindung:"
msgstr ""
#: templates/hosting/bill_detail.html:73
msgid "IBAN:"
msgstr ""
#: templates/hosting/bill_detail.html:76
msgid "BIC:"
msgstr ""
#: templates/hosting/bill_detail.html:81
msgid "CH02 0900 0000 6071 8848 8"
msgstr ""
#: templates/hosting/bill_detail.html:84
msgid "POFICHBEXXX"
msgstr ""
#: templates/hosting/bills.html:12
msgid "Customers"
msgstr "Kunden"
#: templates/hosting/bills.html:16 templates/hosting/user_keys.html.py:25
msgid "Name"
msgstr ""
#: templates/hosting/bills.html:17
msgid "Email"
msgstr ""
#: templates/hosting/bills.html:28
msgid "View Bill"
msgstr "Rechnung anzeigen"
#: templates/hosting/bills.html:41 templates/hosting/orders.html.py:82
#: templates/hosting/virtual_machines.html:70
msgid "previous"
msgstr "vorherige"
#: templates/hosting/bills.html:47 templates/hosting/orders.html.py:88
#: templates/hosting/virtual_machines.html:76
msgid "next"
msgstr "nächste"
#: templates/hosting/confirm_reset_password.html:10
#: templates/hosting/login.html:12 templates/hosting/reset_password.html:10
#: templates/hosting/signup.html:9 templates/hosting/signup_validate.html:9
msgid "SSH Key"
msgstr "SSH Key"
msgid "Choose a key option in order to access your VM"
msgstr "Wähle eine Option um Zugriff auf deine VM zu erhalten"
msgid "Generating a new key pair"
msgstr "Neuen SSH-Key erstellen"
msgid "I want to generate a new key pair"
msgstr "Ich möchte einen neuen SSH-Key erstellen"
msgid "Generate"
msgstr "Generieren"
msgid "Using existing key"
msgstr "Nutzung eines existierenden SSH-Keys"
msgid "I want to use my existing public key"
msgstr "Ich möchte einen existierenden SSH-Key nutzen"
msgid "Upload"
msgstr "Hochladen"
msgid "Your VM hosted in Switzerland"
msgstr "deine VM in der Schweiz"
#: templates/hosting/confirm_reset_password.html:14
msgid "Set your new password"
msgstr "Setze dein neues Passwort"
#: templates/hosting/confirm_reset_password.html:29
#: templates/hosting/reset_password.html:23
msgid "Reset"
msgstr "Zurücksetzen"
#: templates/hosting/confirm_reset_password.html:35
#: templates/hosting/reset_password.html:29 templates/hosting/signup.html:27
msgid "Already have an account ?"
msgstr "Hast Du bereits ein Benutzerkonto?"
#: templates/hosting/create_virtual_machine.html:20
msgid "Login"
msgstr "Anmelden"
msgid "New Virtual Machine"
msgstr "Neue virtuelle Maschine"
#: templates/hosting/create_virtual_machine.html:28
msgid "Step 1. Select VM Template:"
msgstr "Wähle eine Vorlage"
#: templates/hosting/create_virtual_machine.html:42
msgid "Step2. Select VM Configuration"
msgstr "Wähle eine Konfiguration"
#: templates/hosting/create_virtual_machine.html:59
msgid "Price "
msgstr "Preis"
#: templates/hosting/create_virtual_machine.html:59
msgid "CHF/Month"
msgstr "CHF/Monat"
#: templates/hosting/create_virtual_machine.html:61
msgid "Start VM"
msgstr "VM jetzt starten"
#: templates/hosting/emails/password_reset_email.html:2
#: templates/hosting/emails/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
#: templates/hosting/emails/password_reset_email.html:4
#: templates/hosting/emails/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr ""
#: templates/hosting/emails/password_reset_email.html:9
#: templates/hosting/emails/password_reset_email.txt:9
msgid "Thanks for using our site!"
msgstr ""
#: templates/hosting/emails/password_reset_email.html:11
#: templates/hosting/emails/password_reset_email.txt:11
#, python-format
msgid "The %(site_name)s team"
msgstr ""
#: templates/hosting/login.html:34
msgid "Don't have an account yet ? "
msgstr "Besitzt du kein Benutzerkonto?"
#: templates/hosting/login.html:37 templates/hosting/signup.html.py:13
#: templates/hosting/signup.html:21 views.py:219
msgid "Sign up"
msgstr "Registrieren"
#: templates/hosting/login.html:39
msgid "Forgot your password ? "
msgstr "Passwort vergessen?"
#: templates/hosting/notifications.html:9
msgid "Notifications"
msgstr "Benachrichtigungen"
#: templates/hosting/notifications.html:16
msgid "Unread"
msgstr "Ungelesen"
#: templates/hosting/notifications.html:26
msgid "All"
msgstr "Alle"
#: templates/hosting/notifications.html:38
msgid "Unread notifications"
msgstr "Ungelesene Benachrichtigungen"
#: templates/hosting/notifications.html:48
msgid "Mark as read"
msgstr "Als gelesen markieren"
#: templates/hosting/notifications.html:59
msgid "All notifications"
msgstr "Alle Benachrichtigungen"
#: templates/hosting/order_detail.html:23
msgid "Confirm Order"
msgstr "Bestellung Bestätigen"
#: templates/hosting/order_detail.html:29
msgid "Billed To:"
msgstr "Rechnungsadresse"
#: templates/hosting/order_detail.html:37 templates/hosting/orders.html:17
msgid "Date"
msgstr "Datum"
#: templates/hosting/order_detail.html:39
msgid "Status:"
msgstr ""
#: templates/hosting/order_detail.html:51
msgid "Billed To:"
msgstr "Rechnungsadresse"
msgid "Payment Method:"
msgstr "Bezahlmethode"
#: templates/hosting/order_detail.html:62
msgid "Order summary"
msgstr "Bestellungsübersicht"
#: templates/hosting/order_detail.html:65 templates/hosting/payment.html:13
#: templates/hosting/virtual_machine_detail.html:76
msgid "Cores"
msgstr "Prozessorkerne"
#: templates/hosting/order_detail.html:67 templates/hosting/payment.html:16
#: templates/hosting/virtual_machine_detail.html:82
msgid "Memory"
msgstr "Arbeitsspeicher"
#: templates/hosting/order_detail.html:69 templates/hosting/payment.html:19
msgid "Disk space"
msgstr "Festplattenkapazität"
#: templates/hosting/order_detail.html:71 templates/hosting/payment.html:41
msgid "Total"
msgstr "Gesamt"
#: templates/hosting/order_detail.html:77
msgid "Finish Configuration"
msgstr "Konfiguration beenden"
#: templates/hosting/orders.html:18
msgid "Amount"
msgstr "Betrag"
#: templates/hosting/orders.html:19 templates/hosting/user_keys.html.py:27
#: templates/hosting/virtual_machine_detail.html:30
#: templates/hosting/virtual_machines.html:31
msgid "Status"
msgstr ""
#: templates/hosting/orders.html:30
msgid "Approved"
msgstr "Akzeptiert"
#: templates/hosting/orders.html:32
msgid "Declined"
msgstr "Abgelehnt"
#: templates/hosting/orders.html:37 templates/hosting/virtual_machines.html:58
msgid "View Detail"
msgstr "Details anzeigen"
#: templates/hosting/orders.html:40
msgid "Cancel Order"
msgstr "Bestellung stornieren"
#: templates/hosting/orders.html:55
msgid "Do You want to delete your order?"
#, fuzzy
#| msgid "Do You want to delete your order?"
msgid "Do you want to delete your order?"
msgstr "Willst du deine Bestellung löschen?"
#: templates/hosting/orders.html:63 templates/hosting/user_keys.html.py:63
msgid "Close"
msgstr "Schliessen"
#: templates/hosting/orders.html:65 templates/hosting/user_keys.html.py:65
msgid "Delete"
msgstr "Löschen"
#: templates/hosting/payment.html:10
msgid "Your Order"
msgstr "Deine Bestellung"
#: templates/hosting/payment.html:22
#: templates/hosting/virtual_machine_detail.html:98
msgid "Configuration"
msgstr "Konfiguration"
#: templates/hosting/payment.html:41
msgid "including VAT"
msgstr "inkl. Mehrwertsteuer"
#: templates/hosting/payment.html:55
msgid "Billing Address"
msgstr "Rechnungsadresse"
#: templates/hosting/payment.html:66
msgid "Credit Card"
msgstr "Kreditkarte"
#: templates/hosting/payment.html:71
msgid ""
"\n"
" Please fill in your credit card information "
@ -385,7 +297,6 @@ msgstr ""
"\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und "
"speichern keine Informationen in unserer Datenbank."
#: templates/hosting/payment.html:90
msgid ""
"\n"
" You are not making any payment yet. "
@ -399,27 +310,21 @@ msgstr ""
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:101 templates/hosting/payment.html.py:143
msgid "Submit"
msgstr "Absenden"
#: templates/hosting/payment.html:113
msgid "Card Number"
msgstr "Kreditkartennummer"
#: templates/hosting/payment.html:117
msgid "Expiry Date"
msgstr "Ablaufdatum"
#: templates/hosting/payment.html:122
msgid "CVC"
msgstr ""
#: templates/hosting/payment.html:126
msgid "Card Type"
msgstr "Kartentyp"
#: templates/hosting/payment.html:135
msgid ""
"\n"
" You are not making any payment "
@ -433,125 +338,115 @@ msgstr ""
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:178
msgid "Processing"
msgstr "Weiter"
#: templates/hosting/payment.html:179
msgid "Enter your credit card number"
msgstr "Deine Kreditkartennummer"
#: templates/hosting/reset_password.html:15
msgid "Reset your password"
msgstr "Passwort zurücksetzen"
#: templates/hosting/user_key.html:11 templates/hosting/user_keys.html.py:9
msgid "Access Key"
msgstr "Zugriffsschlüssel"
msgid "Add your public SSH key"
msgstr "Füge deinen öffentlichen SSH-Key hinzu"
#: templates/hosting/user_key.html:24
msgid "Upload your own key. "
msgstr "Lade deinen Key hoch"
msgid "Use your created key to access to the VM"
msgstr "Benutze deinen erstellten SSH-Key um auf deine VM zugreifen zu können"
#: templates/hosting/user_key.html:28
msgid "Or generate a new key pair."
msgstr "Oder erstelle dein neues Keypaar"
msgid "Add SSH Key"
msgstr "Hinzufügen"
#: templates/hosting/user_key.html:30
msgid "Generate Key Pair"
msgstr "Schlüsselpaar generieren"
msgid "Or you can generate a new key pair"
msgstr "Erstelle dein neues Keypaar"
#: templates/hosting/user_key.html:40
msgid "Warning!"
msgstr "Achtung!"
#: templates/hosting/user_key.html:40
msgid "You can download your SSH private key once. Don't lost your key"
#, fuzzy
#| msgid "You can download your SSH private key once. Don't lost your key"
msgid "You can download your SSH private key once. Don't loose your key"
msgstr ""
"Du kannst deinen privaten SSH Schlüssel nur einmal herunterladen. Beware ihn "
"sicher auf."
#: templates/hosting/user_keys.html:18
msgid "Add Key"
msgstr "Schlüssel hinzufügen"
msgid "Your SSH Keys"
msgstr "Deine SSH Keys"
#: templates/hosting/user_keys.html:26
msgid "Created at"
msgstr "Erstellt am"
msgid ""
"To generate a new key pair or to upload your existing key, click 'Add Key'"
msgstr ""
"Um einen neuen SSH-Key zu erstellen oder um einen vorhandenen SSH-Key "
"hinzuzufügen, klicke auf 'Hinzufügen'"
#: templates/hosting/user_keys.html:43
msgid "Delete Key"
msgstr "Löschen"
#: templates/hosting/user_keys.html:56
msgid "Public Key"
msgstr ""
msgid "Private Key"
msgstr ""
msgid "Do You want to delete this key?"
msgstr "Möchtest Du den Schlüssel löschen?"
#: templates/hosting/virtual_machine_detail.html:19
msgid "Close"
msgstr "Schliessen"
msgid "Show"
msgstr "Anzeigen"
msgid "Public ssh key"
msgstr ""
msgid "Download"
msgstr ""
msgid "Settings"
msgstr "Einstellungen"
#: templates/hosting/virtual_machine_detail.html:25
msgid "Billing"
msgstr "Abrechnungen"
#: templates/hosting/virtual_machine_detail.html:60
msgid "Ip not assigned yet"
msgstr "Ip nicht zugewiesen"
#: templates/hosting/virtual_machine_detail.html:89
msgid "Disk"
msgstr "Festplatte"
#: templates/hosting/virtual_machine_detail.html:108
msgid "Current pricing"
msgstr "Aktueller Preis"
#: templates/hosting/virtual_machine_detail.html:117
msgid "Current status"
msgstr "Aktueller Status"
#: templates/hosting/virtual_machine_detail.html:142
msgid "Terminate Virtual Machine"
msgstr "Virtuelle Maschine beenden"
#: templates/hosting/virtual_machine_detail.html:163
msgid "Terminate your Virtual Machine"
msgstr "Ihre virtuelle Maschine beenden"
#: templates/hosting/virtual_machine_detail.html:166
msgid "Are you sure do you want to cancel your Virtual Machine "
msgstr "Sind Sie sicher, dass Sie ihre virtuelle Maschine beenden wollen "
#: templates/hosting/virtual_machine_detail.html:169
msgid "Cancel"
msgstr "Beenden"
#: templates/hosting/virtual_machines.html:9
msgid "Virtual Machines"
msgstr "Virtuelle Maschinen"
#: templates/hosting/virtual_machines.html:22
msgid "Create VM"
msgstr "Neue VM"
#: templates/hosting/virtual_machines.html:28
msgid "ID"
msgstr ""
#: templates/hosting/virtual_machines.html:29
msgid "Ipv4"
msgstr "IPv4"
#: templates/hosting/virtual_machines.html:30
msgid "Ipv6"
msgstr "IPv6"
#: views.py:207 views.py:229
msgid "login"
msgstr "einloggen"
#: views.py:212
msgid ""
"Thank you for signing up. We have sent an email to you. Please follow the "
"instructions in it to activate your account. Once activated, you can login "
@ -561,32 +456,135 @@ msgstr ""
"den Anweisungen um deinen Account zu aktivieren. Danach kannst du dich über "
"diesen"
#: views.py:214 views.py:240
msgid "Go back to"
msgstr "Zurück"
#: views.py:230
msgid "Account activation"
msgstr "Accountaktivierung"
#: views.py:233
msgid "Your account has been activated."
msgstr "Dein Account wurde aktiviert."
#: views.py:234
msgid "You can now"
msgstr "Du kannst dich nun"
#: views.py:239
msgid "Sorry. Your request is invalid."
msgstr "Entschuldigung, deine Anfrage ist ungültig."
#: views.py:757
msgid ""
"We could not find the requested VM. Please "
"contact Data Center Light Support."
msgstr ""
#~ msgid "Cancel"
#~ msgstr "Beenden"
#~ msgid "Add SSH key"
#~ msgstr "Hinzufügen"
#~ msgid "Keys"
#~ msgstr "Schlüssel"
#, fuzzy
#~| msgid "Contact"
#~ msgid "Content"
#~ msgstr "Kontakt"
#, fuzzy
#~| msgid "Contact"
#~ msgid "DG.Contact"
#~ msgstr "Kontakt"
#, fuzzy
#~| msgid "Home"
#~ msgid "DG.Home"
#~ msgstr "Home"
#, fuzzy
#~| msgid "Amount"
#~ msgid "Country"
#~ msgstr "Betrag"
#~ msgid "Log in"
#~ msgstr "Anmelden"
#, fuzzy
#~| msgid "Configuration"
#~ msgid "Donation #"
#~ msgstr "Konfiguration"
#, fuzzy
#~| msgid "Billing Address"
#~ msgid "Billing Address:"
#~ msgstr "Rechnungsadresse"
#, fuzzy
#~| msgid "Date"
#~ msgid "Date:"
#~ msgstr "Datum"
#, fuzzy
#~| msgid "Configuration"
#~ msgid "Donation"
#~ msgstr "Konfiguration"
#, fuzzy
#~| msgid "View Detail"
#~ msgid "View Donations"
#~ msgstr "Details anzeigen"
#~ msgid "You haven been logged out"
#~ msgstr "Sie wurden abgmeldet"
#, fuzzy
#~| msgid "Log in"
#~ msgid "Log in "
#~ msgstr "Anmelden"
#, fuzzy
#~| msgid "View Detail"
#~ msgid "DG.Detail"
#~ msgstr "Details anzeigen"
#, fuzzy
#~| msgid "Cancel"
#~ msgid "France"
#~ msgstr "Beenden"
#, fuzzy
#~| msgid "Enter your credit card number"
#~ msgid "Enter your name or company name"
#~ msgstr "Deine Kreditkartennummer"
#, fuzzy
#~| msgid "Card Number"
#~ msgid "Cardholder Name"
#~ msgstr "Kreditkartennummer"
#~ msgid "How it works"
#~ msgstr "So funktioniert es"
#~ msgid "Your infrastructure"
#~ msgstr "deine Infrastruktur"
#~ msgid "Our inftrastructure"
#~ msgstr "Unsere Infrastruktur"
#~ msgid "Pricing"
#~ msgstr "Preise"
#~ msgid "Access Key"
#~ msgstr "Zugriffsschlüssel"
#~ msgid "Upload your own key. "
#~ msgstr "Lade deinen Key hoch"
#~ msgid "Generate Key Pair"
#~ msgstr "Schlüsselpaar generieren"
#~ msgid "Created at"
#~ msgstr "Erstellt am"
#~ msgid "Billing Amount"
#~ msgstr "Rechnungsbetrag"
@ -610,25 +608,6 @@ msgstr ""
#~ msgid "EXPIRATION DATE"
#~ msgstr "Ablaufdatum"
#~ msgid "Home"
#~ msgstr "Home"
#~ msgid "Log in"
#~ msgstr "Anmelden"
#~ msgid "You haven been logged out"
#~ msgstr "Sie wurden abgmeldet"
#~ msgid "Upload Key"
#~ msgstr "Schlüssel hochladen"
#~ msgid ""
#~ "Use your created key to access to the machine. If you lost it, contact us."
#~ msgstr ""
#~ "Verwende deinen privaten SSH Schlüssel, um dich mit deinen Maschinen zu "
#~ "verbinden. Solltest du deinen privaten Schlüssel verloren haben, dann "
#~ "kontaktiere uns."
#~ msgid "Copy to Clipboard"
#~ msgstr "Kopieren"
@ -638,6 +617,3 @@ msgstr ""
#~ msgstr ""
#~ "Dein privater SSH Schlüssel wurde bereits generiert und heruntergeladen. "
#~ "Falls du ihn verloren hast, kontaktiere uns."
#~ msgid "Generate my key"
#~ msgstr "Generiere meinen Schlüssel"

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2017-07-06 09:06
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hosting', '0040_hostingplan'),
]
operations = [
migrations.AddField(
model_name='userhostingkey',
name='private_key',
field=models.FileField(blank=True, upload_to='private_keys'),
),
]

View file

@ -101,6 +101,7 @@ class HostingOrder(AssignPermissionsMixin, models.Model):
class UserHostingKey(models.Model):
user = models.ForeignKey(CustomUser)
public_key = models.TextField()
private_key = models.FileField(upload_to='private_keys', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=100)

View file

@ -58,6 +58,9 @@
width: 90%;
}
}
.btn:focus, .btn:active:focus {
outline: 0;
}
/***********Styles for Model********************/
.modal-content {
@ -70,7 +73,7 @@
}
.modal-header {
min-height: 25px;
min-height: 30px;
}
.modal-header .close {
@ -79,8 +82,12 @@
margin-top: 0;
position: absolute;
top: 0;
right: 15px;
right: 11px;
z-index: 10;
line-height: 60px;
}
.modal-header .close span {
display: block;
}
.modal-header .close:focus {
@ -95,8 +102,8 @@
.modal-body {
text-align: center;
width: 100%;
float: left;
padding: 0px 30px 15px 30px;
float: left;
padding: 0px 40px 15px 30px;
}
.modal-body .modal-icon i {
font-size: 80px;
@ -142,7 +149,7 @@
@media (max-width: 767px) {
.modal-dialog {
/* top: 30%; */
width: 90%;
width: 95%;
margin: 0 auto !important;
}
}
@ -176,4 +183,4 @@
display: inline-block;
text-align: left;
vertical-align: middle;
}
}

View file

@ -0,0 +1,325 @@
/* ssh_keys_choice */
.h1-thin {
font-family: Lato, sans-serif;
font-weight: 300;
font-size: 32px;
}
.dashboard-container .page-header {
border: 0;
margin-top: 0;
}
.dashboard-choice-container .page-header p {
font-size: 16px;
font-family: Lato, sans-serif;
font-weight: 300;
}
.dashboard-choice-container h2 {
font-family: Lato, sans-serif;
font-weight: 400;
font-size: 22px;
margin-top: 0;
}
.choice-container {
border: 1px solid #C9C6C6;
padding: 25px;
border-radius: 1px;
}
.choice-container p{
font-size: 18px;
font-family: Lato, sans-serif;
font-weight: 300;
}
.choice-container-top {
border-bottom: 1px solid #C9C6C6;
padding-bottom: 25px;
margin-bottom: 25px;
}
.choice-container .choice-btn {
margin-top: 25px;
}
.choice-btn {
min-width: 110px;
background-color: #3C5480;
color: #fff;
border: 2px solid #3C5480;
padding: 4px 10px;
transition: 0.3s all ease-out;
}
.choice-btn:focus,
.choice-btn:hover,
.choice-btn:active {
color: #3C5480;
background-color: #fff;
}
.choice-btn-faded {
background-color: #8396C4;
border: 2px solid #8396C4;
}
@media (max-width: 767px) {
.h1-thin {
font-size: 27px;
}
.dashboard-choice-container h2 {
font-size: 20px;
}
.choice-container p {
font-size: 16px;
}
.choice-btn{
margin-top: 15px;
}
}
@media (max-width: 420px) {
.ssh-keys-table {table-layout: fixed;}
}
.ssh-keys-table thead tr th,
.ssh-keys-table tbody tr td{
color: #717274;
text-align: center;
border-bottom: 1px solid #cbcbcb;
vertical-align: middle;
}
.ssh-keys-table tbody tr{
border-bottom: 1px solid #cbcbcb;
}
.ssh-keys-table thead tr th:first-of-type,
.ssh-keys-table tbody tr td:first-of-type{
text-align: left;
}
.ssh-keys-table thead tr th:last-of-type,
.ssh-keys-table tbody tr td:last-of-type{
width: 20%;
}
.ssh-key-header {
color: #717274;
font-size: 16px;
font-weight: 300;
text-align: justify;
}
.ssh-header-container{
padding-top: 15px;
}
@media (min-width: 768px) {
.ssh-header-container {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.ssh-header-container p{
margin-bottom: 0;
}
}
.ssh-header-container p{
padding: 0;
color: #717274;
font-size: 16px;
font-weight: 300;
font-family: 'Lato';
}
.borderless tbody:before {
display: none !important;
}
.btn-custom-download{
background-color: #337ab7;
margin-top: auto;
margin-bottom: auto;
/* font-weight: 700; */
vertical-align: middle;
margin-right: 25px;
}
.btn-custom-delete{
width: 100px;
background-color: #f1f0f0;
}
.btn-custom-delete a, .btn-custom-download a{
text-decoration: none;
}
.modal-body p{
width: 100%;
word-wrap: break-word;
text-align: left;
}
@media screen and (max-width: 768px) {
.ssh-header-container{
flex-direction: column-reverse;
align-items: flex-start;
}
.btn-custom-delete{
width: auto;
}
.dashboard-container {
width: 100% !important;
}
.row {
/* margin-right: 0; */
/* margin-left: 0; */
}
.col-md-12, .col-sm-12{
padding-left: 5px;
padding-right: 5px;
}
}
@media (max-width: 360px){
.content-dashboard {
/* width: 100% !important; */
}
.container {
padding-right: 5px;
padding-left: 5px;
}
}
.dashboard-choice-container {
max-width: 834px !important;
}
.form_public_key{
resize: none;
}
@media (min-width: 768px) {
.form_key_name{
width:60%;
min-width: 215px;
}
}
.form_public_key,
.form_key_name{
position: relative;
border:none;
border-bottom: 1px solid grey;
box-shadow: none;
border-radius: 0;
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
padding-left: 0;
}
.form_key_name::-webkit-input-placeholder{
font-size: 20px;
font-weight:100;
font-family: 'Lato-Light', sans-serif;
}
.form_key_name::-moz-input-placeholder{
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.form_key_name:-moz-input-placeholder{
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
font-weight:200;
}
.form_key_name:-ms-input-placeholder {
font-size: 20px;
font-family: 'Lato-Light', sans-serif;
font-weight:200;
}
.form_public_key::-webkit-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-weight: 200;
font-family: 'Lato-Light', sans-serif;
}
.form_public_key::-moz-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-family: 'Lato-Light', sans-serif;
font-weight:200;
}
.form_public_key:-moz-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.form_public_key:-ms-input-placeholder {
position: relative;
top: 110px;
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.underform-contaner{
margin-bottom: 20px;
}
@media (min-width: 767px) {
.underform-contaner {
display: flex;
vertical-align: middle;
align-items: center;
justify-content: space-between;
flex-direction: row;
}
}
@media (max-width: 767px) {
.underform-contaner .btn-container {
text-align: right;
}
}
.underform-contaner h4{
font-family: 'Lato-Light', sans-serif;
}
.underform-contaner button{
/* font-family: Lato; */
/* font-weight: 600; */
min-width: 120px;
height: 35px;
margin-top: 0;
}
.underform-contaner .btn-default{
background-color: #ccc;
color: #fff;
}
.control-label{
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
font-weight:200;
}
.form-ssh h3{
margin-bottom: 40px;
}
.custom_form_button{
border-radius: 0;
}
.form_key_name:focus,
.form_public_key:focus,
.has-error .form_key_name,
.has-error .form_key_name:focus,
.has-error .form_public_key,
.has-error .form_public_key:focus,
.has-success .form_key_name,
.has-success .form_key_name:focus,
.has-success .form_public_key,
.has-success .form_public_key:focus {
box-shadow: none;
}
.wide440 {
max-width: 440px;
margin: auto;
}
.mob-only {
display: none;
}
@media (max-width: 767px) {
.mob-only {
display: initial;
}
.pc-only {
display: none;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

View file

@ -18,6 +18,7 @@
<!-- Custom CSS -->
<link href="{% static 'hosting/css/landing-page.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/user_keys.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/payment.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/order.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/orders.css' %}" rel="stylesheet">
@ -27,7 +28,7 @@
<!-- Custom Fonts -->
<link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link href="//fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=Lato:300,400,500,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="{% static 'hosting/css/owl.carousel.min.css' %}">
<link rel="stylesheet" href="{% static 'hosting/css/owl.theme.default.min.css' %}">
@ -84,7 +85,7 @@
<ul id="g-account-menu" class="dropdown-menu" role="menu">
<li>
<a href="{% url 'hosting:ssh_keys' %}">
<i class="fa fa-key"></i> {% trans "Keys"%}
<i class="fa fa-key"></i> {% trans "SSH Keys" %}
</a>
</li>
<li>

View file

@ -0,0 +1,66 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
<div>
<div class="container virtual-machine-container dashboard-container dashboard-choice-container">
<div class="wide440">
<div class="page-header">
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "SSH Key"%}</h1>
<p>{% trans "Choose a key option in order to access your VM" %}.</p>
</div>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<div class="choice-container">
<div class="choice-container-top">
<h2>{% trans "Generating a new key pair" %}</h2>
<p>{% trans "I want to generate a new key pair" %}.</p>
<form class="text-right" action="" method="post">
{% csrf_token %}
<button type="submit" class="btn choice-btn choice-btn-faded">
{% trans "Generate" %}
</button>
</form>
</div>
<div>
<h2>{% trans "Using existing key" %}</h2>
<p>{% trans "I want to use my existing public key"%}.</p>
<form class="text-right" action="{% url 'hosting:create_ssh_key' %}">
<button type="submit" class="btn choice-btn">
{% trans "Upload" %}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% if next_url %}
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
<script type="text/javascript">
window.onload = function () {
{% for user_key in keys %}
var locale_date = moment.utc(document.getElementById("ssh-created_at-{{user_key.id}}").textContent,'YYYY-MM-DD HH:mm').toDate();
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
document.getElementById('ssh-created_at-{{user_key.id}}').innerHTML = locale_date;
{% endfor %}
};
</script>
{%endblock%}

View file

@ -1,60 +1,61 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
{% block content %}
<div>
<div class="virtual-machine-container dashboard-container ">
<div class="virtual-machine-container dashboard-container">
<div class="row">
<div class="container-table col-md-9 col-md-offset-2">
<div class="col-sm-12">
<form method="POST" action="" novalidate class="form-ssh">
{% csrf_token %}
<h3><i class="fa fa-key fa-separate" aria-hidden="true"></i>{% trans "Access Key"%} </h3>
{% if messages %}
<div class="col-md-9 col-md-offset-2">
<form method="POST" action="" novalidate class="form-ssh">
{% csrf_token %}
<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>
</div>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-success">
{% trans "Upload your own key. "%}
{% endif %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<div class="underform-contaner">
<h4>{% trans "Use your created key to access to the VM" %}.</h4>
<div class="btn-container">
<button type="submit" name="add_ssh" class="btn choice-btn choice-btn-faded">
{% trans "Add SSH Key" %}
</button>
<br />
<br />
{% trans "Or generate a new key pair."%} <br />
<br />
<button class="btn btn-success">{% trans "Generate Key Pair"%} </a>
</div>
</div>
<div class="underform-contaner">
<h4>{% trans "Or you can generate a new key pair"%}.</h4>
<div class="btn-container">
<button type="submit" name="generate" class="btn choice-btn">
{% trans "Generate" %}
</button>
</div>
</div>
{% endbuttons %}
</form>
{% endbuttons %}
</form>
<h5> Use your created key to access to the machine. If you lost it, contact us. </h5>
{% if private_key %}
<div class="alert alert-warning">
<strong>{% trans "Warning!"%}</strong>{% trans "You can download your SSH private key once. Don't lost your key"%}
</div>
<div class="form-group">
<textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
{% if private_key %}
<div class="alert alert-warning">
<strong>{% trans "Warning!"%}</strong>{% trans "You can download your SSH private key once. Don't loose your key" %}
</div>
<div class="form-group">
<textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% if private_key %}
<!-- Force to download ssh key on page load -->
<script type="text/javascript">
<script type="text/javascript">
var key = window.document.getElementById('ssh_key');
@ -75,7 +76,7 @@
{%endif%}
{% if next_url %}
<script type="text/javascript">
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}

View file

@ -3,85 +3,109 @@
{% block content %}
<div>
<div class="container virtual-machine-container dashboard-container ">
<div class="row">
<div class="col-md-9 col-md-offset-2">
<div class="col-sm-12">
<h3><i class="fa fa-key" aria-hidden="true"></i>{% trans "Access Key"%} </h3>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<p class="pull-right">
<a class="btn btn-success" href="{% url 'hosting:create_ssh_key' %}" >{% trans "Add Key"%} </a>
</p>
<h5> Use your created key to access to the machine. If you lost it, contact us. </h5>
<table class="table borderless table-hover">
<br/>
<thead>
<tr>
<th>{% trans "Name"%}</th>
<th>{% trans "Created at"%} </th>
<th>{% trans "Status"%} </th>
<th></th>
</tr>
</thead>
<tbody>
{% for user_key in keys %}
<tr>
<td scope="row">{{user_key.name}}</td>
<td><span id="ssh-created_at-{{user_key.id}}">{{user_key.created_at|date:'Y-m-d H:i' }}</span></td>
<td>
<span class="h3 label label-success"><strong>Active</strong></span>
</td>
<td>
<button type="button" class="btn btn-default" data-toggle="modal"
data-target="#Modal{{ user_key.id }}"><a
href="#">{% trans "Delete Key"%}</a>
</button>
<div class="modal fade" id="Modal{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div>
<h4 class="modal-title" id="ModalLabel">{% trans "Delete SSH Key"%}</h4>
<p class="modal-text">{% trans "Do You want to delete this key?"%}</p>
<form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}">
{% csrf_token %}
<div class="modal-footer">
<button type="submit" class="btn btn-danger">{% trans "Delete"%}
</button>
</div>
</form>
</div>
</div>
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "Your SSH Keys" %}</h1>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<div class="ssh-header-container">
<p>{% trans "To generate a new key pair or to upload your existing key, click 'Add Key'" %}</p>
<a class="btn choice-btn" href="{% url 'hosting:choice_ssh_keys' %}" >
<span class="fa fa-plus"></span>&nbsp;&nbsp;{% trans "Add SSH Key" %}
</a>
</div>
<table class="table borderless table-hover ssh-keys-table">
<br/>
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Delete Key" %}</th>
<th>{% trans "Public Key" %}</th>
<th>{% trans "Private Key" %}</th>
</tr>
</thead>
<tbody>
{% for user_key in keys %}
<tr>
<td scope="row">{{user_key.name}}</td>
<td>
<button type="button" class="btn btn-default btn-custom-delete" data-toggle="modal"
data-target="#Modal{{ user_key.id }}" style="color: #717274">
<span class="pc-only">{% trans "Delete" %}</span>
<span class="mob-only"><i class="fa fa-trash"></i></span>
</button>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="modal fade" id="Modal{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete this key?" %}</h4>
<form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}">
{% csrf_token %}
<div class="modal-footer">
<button type="submit" class="btn btn-primary">{% trans "Delete" %}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</td>
<td>
<p type="button" data-toggle="modal" style="margin: 0" data-target="#Modal_public_key{{ user_key.id }}">
<a href="#">{% trans "Show" %}</a>
</p>
<div class="modal fade" id="Modal_public_key{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public ssh key" %}</h4>
<p style="margin-top: 10px;">{{ user_key.public_key }}</p>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close" %}
</button>
</div>
</div>
</div>
</div>
</div>
</td>
</td>
<td>
{% if user_key.private_key %}
<form action="{{ user_key.private_key.url }}">
<button style="color: #717274" type="submit" class="btn btn-default" data-toggle="modal"
>
<span class="pc-only">{% trans "Download" %}</span>
<span class="mob-only"><i class="fa fa-download"></i></span>
</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% if next_url %}

View file

@ -7,7 +7,7 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
VirtualMachineView, OrdersHostingDeleteView, NotificationsView, \
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, \
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, SSHKeyChoiceView
urlpatterns = [
url(r'index/?$', IndexView.as_view(), name='index'),
@ -27,6 +27,8 @@ urlpatterns = [
name='virtual_machines'),
url(r'ssh_keys/?$', SSHKeyListView.as_view(),
name='ssh_keys'),
url(r'ssh_keys_choice/?$', SSHKeyChoiceView.as_view(),
name='choice_ssh_keys'),
url(r'delete_ssh_key/(?P<pk>\d+)/?$', SSHKeyDeleteView.as_view(),
name='delete_ssh_key'),
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),

View file

@ -1,3 +1,7 @@
import uuid
from django.core.files.base import ContentFile
from oca.pool import WrongNameError, WrongIdError
from django.shortcuts import render
from django.http import Http404
@ -24,7 +28,7 @@ from utils.forms import BillingAddressForm, PasswordResetRequestForm, UserBillin
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
from utils.mailer import BaseEmail
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm, generate_ssh_key_name
from .mixins import ProcessVMSelectionMixin
from opennebula_api.models import OpenNebulaManager
@ -193,8 +197,10 @@ class SignupView(CreateView):
name = form.cleaned_data.get('name')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
this_base_url = "{0}://{1}".format(self.request.scheme, self.request.get_host())
CustomUser.register(name, password, email, app='dcl', base_url=this_base_url)
this_base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
CustomUser.register(name, password, email,
app='dcl', base_url=this_base_url)
return HttpResponseRedirect(reverse_lazy('hosting:signup-validate'))
@ -204,8 +210,10 @@ class SignupValidateView(TemplateView):
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>'
home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>'
login_url = '<a href="' + \
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
home_url = '<a href="' + \
reverse('datacenterlight:index') + '">Data Center Light</a>'
message = '{signup_success_message} {lurl}</a> \
<br />{go_back} {hurl}.'.format(
signup_success_message=_(
@ -226,15 +234,18 @@ class SignupValidatedView(SignupValidateView):
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
validated = CustomUser.validate_url(self.kwargs['validate_slug'])
login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>'
login_url = '<a href="' + \
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
section_title = _('Account activation')
if validated:
message = '{account_activation_string} <br /> {login_string} {lurl}.'.format(
account_activation_string=_("Your account has been activated."),
account_activation_string=_(
"Your account has been activated."),
login_string=_("You can now"),
lurl=login_url)
else:
home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>'
home_url = '<a href="' + \
reverse('datacenterlight:index') + '">Data Center Light</a>'
message = '{sorry_message} <br />{go_back_to} {hurl}'.format(
sorry_message=_("Sorry. Your request is invalid."),
go_back_to=_('Go back to'),
@ -364,10 +375,29 @@ class SSHKeyListView(LoginRequiredMixin, ListView):
def render_to_response(self, context, **response_kwargs):
if not self.queryset:
return HttpResponseRedirect(reverse('hosting:create_ssh_key'))
return HttpResponseRedirect(reverse('hosting:choice_ssh_keys'))
return super(SSHKeyListView, self).render_to_response(context, **response_kwargs)
class SSHKeyChoiceView(LoginRequiredMixin, View):
template_name = "hosting/choice_ssh_keys.html"
login_url = reverse_lazy('hosting:login')
def get(self, request, *args, **kwargs):
context = {}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
name = generate_ssh_key_name()
private_key, public_key = UserHostingKey.generate_keys()
content = ContentFile(private_key)
ssh_key = UserHostingKey.objects.create(
user=request.user, public_key=public_key, name=name)
filename = name + '_' + str(uuid.uuid4())[:8] + '_private.pem'
ssh_key.private_key.save(filename, content)
return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar')
class SSHKeyCreateView(LoginRequiredMixin, FormView):
form_class = UserHostingKeyForm
model = UserHostingKey
@ -383,6 +413,11 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
def form_valid(self, form):
form.save()
if 'dcl-generated-key-' 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(
@ -407,10 +442,11 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
manager = OpenNebulaManager()
# Get user ssh key
public_key = form.cleaned_data.get('public_key', '').decode('utf-8')
public_key = str(form.cleaned_data.get('public_key', ''))
# Add ssh key to user
try:
manager.add_public_key(user=owner, public_key=public_key, merge=True)
manager.add_public_key(
user=owner, public_key=public_key, merge=True)
except ConnectionError:
pass
except WrongNameError:
@ -421,6 +457,9 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
def post(self, request, *args, **kwargs):
print(self.request.POST.dict())
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:
@ -563,7 +602,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
# Create a Hosting Bill
HostingBill.create(
customer=customer, billing_address=billing_address)
customer=customer, billing_address=billing_address)
# Create Billing Address for User if he does not have one
if not customer.user.billing_addresses.count():