Added next button in order detail view after the user make a payment, Avoid to regenerate SSH Key if the user refresh the page, Now the key is served to download from javascript , Added public_key attribute to VirtualVMPlan in order to store keys created by the user, Now private key has PEM format and public has OpenSSH

This commit is contained in:
Levi 2016-05-24 01:19:49 -05:00
parent 35e312411f
commit b4164e56ab
7 changed files with 140 additions and 33 deletions

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-05-24 03:57
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hosting', '0017_virtualmachinetype_location'),
]
operations = [
migrations.AddField(
model_name='virtualmachineplan',
name='public_key',
field=models.TextField(default='sada'),
preserve_default=False,
),
]

View file

@ -1,12 +1,14 @@
import json import os
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.core import serializers
from membership.models import StripeCustomer from membership.models import StripeCustomer
from utils.models import BillingAddress from utils.models import BillingAddress
from Crypto.PublicKey import RSA
from .managers import VMPlansManager from .managers import VMPlansManager
@ -84,6 +86,7 @@ class VirtualMachinePlan(models.Model):
disk_size = models.IntegerField() disk_size = models.IntegerField()
vm_type = models.ForeignKey(VirtualMachineType) vm_type = models.ForeignKey(VirtualMachineType)
price = models.FloatField() price = models.FloatField()
public_key = models.TextField()
objects = VMPlansManager() objects = VMPlansManager()
@ -104,20 +107,24 @@ class VirtualMachinePlan(models.Model):
instance = cls.objects.create(**data) instance = cls.objects.create(**data)
return instance return instance
@classmethod @staticmethod
def generate_RSA(bits=2048): def generate_RSA(bits=2048):
''' '''
Generate an RSA keypair with an exponent of 65537 in PEM format Generate an RSA keypair with an exponent of 65537 in PEM format
param: bits The key length in bits param: bits The key length in bits
Return private key and public key Return private key and public key
''' '''
from Crypto.PublicKey import RSA
import os
new_key = RSA.generate(2048, os.urandom) new_key = RSA.generate(2048, os.urandom)
public_key = new_key.publickey() public_key = new_key.publickey().exportKey("OpenSSH")
private_key = new_key.exportKey("OpenSSH") private_key = new_key.exportKey("PEM")
return private_key, public_key return private_key, public_key
def generate_keys(self):
private_key, public_key = self.generate_RSA()
self.public_key = public_key
self.save(update_fields=['public_key'])
return private_key
class HostingOrder(models.Model): class HostingOrder(models.Model):

View file

@ -0,0 +1,42 @@
$( document ).ready(function() {
// Create a file with ssh private key info
function donwloadKeyFile(){
var key = $('#ssh_key').text();
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([key], {type: 'text'}));
a.download = 'private_key.pem';
// Append anchor to body.
document.body.appendChild(a);
a.click();
// Remove anchor from body
document.body.removeChild(a);
}
// Create a file with ssh private key info
$('#download_ssh_key').on('click',donwloadKeyFile);
$('[data-toggle="tooltip"]').tooltip();
var clipboard = new Clipboard('#copy_to_clipboard');
clipboard.on('success', function(e) {
var selector = "#";
var copy_button_id = selector.concat(e.trigger.id);
setTimeout(function(){
$(copy_button_id).tooltip('hide');
}, 1000);
});
});

View file

@ -163,6 +163,9 @@
<!-- Proccess payment lib --> <!-- Proccess payment lib -->
<script type="text/javascript" src="{% static 'hosting/js/payment.js' %}"></script> <script type="text/javascript" src="{% static 'hosting/js/payment.js' %}"></script>
<!-- Gen SSH Key lib -->
<script type="text/javascript" src="{% static 'hosting/js/gen-ssh-key.js' %}"></script>
</body> </body>
</html> </html>

View file

@ -58,7 +58,13 @@
<hr> <hr>
<h4>Total<p class="pull-right"><b>{{order.vm_plan.price}} CHF</b></p></h4> <h4>Total<p class="pull-right"><b>{{order.vm_plan.price}} CHF</b></p></h4>
</div> </div>
<a href="{% url 'hosting:virtual_machines' order.vm_plan.id %}" class="pull-right"><button class="btn-info">View instance</button></a> <br/>
{% url 'hosting:payment' as payment_url %}
{% if payment_url in request.META.HTTP_REFERER %}
<div class=" content pull-right">
<a href="{% url 'hosting:virtual_machine_key' order.vm_plan.id %}" ><button class="btn btn-info">Finish Configuration</button></a>
</div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>

View file

@ -6,25 +6,58 @@
<div class="row"> <div class="row">
<div class="col-md-9 col-md-offset-2"> <div class="col-md-9 col-md-offset-2">
<div class="col-sm-12"> <div class="col-sm-12">
<h3><i class="fa fa-key" aria-hidden="true"></i> Private Key</h3>
<h3><i class="fa fa-key" aria-hidden="true"></i> SSH Private Key</h3>
<hr/> <hr/>
{% if private_key %}
<div class="alert alert-warning">
<strong>Warning!</strong> You can view your SSH private key once. Copy it or if it wasn't downloaded automatically, just click on Download to start it.
</div>
<div class="form-group"> <div class="form-group">
<label for="comment">private_key.pem</label> <label for="comment">private_key.pem</label>
<textarea class="form-control" rows="8" id="ssh_key">{{private_key}}</textarea> <textarea class="form-control" rows="6" id="ssh_key">{{private_key}}</textarea>
<span class="h3 pull-right"><button type="button" class="btn btn-default"><a href=""> Download </a></button></span>
<span class="h3 pull-right"><button type="button" data-clipboard-target="#ssh_key" class="btn btn-default">Copy to Clipboard</button></span>
</div> </div>
<div class="form-group pull-right">
<button type="button" id="copy_to_clipboard" data-clipboard-target="#ssh_key" class="btn btn-warning"
data-toggle="tooltip" data-placement="bottom" title="Copied" data-trigger="click">Copy to Clipboard</button>
<button type="button" id="download_ssh_key" class="btn btn-warning">Download</button>
</div>
{% else %}
<div class="alert alert-warning">
<strong>Warning!</strong> Your SSH private key was already generated and downloaded, if you lost it, contact us.
</div>
{% endif %}
<a class="btn btn-success" href="{% url 'hosting:virtual_machines' virtual_machine.id %}"> Go to my Virtual Machine Dashboard</a>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% if private_key %}
<!-- Force to download ssh key on page load -->
<script type="text/javascript"> <script type="text/javascript">
(function () {new Clipboard('.btn');})();
var key = window.document.getElementById('ssh_key');
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob(['key'], {type: 'text'}));
a.download = 'private_key.pem';
// Append anchor to body.
document.body.appendChild(a);
a.click();
// Remove anchor from body
document.body.removeChild(a);
</script> </script>
{%endif%}
{%endblock%} {%endblock%}

View file

@ -145,29 +145,23 @@ class SignupView(CreateView):
return HttpResponseRedirect(self.get_success_url()) return HttpResponseRedirect(self.get_success_url())
class GenerateVMSSHKeysView(LoginRequiredMixin, UpdateView): class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView):
model = VirtualMachinePlan model = VirtualMachinePlan
template_name = 'hosting/virtual_machine_key.html' template_name = 'hosting/virtual_machine_key.html'
success_url = reverse_lazy('hosting:orders') success_url = reverse_lazy('hosting:orders')
context_object_name = "virtual_machine"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
private_key, public_key = VirtualMachinePlan.generate_RSA()
context = {
'private_key': private_key
}
return context
# def get(self, *args, **kwargs): context = super(GenerateVMSSHKeysView, self).get_context_data(**kwargs)
# vm = self.get_object() vm = self.get_object()
# private_key, public_key = VirtualMachinePlan.generate_RSA() if not vm.public_key:
# print(private_key) private_key = vm.generate_keys()
# print(public_key) context.update({
# key_name = "private_key" 'private_key': private_key
# response = HttpResponse(content_type='text/plain') })
# response['Content-Disposition'] = 'attachment; filename="%s.pem"' % key_name return context
# response.write(private_key) return context
# return response
# return HttpResponseRedirect(reverse(''))
class PaymentVMView(LoginRequiredMixin, FormView): class PaymentVMView(LoginRequiredMixin, FormView):
@ -269,6 +263,7 @@ class OrdersHostingListView(LoginRequiredMixin, ListView):
self.queryset = HostingOrder.objects.filter(customer__user=user) self.queryset = HostingOrder.objects.filter(customer__user=user)
return super(OrdersHostingListView, self).get_queryset() return super(OrdersHostingListView, self).get_queryset()
class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView): class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView):
login_url=reverse_lazy('hosting:login') login_url=reverse_lazy('hosting:login')
success_url = reverse_lazy('hosting:orders') success_url = reverse_lazy('hosting:orders')