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:
		
					parent
					
						
							
								35e312411f
							
						
					
				
			
			
				commit
				
					
						b4164e56ab
					
				
			
		
					 7 changed files with 140 additions and 33 deletions
				
			
		
							
								
								
									
										21
									
								
								hosting/migrations/0018_virtualmachineplan_public_key.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								hosting/migrations/0018_virtualmachineplan_public_key.py
									
										
									
									
									
										Normal 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, | ||||
|         ), | ||||
|     ] | ||||
|  | @ -1,12 +1,14 @@ | |||
| import json | ||||
| import os | ||||
| 
 | ||||
| from django.db import models | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| from django.utils.functional import cached_property | ||||
| from django.core import serializers | ||||
| from membership.models import StripeCustomer | ||||
| from utils.models import BillingAddress | ||||
| 
 | ||||
| from Crypto.PublicKey import RSA | ||||
| 
 | ||||
| 
 | ||||
| from .managers import VMPlansManager | ||||
| 
 | ||||
| 
 | ||||
|  | @ -84,6 +86,7 @@ class VirtualMachinePlan(models.Model): | |||
|     disk_size = models.IntegerField() | ||||
|     vm_type = models.ForeignKey(VirtualMachineType) | ||||
|     price = models.FloatField() | ||||
|     public_key = models.TextField() | ||||
| 
 | ||||
|     objects = VMPlansManager() | ||||
| 
 | ||||
|  | @ -104,20 +107,24 @@ class VirtualMachinePlan(models.Model): | |||
|         instance = cls.objects.create(**data) | ||||
|         return instance | ||||
| 
 | ||||
|     @classmethod | ||||
|     @staticmethod | ||||
|     def generate_RSA(bits=2048): | ||||
|         ''' | ||||
|         Generate an RSA keypair with an exponent of 65537 in PEM format | ||||
|         param: bits The key length in bits | ||||
|         Return private key and public key | ||||
|         ''' | ||||
|         from Crypto.PublicKey import RSA | ||||
|         import os | ||||
|         new_key = RSA.generate(2048, os.urandom) | ||||
|         public_key = new_key.publickey() | ||||
|         private_key = new_key.exportKey("OpenSSH") | ||||
|         public_key = new_key.publickey().exportKey("OpenSSH") | ||||
|         private_key = new_key.exportKey("PEM") | ||||
|         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): | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										42
									
								
								hosting/static/hosting/js/gen-ssh-key.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								hosting/static/hosting/js/gen-ssh-key.js
									
										
									
									
									
										Normal 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); | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
|  | @ -163,6 +163,9 @@ | |||
|     <!-- Proccess payment lib --> | ||||
|     <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> | ||||
| 
 | ||||
| </html> | ||||
|  |  | |||
|  | @ -58,7 +58,13 @@ | |||
|                 <hr> | ||||
|                 <h4>Total<p class="pull-right"><b>{{order.vm_plan.price}} CHF</b></p></h4> | ||||
|             </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> | ||||
|  |  | |||
|  | @ -6,25 +6,58 @@ | |||
| 		<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> Private Key</h3> | ||||
| 
 | ||||
| 				        <h3><i class="fa fa-key" aria-hidden="true"></i> SSH Private Key</h3> | ||||
| 				        <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"> | ||||
| 						  <label for="comment">private_key.pem</label> | ||||
| 						  <textarea class="form-control" rows="8" 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>  | ||||
| 						  <textarea class="form-control" rows="6" id="ssh_key">{{private_key}}</textarea> | ||||
| 
 | ||||
| 						</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> | ||||
| 			</div> | ||||
| 
 | ||||
| 	    </div> | ||||
| 	</div> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
| {% if private_key %} | ||||
| <!-- Force to download ssh key on page load --> | ||||
| <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> | ||||
| {%endif%} | ||||
| 
 | ||||
| 
 | ||||
| {%endblock%} | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -145,29 +145,23 @@ class SignupView(CreateView): | |||
|         return HttpResponseRedirect(self.get_success_url()) | ||||
| 
 | ||||
| 
 | ||||
| class GenerateVMSSHKeysView(LoginRequiredMixin, UpdateView): | ||||
| class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView): | ||||
|     model = VirtualMachinePlan | ||||
|     template_name = 'hosting/virtual_machine_key.html' | ||||
|     success_url = reverse_lazy('hosting:orders') | ||||
|     context_object_name = "virtual_machine" | ||||
| 
 | ||||
|     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): | ||||
|     #     vm = self.get_object() | ||||
|     #     private_key, public_key = VirtualMachinePlan.generate_RSA() | ||||
|     #     print(private_key) | ||||
|     #     print(public_key) | ||||
|     #     key_name = "private_key" | ||||
|     #     response = HttpResponse(content_type='text/plain') | ||||
|     #     response['Content-Disposition'] = 'attachment; filename="%s.pem"' % key_name | ||||
|     #     response.write(private_key) | ||||
|     #     return response | ||||
|         # return HttpResponseRedirect(reverse('')) | ||||
|         context = super(GenerateVMSSHKeysView, self).get_context_data(**kwargs) | ||||
|         vm = self.get_object() | ||||
|         if not vm.public_key: | ||||
|             private_key = vm.generate_keys() | ||||
|             context.update({ | ||||
|                 'private_key': private_key | ||||
|             }) | ||||
|             return context | ||||
|         return context | ||||
| 
 | ||||
| 
 | ||||
| class PaymentVMView(LoginRequiredMixin, FormView): | ||||
|  | @ -269,7 +263,8 @@ class OrdersHostingListView(LoginRequiredMixin, ListView): | |||
|         self.queryset = HostingOrder.objects.filter(customer__user=user) | ||||
|         return super(OrdersHostingListView, self).get_queryset() | ||||
| 
 | ||||
| class OrdersHostingDeleteView(LoginRequiredMixin,DeleteView): | ||||
| 
 | ||||
| class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView): | ||||
|     login_url=reverse_lazy('hosting:login') | ||||
|     success_url = reverse_lazy('hosting:orders') | ||||
|     model = HostingOrder | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue