Commit c38e0610 by Kálmán Viktor

dashboard: template acl

parent 3f0ef5e7
from datetime import timedelta
import uuid
from django.contrib.auth.models import User
from crispy_forms.helper import FormHelper
from crispy_forms.layout import (
Layout, Div, BaseInput, Field, HTML, Submit, Fieldset, TEMPLATE_PACK
......@@ -430,8 +432,16 @@ class TemplateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
parent = kwargs.pop("parent", None)
self.user = kwargs.pop("user", None)
super(TemplateForm, self).__init__(*args, **kwargs)
self.fields['disks'] = forms.ModelMultipleChoiceField(queryset=DISKS)
self.fields['disks'] = forms.ModelMultipleChoiceField(
queryset=Disk.get_objects_with_level(
'user', self.user).exclude(type="qcow2-snap")
)
data = self.data.copy()
data['owner'] = self.user.pk
self.data = data
if parent is not None:
template = InstanceTemplate.objects.get(pk=parent)
......@@ -458,6 +468,11 @@ class TemplateForm(forms.ModelForm):
self.instance.ram_size = 512
self.instance.num_cores = 2
def clean_owner(self):
if self.instance.pk is not None:
return User.objects.get(pk=self.instance.owner.pk)
return self.user
def save(self, commit=True):
data = self.cleaned_data
self.instance.max_ram_size = data.get('ram_size')
......
......@@ -4,11 +4,11 @@
{% block content %}
<div class="row">
<div class="col-md-12">
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-heading">
<a class="pull-right btn btn-default btn-xs" href="{% url "dashboard.views.template-list" %}">Back</a>
<h3 class="no-margin"><i class="icon-desktop"></i> Edit template</h3>
<h3 class="no-margin"><i class="icon-desktop"></i> {% trans "Edit template" %}</h3>
</div>
<div class="panel-body">
{% with form=form %}
......@@ -18,8 +18,56 @@
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="no-margin"><i class="icon-group"></i> {% trans "Manage access" %}</h3>
</div>
<div class="panel-body">
<form action="{% url "dashboard.views.template-acl" pk=object.pk %}" method="post">{% csrf_token %}
<table class="table table-striped table-with-form-fields">
<thead><tr><th></th><th>{% trans "Who" %}</th><th>{% trans "What" %}</th><th></th></tr></thead>
<tbody>
{% for i in acl.users %}
<tr><td><i class="icon-user"></i></td><td>{{i.user}}</td>
<td><select class="form-control" name="perm-u-{{i.user.id}}">
{% for id, name in acl.levels %}
<option{%if id = i.level%} selected="selected"{%endif%} value="{{id}}">{{name}}</option>
{% endfor %}
</select></td>
<td><a href="#" class="btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a></td></tr>
{% endfor %}
{% for i in acl.groups %}
<tr><td><i class="icon-group"></i></td><td>{{i.group}}</td>
<td><select class="form-control" name="perm-g-{{i.group.id}}">
{% for id, name in acl.levels %}
<option{%if id = i.level%} selected="selected"{%endif%} value="{{id}}">{{name}}</option>
{% endfor %}
</select></td>
<td><a href="#" class="btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a></td></tr>
{% endfor %}
<tr><td><i class="icon-plus"></i></td>
<td><input type="text" class="form-control" name="perm-new-name"
placeholder="{% trans "Name of group or user" %}"></td>
<td><select class="form-control" name="perm-new">
{% for id, name in acl.levels %}
<option value="{{id}}">{{name}}</option>
{% endfor %}
</select></td><td></td>
</tr>
</tbody>
</table>
<div class="form-actions">
<button type="submit" class="btn btn-success">{% trans "Save" %}</button>
</div>
</form>
</div>
</div>
</div>
</div>
<style>
fieldset {
margin-top: 40px;
......
......@@ -7,7 +7,7 @@ from .views import (
TransferOwnershipView, TransferOwnershipConfirmView, NodeDelete,
TemplateList, LeaseDetail, NodeCreate, LeaseCreate, TemplateCreate,
FavouriteView, NodeStatus, GroupList, TemplateDelete, LeaseDelete,
VmGraphView,
VmGraphView, TemplateAclUpdateView
)
urlpatterns = patterns(
......@@ -19,14 +19,18 @@ urlpatterns = patterns(
name="dashboard.views.lease-create"),
url(r'^lease/delete/(?P<pk>\d+)/$', LeaseDelete.as_view(),
name="dashboard.views.lease-delete"),
url(r'^template/create/$', TemplateCreate.as_view(),
name="dashboard.views.template-create"),
url(r'template/(?P<pk>\d+)/acl/$', TemplateAclUpdateView.as_view(),
name='dashboard.views.template-acl'),
url(r'^template/(?P<pk>\d+)/$', TemplateDetail.as_view(),
name='dashboard.views.template-detail'),
url(r"^template/list/$", TemplateList.as_view(),
name="dashboard.views.template-list"),
url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(),
name="dashboard.views.template-delete"),
url(r'^vm/(?P<pk>\d+)/remove_port/(?P<rule>\d+)/$', PortDelete.as_view(),
name='dashboard.views.remove-port'),
url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(),
......@@ -43,6 +47,7 @@ urlpatterns = patterns(
url(r'^vm/mass-delete/', VmMassDelete.as_view(),
name='dashboard.view.mass-delete-vm'),
url(r'^vm/(?P<pk>\d+)/activity/$', vm_activity),
url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'),
url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(),
name='dashboard.views.node-detail'),
......@@ -54,8 +59,10 @@ urlpatterns = patterns(
name="dashboard.views.status-node"),
url(r'^node/create/$', NodeCreate.as_view(),
name='dashboard.views.node-create'),
url(r'^favourite/$', FavouriteView.as_view(),
name='dashboard.views.favourite'),
url(r'^group/list/$', GroupList.as_view(),
name='dashboard.views.group-list'),
url((r'^vm/(?P<pk>\d+)/graph/(?P<metric>cpu|memory|network)/'
......
......@@ -487,6 +487,29 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
value, unicode(request.user))
class TemplateAclUpdateView(AclUpdateView):
model = InstanceTemplate
def post(self, request, *args, **kwargs):
template = self.get_object()
if not (template.has_level(request.user, "owner") or
getattr(template, 'owner', None) == request.user):
logger.warning('Tried to set permissions of %s by non-owner %s.',
unicode(template), unicode(request.user))
raise PermissionDenied()
self.set_levels(request, template)
self.add_levels(request, template)
post_for_disk = request.POST.copy()
post_for_disk['perm-new'] = 'user'
request.POST = post_for_disk
for d in template.disks.all():
self.add_levels(request, d)
return redirect(reverse("dashboard.views.template-detail",
kwargs=self.kwargs))
class TemplateCreate(SuccessMessageMixin, CreateView):
model = InstanceTemplate
form_class = TemplateForm
......@@ -496,27 +519,28 @@ class TemplateCreate(SuccessMessageMixin, CreateView):
def get(self, *args, **kwargs):
if not self.request.user.has_perm('vm.create_template'):
raise PermissionDenied()
form = self.form_class()
form.fields['disks'].queryset = Disk.get_objects_with_level(
'user', self.request.user).exclude(type="qcow2-snap")
self.parent = self.request.GET.get("parent")
return super(TemplateCreate, self).get(*args, **kwargs)
def get_form_kwargs(self):
kwargs = super(TemplateCreate, self).get_form_kwargs()
kwargs['parent'] = getattr(self, "parent", None)
kwargs['user'] = self.request.user
return kwargs
def post(self, request, *args, **kwargs):
if not self.request.user.has_perm('vm.create_template'):
raise PermissionDenied()
form = self.form_class(request.POST)
form = self.form_class(request.POST, user=request.user)
if not form.is_valid():
return self.get(request, form, *args, **kwargs)
post = form.cleaned_data
for disk in post['disks']:
if not disk.has_level(request.user, 'user'):
raise PermissionDenied()
return super(TemplateCreate, self).post(self, request, args, kwargs)
def get_success_url(self):
......@@ -556,6 +580,11 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
else:
return super(TemplateDetail, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(TemplateDetail, self).get_context_data(**kwargs)
context['acl'] = get_acl_data(self.get_object())
return context
def get_success_url(self):
return reverse_lazy("dashboard.views.template-detail",
kwargs=self.kwargs)
......@@ -569,6 +598,11 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
raise PermissionDenied()
return super(TemplateDetail, self).post(self, request, args, kwargs)
def get_form_kwargs(self):
kwargs = super(TemplateDetail, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
class TemplateList(LoginRequiredMixin, SingleTableView):
template_name = "dashboard/template-list.html"
......
......@@ -147,6 +147,12 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel):
else:
return 'linux'
def save(self, *args, **kwargs):
is_new = getattr(self, "pk", None) is None
super(InstanceTemplate, self).save(*args, **kwargs)
if is_new:
self.set_level(self.owner, 'owner')
class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment