Allow users to delete ssh keys

This commit is contained in:
Modulos 2017-06-03 15:03:55 +02:00
parent ab29b138c3
commit 346733fbcd
6 changed files with 250 additions and 202 deletions

View file

@ -85,7 +85,7 @@
<ul id="g-account-menu" class="dropdown-menu" role="menu"> <ul id="g-account-menu" class="dropdown-menu" role="menu">
<li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li> <li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li>
<li> <li>
<a href="{% url 'hosting:key_pair' %}"> <a href="{% url 'hosting:ssh_keys' %}">
<i class="fa fa-key"></i> {% trans "Keys"%} <i class="fa fa-key"></i> {% trans "Keys"%}
</a> </a>
</li> </li>
@ -149,7 +149,7 @@
<li>&sdot;</li> <li>&sdot;</li>
<li> <li>
<li> <li>
<a href="{% url 'hosting:key_pair' %}"> <a href="{% url 'hosting:ssh_keys' %}">
{% trans "Keys"%} {% trans "Keys"%}
</a> </a>
</li> </li>

View file

@ -0,0 +1,92 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% 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">
<form method="POST" action="" novalidate>
{% csrf_token %}
<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 %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-success">
{% trans "Upload your own key. "%}
</button>
<br />
<br />
{% trans "Or generate a new key pair."%} <br />
<br />
<button class="btn btn-success">{% trans "Generate Key Pair"%} </a>
</button>
{% 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>
</div>
</div>
</div>
</div>
{% if private_key %}
<!-- Force to download ssh key on page load -->
<script type="text/javascript">
var key = window.document.getElementById('ssh_key');
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([key.value], {type: 'text'}));
a.download = '{{key_name}}.pem';
// Append anchor to body.
document.body.appendChild(a);
a.click();
// Remove anchor from body
document.body.removeChild(a);
</script>
{%endif%}
{% if next_url %}
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
{%endblock%}

View file

@ -0,0 +1,96 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% 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>{{user_key.created_at}}</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">
<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="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close"%}
</button>
<button type="submit" class="btn btn-primary">{% trans "Delete"%}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</div>
{% if next_url %}
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
{%endblock%}

View file

@ -1,163 +0,0 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% 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">
<form method="POST" action="" novalidate>
{% csrf_token %}
<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 %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-success">
{% trans "Upload your own key. "%}
</button>
<br />
<br />
{% trans "Or generate a new key pair."%} <br />
<br />
<button class="btn btn-success">{% trans "Generate Key Pair"%} </a>
</button>
{% endbuttons %}
<div class="form-group">
</div>
<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>{{user_key.created_at}}</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">
<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="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close"%}
</button>
<button type="submit" class="btn btn-primary">{% trans "Delete"%}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</tr>
{% endfor %}
</tbody>
</table>
</form>
{% 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>
<!-- <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">{% trans "Copy to Clipboard"%}</button>
<button type="button" id="download_ssh_key" class="btn btn-warning">{% trans "Download"%}</button>
</div> -->
{% else %}
<!-- <div class="alert alert-warning">
<strong>{% trans "Warning!"%}</strong>{% trans "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' %}">{% trans "Generate my key"%} </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">
var key = window.document.getElementById('ssh_key');
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([key.value], {type: 'text'}));
a.download = '{{key_name}}.pem';
// Append anchor to body.
document.body.appendChild(a);
a.click();
// Remove anchor from body
document.body.removeChild(a);
</script>
{%endif%}
{% if next_url %}
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
{%endblock%}

View file

@ -3,9 +3,10 @@ from django.conf.urls import url
from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
NodeJSHostingView, LoginView, SignupView, IndexView, \ NodeJSHostingView, LoginView, SignupView, IndexView, \
OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\ OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \ VirtualMachineView, OrdersHostingDeleteView, NotificationsView, \
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\ MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, SSHKeyDeleteView CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, \
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView
urlpatterns = [ urlpatterns = [
url(r'index/?$', IndexView.as_view(), name='index'), url(r'index/?$', IndexView.as_view(), name='index'),
@ -23,12 +24,12 @@ urlpatterns = [
url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'), url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'),
url(r'my-virtual-machines/(?P<pk>\d+)/?$', VirtualMachineView.as_view(), url(r'my-virtual-machines/(?P<pk>\d+)/?$', VirtualMachineView.as_view(),
name='virtual_machines'), name='virtual_machines'),
# url(r'my-virtual-machines/(?P<pk>\d+)/delete/?$', VirtualMachineCancelView.as_view(), url(r'ssh_keys/?$', SSHKeyListView.as_view(),
# name='virtual_machines_cancel'), name='ssh_keys'),
url(r'vm-key-pair/?$', GenerateVMSSHKeysView.as_view(),
name='key_pair'),
url(r'delete_ssh_key/(?P<pk>\d+)/?$', SSHKeyDeleteView.as_view(), url(r'delete_ssh_key/(?P<pk>\d+)/?$', SSHKeyDeleteView.as_view(),
name='delete_ssh_key'), name='delete_ssh_key'),
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),
name='create_ssh_key'),
url(r'^notifications/$', NotificationsView.as_view(), name='notifications'), url(r'^notifications/$', NotificationsView.as_view(), name='notifications'),
url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(), url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(),
name='read_notification'), name='read_notification'),

View file

@ -188,7 +188,7 @@ class SignupView(CreateView):
template_name = 'hosting/signup.html' template_name = 'hosting/signup.html'
form_class = HostingUserSignupForm form_class = HostingUserSignupForm
model = CustomUser model = CustomUser
success_url = reverse_lazy('hosting:key_pair') success_url = reverse_lazy('hosting:ssh_keys')
def get_success_url(self): def get_success_url(self):
next_url = self.request.session.get( next_url = self.request.session.get(
@ -290,34 +290,56 @@ class MarkAsReadNotificationView(LoginRequiredMixin, UpdateView):
class SSHKeyDeleteView(LoginRequiredMixin, DeleteView): class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
login_url = reverse_lazy('hosting:login') login_url = reverse_lazy('hosting:login')
success_url = reverse_lazy('hosting:key-pair') success_url = reverse_lazy('hosting:ssh_keys')
model = UserHostingKey model = UserHostingKey
class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): def delete(self, request, *args, **kwargs):
owner = self.request.user
manager = OpenNebulaManager()
pk = self.kwargs.get('pk')
# Get user ssh key
public_key = UserHostingKey.objects.get(pk=pk)
# Add ssh key to user
try:
manager.remove_public_key(user=owner, public_key=public_key)
except ConnectionError:
pass
except WrongNameError:
pass
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
class SSHKeyListView(LoginRequiredMixin, ListView):
template_name = "hosting/user_keys.html"
login_url = reverse_lazy('hosting:login')
context_object_name = "keys"
model = UserHostingKey
paginate_by = 10
ordering = '-id'
def get_queryset(self):
user = self.request.user
self.queryset = UserHostingKey.objects.filter(user=user)
return super(SSHKeyListView, self).get_queryset()
def render_to_response(self, context, **response_kwargs):
if not self.queryset:
return HttpResponseRedirect(reverse('hosting:create_ssh_key'))
return super(SSHKeyListView, self).render_to_response(context, **response_kwargs)
class SSHKeyCreateView(LoginRequiredMixin, FormView):
form_class = UserHostingKeyForm form_class = UserHostingKeyForm
model = UserHostingKey model = UserHostingKey
template_name = 'hosting/virtual_machine_key.html' template_name = 'hosting/user_key.html'
login_url = reverse_lazy('hosting:login') login_url = reverse_lazy('hosting:login')
context_object_name = "virtual_machine" context_object_name = "virtual_machine"
success_url = reverse_lazy('hosting:ssh_keys')
def get_context_data(self, **kwargs):
context = super(
GenerateVMSSHKeysView,
self
).get_context_data(**kwargs)
user_keys = UserHostingKey.objects.filter(
user=self.request.user
)
context.update({
'keys': user_keys
})
return context
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(GenerateVMSSHKeysView, self).get_form_kwargs() kwargs = super(SSHKeyCreateView, self).get_form_kwargs()
kwargs.update({'request': self.request}) kwargs.update({'request': self.request})
return kwargs return kwargs
@ -344,22 +366,22 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView):
}) })
owner = self.request.user owner = self.request.user
# Create OpenNebulaManager manager = OpenNebulaManager()
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# Get OpenNebula user id
user_pool = manager._get_user_pool()
opennebula_user = user_pool.get_by_name(owner.email)
# Get user ssh key # Get user ssh key
public_key = form.cleaned_data.get('public_key') public_key = form.cleaned_data.get('public_key')
# Add ssh key to user # Add ssh key to user
manager.oneadmin_client.call('user.update', opennebula_user.id, try:
'<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key)) manager.add_public_key(user=owner, public_key=public_key, merge=True)
except ConnectionError:
pass
except WrongNameError:
pass
return render(self.request, self.template_name, context) return HttpResponseRedirect(self.success_url)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
print(self.request.POST.dict())
form = self.get_form() form = self.get_form()
if form.is_valid(): if form.is_valid():
return self.form_valid(form) return self.form_valid(form)
@ -417,7 +439,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
request, request,
'In order to create a VM, you create/upload your SSH KEY first.' 'In order to create a VM, you create/upload your SSH KEY first.'
) )
return HttpResponseRedirect(reverse('hosting:key_pair')) return HttpResponseRedirect(reverse('hosting:ssh_keys'))
if 'next' in request.session: if 'next' in request.session:
del request.session['next'] del request.session['next']
@ -633,7 +655,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
request, request,
'In order to create a VM, you need to create/upload your SSH KEY first.' 'In order to create a VM, you need to create/upload your SSH KEY first.'
) )
return HttpResponseRedirect(reverse('hosting:key_pair')) return HttpResponseRedirect(reverse('hosting:ssh_keys'))
try: try:
manager = OpenNebulaManager() manager = OpenNebulaManager()