Commit 3cf09597 by Bach Dániel

Merge branch 'feature-group-details-fixed'

Conflicts:
	circle/dashboard/static/dashboard/dashboard.js
	circle/dashboard/urls.py
parents 2d8071b0 9871de77
...@@ -19,11 +19,11 @@ from __future__ import absolute_import ...@@ -19,11 +19,11 @@ from __future__ import absolute_import
from datetime import timedelta from datetime import timedelta
from django.contrib.auth.models import User
from django.contrib.auth.forms import ( from django.contrib.auth.forms import (
AuthenticationForm, PasswordResetForm, SetPasswordForm, AuthenticationForm, PasswordResetForm, SetPasswordForm,
PasswordChangeForm, PasswordChangeForm,
) )
from django.contrib.auth.models import User, Group
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import ( from crispy_forms.layout import (
...@@ -312,6 +312,55 @@ class VmCustomizeForm(forms.Form): ...@@ -312,6 +312,55 @@ class VmCustomizeForm(forms.Form):
) )
class GroupCreateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(GroupCreateForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.layout = Layout(
Div(
Div(
AnyTag(
'h4',
HTML(_("Name")),
),
css_class="col-sm-10",
),
css_class="row",
),
Div(
Div(
Field('name', id="group-create-name"),
css_class="col-sm-10",
),
css_class="row",
),
Div( # buttons
Div(
AnyTag( # tip: don't try to use Button class
"button",
AnyTag(
"i",
css_class="icon-play"
),
HTML(" Create"),
css_id="vm-create-submit",
css_class="btn btn-success",
),
css_class="col-sm-5",
),
css_class="row",
),
)
class Meta:
model = Group
fields = ['name', ]
class HostForm(forms.ModelForm): class HostForm(forms.ModelForm):
def setowner(self, user): def setowner(self, user):
......
...@@ -26,7 +26,7 @@ from django.contrib.auth.signals import user_logged_in ...@@ -26,7 +26,7 @@ from django.contrib.auth.signals import user_logged_in
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import ( from django.db.models import (
Model, ForeignKey, OneToOneField, CharField, IntegerField, TextField, Model, ForeignKey, OneToOneField, CharField, IntegerField, TextField,
DateTimeField, DateTimeField, permalink,
) )
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _, override, ugettext from django.utils.translation import ugettext_lazy as _, override, ugettext
...@@ -111,6 +111,11 @@ class GroupProfile(AclBase): ...@@ -111,6 +111,11 @@ class GroupProfile(AclBase):
except cls.DoesNotExist: except cls.DoesNotExist:
return Group.objects.get(name=name) return Group.objects.get(name=name)
@permalink
def get_absolute_url(self):
return ('dashboard.views.group-detail', None,
{'pk': self.group.pk})
def get_or_create_profile(self): def get_or_create_profile(self):
obj, created = GroupProfile.objects.get_or_create(group_id=self.pk) obj, created = GroupProfile.objects.get_or_create(group_id=self.pk)
......
...@@ -607,3 +607,26 @@ footer a, footer a:hover, footer a:visited { ...@@ -607,3 +607,26 @@ footer a, footer a:hover, footer a:visited {
#notifications-button { #notifications-button {
margin: 0; margin: 0;
} }
#group-detail-user-table td:first-child, #group-detail-user-table th:last-child,
#group-detail-user-table td:last-child,
#group-detail-perm-table td:first-child, #group-detail-perm-table th:last-child,
#group-detail-perm-table td:last-child {
text-align: center;
width: 100px;
}
#group-detail-perm-header {
margin-top: 25px;
}
textarea[name="list-new-namelist"] {
max-width: 500px;
min-height: 80px;
margin-bottom: 10px;
}
/* 2px border bottom for all bootstrap tables */
.table thead>tr>th {
border-bottom: 1px;
}
...@@ -34,6 +34,22 @@ $(function () { ...@@ -34,6 +34,22 @@ $(function () {
return false; return false;
}); });
$('.group-create').click(function(e) {
$.ajax({
type: 'GET',
url: '/dashboard/group/create/',
success: function(data) {
$('body').append(data);
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
return false;
});
$('.template-choose').click(function(e) { $('.template-choose').click(function(e) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
......
/* rename */ /* rename */
$("#group-details-h1-name, .group-details-rename-button").click(function() { $("#group-details-h1-name, .group-details-rename-button").click(function() {
$("#group-details-h1-name").hide(); $("#group-details-h1-name").hide();
...@@ -30,4 +29,38 @@ ...@@ -30,4 +29,38 @@
$(".group-details-help").stop().slideToggle(); $(".group-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.delete-from-group').click(function() {
var href = $(this).attr('href');
var tr = $(this).closest('tr');
var group = $(this).data('group_pk');
var member = $(this).data('member_pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(removeMember,
{ 'url': href,
'data': [],
'tr': tr,
'group_pk': group,
'member_pk': member,
'type': "user",
'redirect': dir});
return false;
});
function removeMember(data) {
$.ajax({
type: 'POST',
url: data['url'],
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
data['tr'].fadeOut(function() {
$(this).remove();});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger')
}
});
}
...@@ -99,7 +99,7 @@ $(function() { ...@@ -99,7 +99,7 @@ $(function() {
$("#group-list-column-name", row).html( $("#group-list-column-name", row).html(
$("<a/>", { $("<a/>", {
'class': "real-link", 'class': "real-link",
href: "/dashboard/group/" + data['node_pk'] + "/", href: "/dashboard/group/" + data['group_pk'] + "/",
text: data['new_name'] text: data['new_name']
}) })
).show(); ).show();
......
...@@ -134,16 +134,19 @@ class GroupListTable(Table): ...@@ -134,16 +134,19 @@ class GroupListTable(Table):
) )
number_of_users = TemplateColumn( number_of_users = TemplateColumn(
orderable=False,
template_name='dashboard/group-list/column-users.html', template_name='dashboard/group-list/column-users.html',
attrs={'th': {'class': 'group-list-table-admin'}}, attrs={'th': {'class': 'group-list-table-admin'}},
) )
admin = TemplateColumn( admin = TemplateColumn(
orderable=False,
template_name='dashboard/group-list/column-admin.html', template_name='dashboard/group-list/column-admin.html',
attrs={'th': {'class': 'group-list-table-admin'}}, attrs={'th': {'class': 'group-list-table-admin'}},
) )
actions = TemplateColumn( actions = TemplateColumn(
orderable=False,
attrs={'th': {'class': 'group-list-table-thin'}}, attrs={'th': {'class': 'group-list-table-thin'}},
template_code=('{% include "dashboard/group-list/column-' template_code=('{% include "dashboard/group-list/column-'
'actions.html" with btn_size="btn-xs" %}'), 'actions.html" with btn_size="btn-xs" %}'),
......
{% load i18n %}
<div class="modal fade" id="confirmation-modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{% if text %}
{{ text }}
{% else %}
{%blocktrans with object=object%}
Are you sure you want to remove <strong>{{ member }}</strong> from <strong>{{ object }}</strong>?
{%endblocktrans%}
{% endif %}
<br />
<div class="pull-right" style="margin-top: 15px;">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button id="confirmation-modal-button" type="button" class="btn btn-warning">Remove</button>
</div>
<div class="clearfix"></div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% load crispy_forms_tags %}
<style>
.row {
margin-bottom: 15px;
}
</style>
<form method="POST" action="/dashboard/group/create/">
{% csrf_token %}
{% crispy form %}
</form>
...@@ -37,51 +37,92 @@ ...@@ -37,51 +37,92 @@
<div class="row"> <div class="row">
<div class="col-md-12" id="group-detail-pane"> <div class="col-md-12" id="group-detail-pane">
<div class="panel panel-default" id="group-detail-panel"> <div class="panel panel-default" id="group-detail-panel">
<div class="tab-content panel-body"> <div class="tab-content panel-body" id="group-form-body">
<h3>{% trans "User list"|capfirst %}</h3>
<h3>{% trans "User list"|capfirst %}</h3> <form action="" method="post">{% csrf_token %}
<table class="table table-striped table-with-form-fields"> <table class="table table-striped table-with-form-fields table-bordered" id="group-detail-user-table">
<tbody> <tbody>
<thead><tr><th></th><th>{% trans "Who" %}</th><th></th><th></th></tr></thead> <thead><tr><th></th><th>{% trans "Who" %}</th><th>{% trans "Remove" %}</th></tr></thead>
{% for i in users %} {% for i in users %}
<tr><td><i class="icon-user"></i></td><td>{{i.username}}</td> <tr>
<td><a data-group-pk="{{ i.pk }}" href="#" class="real-link groupuser-delete btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a></td></tr> <td><i class="icon-user"></i></td><td>{{i.username}}</td>
<td>
<a data-group_pk="{{ group.pk }}" data-member_pk="{{i.pk}}" href="{% url "dashboard.views.remove-user" member_pk=i.pk group_pk=group.pk %}" class="real-link delete-from-group btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a>
</td>
</tr>
{% endfor %} {% endfor %}
<tr><td><i class="icon-plus"></i></td> <tr>
<td><input type="text" class="form-control" name="perm-new-name" <td><i class="icon-plus"></i></td>
placeholder="{% trans "Name of group or user" %}"></td> <td colspan="2">
<input type="text" class="form-control" name="list-new-name"placeholder="{% trans "Name of user" %}">
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<textarea name="list-new-namelist" class="form-control"
placeholder="{% trans "List of usernames (one per line)." %}"></textarea>
<div class="form-actions">
<button type="submit" class="btn btn-success">{% trans "Save" %}</button>
</div>
</form>
<h3>{% trans "Permissions"|capfirst %}</h3> <h3 id="group-detail-perm-header">{% trans "Permissions"|capfirst %}</h3>
<form action="{{acl.url}}" method="post">{% csrf_token %} <form action="{{acl.url}}" method="post">{% csrf_token %}
<table class="table table-striped table-with-form-fields"> <table class="table table-striped table-with-form-fields table-bordered" id="group-detail-perm-table">
<thead><tr><th></th><th>{% trans "Who" %}</th><th>{% trans "What" %}</th><th></th></tr></thead> <thead>
<tr>
<th></th><th>{% trans "Who" %}</th><th>{% trans "What" %}</th><th>{% trans "Remove" %}</th>
</tr>
</thead>
<tbody> <tbody>
{% for i in acl.users %} {% for i in acl.users %}
<tr><td><i class="icon-user"></i></td><td>{{i.user}}</td> <tr>
<td><select class="form-control" name="perm-u-{{i.user.id}}"> <td><i class="icon-user"></i></td><td>{{i.user}}</td>
{% for id, name in acl.levels %} <td>
<option{%if id = i.level%} selected="selected"{%endif%} value="{{id}}">{{name}}</option> <select class="form-control" name="perm-u-{{i.user.id}}">
{% endfor %} {% for id, name in acl.levels %}
</select></td> <option{%if id = i.level%} selected="selected"{%endif%} value="{{id}}">{{name}}</option>
<td class="user-remove"><a href="#" class="btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a></td></tr>
{% endfor %} {% endfor %}
<tr><td><i class="icon-plus"></i></td> </select>
<td><input type="text" class="form-control" name="perm-new-name" </td>
placeholder="{% trans "Name of group or user" %}"></td> <td class="user-remove"><a data-group_pk="{{ group.pk }}" data-member_pk="{{i.user.pk }}" href="{% url "dashboard.views.remove-acluser" member_pk=i.user.pk group_pk=group.pk %}" class="real-link delete-from-group btn btn-link btn-xs"><i class="icon-remove"><span class="sr-only">{% trans "remove" %}</span></i></a></td>
<td><select class="form-control" name="perm-new"> </tr>
{% for id, name in acl.levels %} {% endfor %}
<option value="{{id}}">{{name}}</option>
{% endfor %} {% for i in acl.groups %}
</select></td><td></td> <tr>
</tr> <td><i class="icon-group"></i></td><td>{{ i.group }}</td>
<td>
<select class="form-control" name="perm-g-{{ i.group.pk }}">
{% for id, name in acl.levels %}
<option{%if id = i.level%} selected="selected"{%endif%} value="{{id}}">{{name}}</option>
{% endfor %}
</select>
</td>
<td class="user-remove"><a data-group_pk="{{ i.pk }}"data-member_pk="{{i.group.pk }}" href="{% url "dashboard.views.remove-aclgroup" member_pk=i.group.pk group_pk=group.pk %}" class="real-link delete-from-group 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> </tbody>
</table> </table>
<textarea class="form-control"></textarea>
<div class="form-actions panel-body"> <div class="form-actions">
<button type="submit" class="btn btn-success">{% trans "Save" %}</button> <button type="submit" class="btn btn-success">{% trans "Save" %}</button>
</div> </div>
</form> </form>
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<i class="icon-chevron-sign-right"></i> <strong>{{ more_groups }}</strong> more <i class="icon-chevron-sign-right"></i> <strong>{{ more_groups }}</strong> more
</a> </a>
{% endif %} {% endif %}
<a class="btn btn-success btn-xs group-create" href="#"><i class="icon-upload-alt"></i> {% trans "new" %} </a> <a class="btn btn-success btn-xs group-create" href="{% url "dashboard.views.group-create" %}"><i class="icon-upload-alt"></i> {% trans "new" %} </a>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</div> </div>
{% endif %} {% endif %}
{% if perms.group %} {% if perms.auth %}
<div class="col-lg-4 col-sm-6"> <div class="col-lg-4 col-sm-6">
{% include "dashboard/index-groups.html" %} {% include "dashboard/index-groups.html" %}
</div> </div>
......
...@@ -871,6 +871,611 @@ class NodeDetailTest(LoginMixin, TestCase): ...@@ -871,6 +871,611 @@ class NodeDetailTest(LoginMixin, TestCase):
self.assertEqual(node_enabled, not Node.objects.get(pk=1).enabled) self.assertEqual(node_enabled, not Node.objects.get(pk=1).enabled)
class GroupCreateTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json']
def setUp(self):
# u0 - user with creating group permissions
self.u0 = User.objects.create(username='user0')
self.u0.set_password('password')
self.u0.save()
permlist = Permission.objects.all()
self.u0.user_permissions.add(
filter(lambda element: 'group' in element.name and
'add' in element.name, permlist)[0])
# u1 simple user without permissions
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
self.u1.save()
self.us = User.objects.create(username='superuser', is_superuser=True)
self.us.set_password('password')
self.us.save()
self.g1 = Group.objects.create(name='group1')
self.g1.save()
def tearDown(self):
super(GroupCreateTest, self).tearDown()
self.g1.delete()
self.u0.delete()
self.u1.delete()
self.us.delete()
def test_anon_group_page(self):
c = Client()
response = c.get('/dashboard/group/create/')
self.assertEqual(response.status_code, 302)
def test_superuser_group_page(self):
c = Client()
self.login(c, 'superuser')
response = c.get('/dashboard/group/create/')
self.assertEqual(response.status_code, 200)
def test_permitted_group_page(self):
c = Client()
self.login(c, 'user0')
response = c.get('/dashboard/group/create/')
self.assertEqual(response.status_code, 200)
def test_unpermitted_group_page(self):
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/create/')
self.assertEqual(response.status_code, 403)
def test_anon_group_create(self):
c = Client()
groupnum = Group.objects.count()
response = c.post('/dashboard/group/create/', {'name': 'newgroup'})
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum)
def test_unpermitted_group_create(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'user1')
response = c.post('/dashboard/group/create/', {'name': 'newgroup'})
self.assertEqual(response.status_code, 403)
self.assertEqual(Group.objects.count(), groupnum)
def test_permitted_group_create(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'user0')
response = c.post('/dashboard/group/create/', {'name': 'newgroup'})
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum + 1)
def test_superuser_group_create(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'superuser')
response = c.post('/dashboard/group/create/', {'name': 'newgroup'})
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum + 1)
def test_namecollision_group_create(self):
# hint: group1 is in setUp, the tests checks creating group with the
# same name
c = Client()
groupnum = Group.objects.count()
self.login(c, 'superuser')
response = c.post('/dashboard/group/create/', {'name': 'group1'})
self.assertEqual(response.status_code, 200)
self.assertEqual(Group.objects.count(), groupnum)
def test_creator_is_owner_when_group_create(self):
# has owner rights in the group the user who created the group?
c = Client()
self.login(c, 'user0')
c.post('/dashboard/group/create/', {'name': 'newgroup'})
newgroup = Group.objects.get(name='newgroup')
self.assertTrue(newgroup.profile.has_level(self.u0, 'owner'))
class GroupDeleteTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json']
def setUp(self):
# u0 - user with creating group permissions
self.u0 = User.objects.create(username='user0')
self.u0.set_password('password')
self.u0.save()
permlist = Permission.objects.all()
self.u0.user_permissions.add(
filter(lambda element: 'group' in element.name and
'delete' in element.name, permlist)[0])
# u1 simple user without permissions
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
self.u1.save()
self.us = User.objects.create(username='superuser', is_superuser=True)
self.us.set_password('password')
self.us.save()
self.g1 = Group.objects.create(name='group1')
self.g1.profile.set_user_level(self.u0, 'owner')
self.g1.save()
def tearDown(self):
super(GroupDeleteTest, self).tearDown()
self.g1.delete()
self.u0.delete()
self.u1.delete()
self.us.delete()
def test_anon_group_page(self):
c = Client()
response = c.get('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
def test_superuser_group_page(self):
c = Client()
self.login(c, 'superuser')
response = c.get('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_permitted_group_page(self):
c = Client()
self.login(c, 'user0')
response = c.get('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_unpermitted_group_page(self):
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 403)
def test_anon_group_delete(self):
c = Client()
groupnum = Group.objects.count()
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum)
def test_unpermitted_group_delete(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'user1')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 403)
self.assertEqual(Group.objects.count(), groupnum)
def test_permitted_group_delete(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'user0')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum - 1)
def test_superuser_group_delete(self):
c = Client()
groupnum = Group.objects.count()
self.login(c, 'superuser')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), groupnum - 1)
class GroupDetailTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json']
def setUp(self):
Instance.get_remote_queue_name = Mock(return_value='test')
# u0 - owner for group1
self.u0 = User.objects.create(username='user0')
self.u0.set_password('password')
self.u0.save()
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
self.u1.save()
self.u2 = User.objects.create(username='user2', is_staff=True)
self.u2.set_password('password')
self.u2.save()
self.u3 = User.objects.create(username='user3')
self.u3.set_password('password')
self.u3.save()
# u4 - removable user for group1
self.u4 = User.objects.create(username='user4')
self.u4.set_password('password')
self.u4.save()
self.us = User.objects.create(username='superuser', is_superuser=True)
self.us.set_password('password')
self.us.save()
self.g1 = Group.objects.create(name='group1')
self.g1.profile.set_user_level(self.u0, 'owner')
self.g1.profile.set_user_level(self.u4, 'operator')
self.g1.user_set.add(self.u4)
self.g1.save()
self.g2 = Group.objects.create(name='group2')
self.g2.save()
self.g3 = Group.objects.create(name='group3')
self.g3.save()
self.g1.profile.set_group_level(self.g3, 'operator')
settings["default_vlangroup"] = 'public'
VlanGroup.objects.create(name='public')
def tearDown(self):
super(GroupDetailTest, self).tearDown()
self.g1.delete()
self.g2.delete()
self.g3.delete()
self.u0.delete()
self.u1.delete()
self.u2.delete()
self.us.delete()
self.u3.delete()
self.u4.delete()
def test_404_superuser_group_page(self):
c = Client()
self.login(c, 'superuser')
response = c.get('/dashboard/group/25555/')
self.assertEqual(response.status_code, 404)
def test_404_user_group_page(self):
c = Client()
self.login(c, 'user0')
response = c.get('/dashboard/group/25555/')
self.assertEqual(response.status_code, 404)
def test_anon_group_page(self):
c = Client()
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
def test_superuser_group_page(self):
c = Client()
self.login(c, 'superuser')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_acluser_group_page(self):
c = Client()
self.login(c, 'user0')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_acluser2_group_page(self):
self.g1.profile.set_user_level(self.u1, 'operator')
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_unpermitted_user_group_page(self):
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 403)
def test_user_in_userlist_group_page(self):
self.g1.user_set.add(self.u1)
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 403)
def test_groupmember_group_page(self):
self.g2.user_set.add(self.u1)
self.g1.profile.set_group_level(self.g2, 'owner')
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 200)
def test_superuser_group_delete(self):
num_of_groups = Group.objects.count()
c = Client()
self.login(c, 'superuser')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), num_of_groups - 1)
def test_unpermitted_group_delete(self):
num_of_groups = Group.objects.count()
c = Client()
self.login(c, 'user3')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 403)
self.assertEqual(Group.objects.count(), num_of_groups)
def test_acl_group_delete(self):
num_of_groups = Group.objects.count()
c = Client()
self.login(c, 'user0')
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), num_of_groups - 1)
def test_anon_group_delete(self):
num_of_groups = Group.objects.count()
c = Client()
response = c.post('/dashboard/group/delete/' + str(self.g1.pk) + '/')
self.assertEqual(response.status_code, 302)
self.assertEqual(Group.objects.count(), num_of_groups)
# add to group
def test_anon_add_user_to_group(self):
c = Client()
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/', {'list-new-name': 'user3'})
self.assertEqual(user_in_group,
self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_unpermitted_add_user_to_group(self):
c = Client()
self.login(c, 'user3')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/', {'list-new-name': 'user3'})
self.assertEqual(user_in_group, self.g1.user_set.count())
self.assertEqual(response.status_code, 403)
def test_superuser_add_user_to_group(self):
c = Client()
self.login(c, 'superuser')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/', {'list-new-name': 'user3'})
self.assertEqual(user_in_group + 1, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_permitted_add_user_to_group(self):
c = Client()
self.login(c, 'user0')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/', {'list-new-name': 'user3'})
self.assertEqual(user_in_group + 1, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_permitted_add_multipleuser_to_group(self):
c = Client()
self.login(c, 'user0')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/',
{'list-new-namelist': 'user1\r\nuser2'})
self.assertEqual(user_in_group + 2, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_add_multipleuser_skip_badname_to_group(self):
c = Client()
self.login(c, 'user0')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/',
{'list-new-namelist': 'user1\r\nnoname\r\nuser2'})
self.assertEqual(user_in_group + 2, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_unpermitted_add_multipleuser_to_group(self):
c = Client()
self.login(c, 'user3')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/',
{'list-new-namelist': 'user1\r\nuser2'})
self.assertEqual(user_in_group, self.g1.user_set.count())
self.assertEqual(response.status_code, 403)
def test_anon_add_multipleuser_to_group(self):
c = Client()
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/',
{'list-new-namelist': 'user1\r\nuser2'})
self.assertEqual(user_in_group, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_anon_add_acluser_to_group(self):
c = Client()
gp = self.g1.profile
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'user3', 'perm-new': 'owner'})
self.assertEqual(acl_users, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_unpermitted_add_acluser_to_group(self):
c = Client()
self.login(c, 'user3')
gp = self.g1.profile
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'user3', 'perm-new': 'owner'})
self.assertEqual(acl_users, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 403)
def test_superuser_add_acluser_to_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'superuser')
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'user3', 'perm-new': 'owner'})
self.assertEqual(acl_users + 1, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_permitted_add_acluser_to_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'user0')
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'user3', 'perm-new': 'owner'})
self.assertEqual(acl_users + 1, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_anon_add_aclgroup_to_group(self):
c = Client()
gp = self.g1.profile
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'group2', 'perm-new': 'owner'})
self.assertEqual(acl_groups, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
def test_unpermitted_add_aclgroup_to_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'user3')
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'group2', 'perm-new': 'owner'})
self.assertEqual(acl_groups, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 403)
def test_superuser_add_aclgroup_to_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'superuser')
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'group2', 'perm-new': 'owner'})
self.assertEqual(acl_groups + 1, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
def test_permitted_add_aclgroup_to_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'user0')
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' +
str(self.g1.pk) + '/acl/',
{'perm-new-name': 'group2', 'perm-new': 'owner'})
self.assertEqual(acl_groups + 1, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
# remove from group
def test_anon_remove_user_from_group(self):
c = Client()
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/user/' + str(self.u4.pk) + '/')
self.assertEqual(user_in_group,
self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_unpermitted_remove_user_from_group(self):
c = Client()
self.login(c, 'user3')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/user/' + str(self.u4.pk) + '/')
self.assertEqual(user_in_group, self.g1.user_set.count())
self.assertEqual(response.status_code, 403)
def test_superuser_remove_user_from_group(self):
c = Client()
self.login(c, 'superuser')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/user/' + str(self.u4.pk) + '/')
self.assertEqual(user_in_group - 1, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_permitted_remove_user_from_group(self):
c = Client()
self.login(c, 'user0')
user_in_group = self.g1.user_set.count()
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/user/' + str(self.u4.pk) + '/')
self.assertEqual(user_in_group - 1, self.g1.user_set.count())
self.assertEqual(response.status_code, 302)
def test_anon_remove_acluser_from_group(self):
c = Client()
gp = self.g1.profile
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/user/' + str(self.u4.pk) + '/')
self.assertEqual(acl_users, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_unpermitted_remove_acluser_from_group(self):
c = Client()
self.login(c, 'user3')
gp = self.g1.profile
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/user/' + str(self.u4.pk) + '/')
self.assertEqual(acl_users, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 403)
def test_superuser_remove_acluser_from_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'superuser')
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/user/' + str(self.u4.pk) + '/')
self.assertEqual(acl_users - 1, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_permitted_remove_acluser_from_group(self):
c = Client()
gp = self.g1.profile
self.login(c, 'user0')
acl_users = len(gp.get_users_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/user/' + str(self.u4.pk) + '/')
self.assertEqual(acl_users - 1, len(gp.get_users_with_level()))
self.assertEqual(response.status_code, 302)
def test_anon_remove_aclgroup_from_group(self):
c = Client()
gp = self.g1.profile
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/group/' + str(self.g3.pk) + '/')
self.assertEqual(acl_groups, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
def test_unpermitted_remove_aclgroup_from_group(self):
c = Client()
self.login(c, 'user3')
gp = self.g1.profile
acl_groups = len(gp.get_groups_with_level())
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/group/' + str(self.g3.pk) + '/')
self.assertEqual(acl_groups, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 403)
def test_superuser_remove_aclgroup_from_group(self):
c = Client()
gp = self.g1.profile
acl_groups = len(gp.get_groups_with_level())
self.login(c, 'superuser')
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/group/' + str(self.g3.pk) + '/')
self.assertEqual(acl_groups - 1, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
def test_permitted_remove_aclgroup_from_group(self):
c = Client()
gp = self.g1.profile
acl_groups = len(gp.get_groups_with_level())
self.login(c, 'user0')
response = c.post('/dashboard/group/' + str(self.g1.pk) +
'/remove/acl/group/' + str(self.g3.pk) + '/')
self.assertEqual(acl_groups - 1, len(gp.get_groups_with_level()))
self.assertEqual(response.status_code, 302)
class VmDetailVncTest(LoginMixin, TestCase): class VmDetailVncTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json'] fixtures = ['test-vm-fixture.json', 'node.json']
......
...@@ -21,7 +21,7 @@ from django.conf.urls import patterns, url, include ...@@ -21,7 +21,7 @@ from django.conf.urls import patterns, url, include
from vm.models import Instance from vm.models import Instance
from .views import ( from .views import (
AclUpdateView, DiskAddView, FavouriteView, GroupAclUpdateView, GroupDelete, AclUpdateView, DiskAddView, FavouriteView, GroupAclUpdateView, GroupDelete,
GroupDetailView, GroupList, GroupUserDelete, IndexView, GroupDetailView, GroupList, IndexView,
InstanceActivityDetail, LeaseCreate, LeaseDelete, LeaseDetail, InstanceActivityDetail, LeaseCreate, LeaseDelete, LeaseDetail,
MyPreferencesView, NodeAddTraitView, NodeCreate, NodeDelete, MyPreferencesView, NodeAddTraitView, NodeCreate, NodeDelete,
NodeDetailView, NodeFlushView, NodeGraphView, NodeList, NodeStatus, NodeDetailView, NodeFlushView, NodeGraphView, NodeList, NodeStatus,
...@@ -30,6 +30,8 @@ from .views import ( ...@@ -30,6 +30,8 @@ from .views import (
TransferOwnershipView, vm_activity, VmCreate, VmDelete, VmDetailView, TransferOwnershipView, vm_activity, VmCreate, VmDelete, VmDetailView,
VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, VmMigrateView, VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, VmMigrateView,
VmRenewView, DiskRemoveView, get_disk_download_status, InterfaceDeleteView, VmRenewView, DiskRemoveView, get_disk_download_status, InterfaceDeleteView,
GroupRemoveAclUserView, GroupRemoveAclGroupView, GroupRemoveUserView,
GroupCreate,
TemplateChoose, TemplateChoose,
) )
...@@ -116,9 +118,6 @@ urlpatterns = patterns( ...@@ -116,9 +118,6 @@ urlpatterns = patterns(
name='dashboard.views.group-detail'), name='dashboard.views.group-detail'),
url(r'^group/(?P<pk>\d+)/acl/$', GroupAclUpdateView.as_view(), url(r'^group/(?P<pk>\d+)/acl/$', GroupAclUpdateView.as_view(),
name='dashboard.views.group-acl'), name='dashboard.views.group-acl'),
url(r'^groupuser/delete/(?P<pk>\d+)/$', GroupUserDelete.as_view(),
name="dashboard.views.delete-groupuser"),
url(r'^notifications/$', NotificationView.as_view(), url(r'^notifications/$', NotificationView.as_view(),
name="dashboard.views.notifications"), name="dashboard.views.notifications"),
...@@ -134,4 +133,15 @@ urlpatterns = patterns( ...@@ -134,4 +133,15 @@ urlpatterns = patterns(
url(r'^profile/$', MyPreferencesView.as_view(), url(r'^profile/$', MyPreferencesView.as_view(),
name="dashboard.views.profile"), name="dashboard.views.profile"),
url(r'^group/(?P<group_pk>\d+)/remove/acl/user/(?P<member_pk>\d+)/$',
GroupRemoveAclUserView.as_view(),
name="dashboard.views.remove-acluser"),
url(r'^group/(?P<group_pk>\d+)/remove/acl/group/(?P<member_pk>\d+)/$',
GroupRemoveAclGroupView.as_view(),
name="dashboard.views.remove-aclgroup"),
url(r'^group/(?P<group_pk>\d+)/remove/user/(?P<member_pk>\d+)/$',
GroupRemoveUserView.as_view(),
name="dashboard.views.remove-user"),
url(r'^group/create/$', GroupCreate.as_view(),
name='dashboard.views.group-create'),
) )
...@@ -52,18 +52,21 @@ from braces.views._access import AccessMixin ...@@ -52,18 +52,21 @@ from braces.views._access import AccessMixin
from .forms import ( from .forms import (
CircleAuthenticationForm, DiskAddForm, HostForm, LeaseForm, MyProfileForm, CircleAuthenticationForm, DiskAddForm, HostForm, LeaseForm, MyProfileForm,
NodeForm, TemplateForm, TraitForm, VmCustomizeForm, NodeForm, TemplateForm, TraitForm, VmCustomizeForm, GroupCreateForm,
CirclePasswordChangeForm CirclePasswordChangeForm
) )
from .tables import (NodeListTable, NodeVmListTable,
TemplateListTable, LeaseListTable, GroupListTable,) from .tables import (
NodeListTable, NodeVmListTable, TemplateListTable, LeaseListTable,
GroupListTable,
)
from vm.models import ( from vm.models import (
Instance, instance_activity, InstanceActivity, InstanceTemplate, Interface, Instance, instance_activity, InstanceActivity, InstanceTemplate, Interface,
InterfaceTemplate, Lease, Node, NodeActivity, Trait, InterfaceTemplate, Lease, Node, NodeActivity, Trait,
) )
from storage.models import Disk from storage.models import Disk
from firewall.models import Vlan, Host, Rule from firewall.models import Vlan, Host, Rule
from .models import Favourite, Profile from .models import Favourite, Profile, GroupProfile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -140,11 +143,13 @@ class IndexView(LoginRequiredMixin, TemplateView): ...@@ -140,11 +143,13 @@ class IndexView(LoginRequiredMixin, TemplateView):
}) })
# groups # groups
groups = Group.objects.all() if user.has_module_perms('auth'):
context.update({ profiles = GroupProfile.get_objects_with_level('operator', user)
'groups': groups[:5], groups = Group.objects.filter(groupprofile__in=profiles)
'more_groups': groups.count() - len(groups[:5]), context.update({
}) 'groups': groups[:5],
'more_groups': groups.count() - len(groups[:5]),
})
# template # template
if user.has_perm('vm.create_template'): if user.has_perm('vm.create_template'):
...@@ -672,6 +677,7 @@ class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): ...@@ -672,6 +677,7 @@ class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
class GroupDetailView(CheckedDetailView): class GroupDetailView(CheckedDetailView):
template_name = "dashboard/group-detail.html" template_name = "dashboard/group-detail.html"
model = Group model = Group
read_level = 'operator'
def get_has_level(self): def get_has_level(self):
return self.object.profile.has_level return self.object.profile.has_level
...@@ -684,12 +690,45 @@ class GroupDetailView(CheckedDetailView): ...@@ -684,12 +690,45 @@ class GroupDetailView(CheckedDetailView):
return context return context
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
self.object = self.get_object()
if not self.get_has_level()(request.user, 'operator'):
raise PermissionDenied()
if request.POST.get('new_name'): if request.POST.get('new_name'):
return self.__set_name(request) return self.__set_name(request)
if request.POST.get('list-new-name'):
return self.__add_user(request)
if request.POST.get('list-new-namelist'):
return self.__add_list(request)
if (request.POST.get('list-new-name') is not None) and \
(request.POST.get('list-new-namelist') is not None):
return redirect(reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.get_object().pk}))
def __add_user(self, request):
name = request.POST['list-new-name']
self.__add_username(request, name)
return redirect(reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.object.pk}))
def __add_username(self, request, name):
if not name:
return
try:
entity = User.objects.get(username=name)
self.object.user_set.add(entity)
except User.DoesNotExist:
warning(request, _('User "%s" not found.') % name)
def __add_list(self, request):
if not self.get_has_level()(request.user, 'operator'):
raise PermissionDenied()
userlist = request.POST.get('list-new-namelist').split('\r\n')
for line in userlist:
self.__add_username(request, line)
return redirect(reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.object.pk}))
def __set_name(self, request): def __set_name(self, request):
self.object = self.get_object()
new_name = request.POST.get("new_name") new_name = request.POST.get("new_name")
Group.objects.filter(pk=self.object.pk).update( Group.objects.filter(pk=self.object.pk).update(
**{'name': new_name}) **{'name': new_name})
...@@ -827,27 +866,6 @@ class GroupAclUpdateView(AclUpdateView): ...@@ -827,27 +866,6 @@ class GroupAclUpdateView(AclUpdateView):
else: else:
self.set_levels(request, instance) self.set_levels(request, instance)
self.add_levels(request, instance) self.add_levels(request, instance)
# return redirect(self.profile)
return redirect(reverse("dashboard.views.group-detail",
kwargs=self.kwargs))
def repost(self, request, *args, **kwargs):
group = self.get_object()
if not (group.profile.has_level(request.user, "owner") or
getattr(group.profile, 'owner', None) == request.user):
logger.warning('Tried to set permissions of %s by non-owner %s.',
unicode(group), unicode(request.user))
raise PermissionDenied()
name = request.POST['perm-new-name']
if (User.objects.filter(username=name).count() +
Group.objects.filter(name=name).count() < 1
and len(name) > 0):
warning(request, _('User or group "%s" not found.') % name)
else:
self.set_levels(request, group.profile)
self.add_levels(request, group.profile)
return redirect(reverse("dashboard.views.group-detail", return redirect(reverse("dashboard.views.group-detail",
kwargs=self.kwargs)) kwargs=self.kwargs))
...@@ -1130,43 +1148,87 @@ class NodeList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView): ...@@ -1130,43 +1148,87 @@ class NodeList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
number_of_VMs=Count('instance_set')).select_related('host') number_of_VMs=Count('instance_set')).select_related('host')
class GroupList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView): class GroupList(LoginRequiredMixin, SingleTableView):
template_name = "dashboard/group-list.html" template_name = "dashboard/group-list.html"
model = Group model = Group
table_class = GroupListTable table_class = GroupListTable
table_pagination = False table_pagination = False
def get(self, *args, **kwargs):
if self.request.is_ajax():
groups = [{
'url': reverse("dashboard.views.group-detail",
kwargs={'pk': i.pk}),
'name': i.name} for i in self.queryset]
return HttpResponse(
json.dumps(list(groups)),
content_type="application/json",
)
else:
return super(GroupList, self).get(*args, **kwargs)
def get_queryset(self):
logger.debug('GroupList.get_queryset() called. User: %s',
unicode(self.request.user))
profiles = GroupProfile.get_objects_with_level(
'operator', self.request.user)
groups = Group.objects.filter(groupprofile__in=profiles)
s = self.request.GET.get("s")
if s:
groups = groups.filter(name__icontains=s)
return groups
class GroupUserDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
"""This stuff deletes the group. class GroupRemoveUserView(CheckedDetailView, DeleteView):
""" model = Group
model = User slug_field = 'pk'
template_name = "dashboard/confirm/base-delete.html" slug_url_kwarg = 'group_pk'
read_level = 'operator'
def get_has_level(self):
return self.object.profile.has_level
def get_context_data(self, **kwargs):
context = super(GroupRemoveUserView, self).get_context_data(**kwargs)
try:
context['member'] = User.objects.get(pk=self.member_pk)
except User.DoesNotExist:
raise Http404()
return context
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.get_object().pk})
def get(self, request, member_pk, *args, **kwargs):
self.member_pk = member_pk
return super(GroupRemoveUserView, self).get(request, *args, **kwargs)
def get_template_names(self): def get_template_names(self):
if self.request.is_ajax(): if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html'] return ['dashboard/confirm/ajax-remove.html']
else: else:
return ['dashboard/confirm/base-delete.html'] return ['dashboard/confirm/base-remove.html']
def get_context_data(self, **kwargs): def remove_member(self, pk):
# this is redundant now, but if we wanna add more to print container = self.get_object()
# we'll need this container.user_set.remove(User.objects.get(pk=pk))
context = super(GroupUserDelete, self).get_context_data(**kwargs)
return context def get_success_message(self):
return _("Member successfully removed from group!")
# github.com/django/django/blob/master/django/views/generic/edit.py#L245
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
object = self.get_object() object = self.get_object()
if not object.profile.has_level(request.user, 'operator'):
object.delete() raise PermissionDenied()
self.remove_member(kwargs["member_pk"])
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Group successfully deleted!") success_message = self.get_success_message()
if request.is_ajax(): if request.is_ajax():
if request.POST.get('redirect').lower() == "true":
messages.success(request, success_message)
return HttpResponse( return HttpResponse(
json.dumps({'message': success_message}), json.dumps({'message': success_message}),
content_type="application/json", content_type="application/json",
...@@ -1175,20 +1237,45 @@ class GroupUserDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): ...@@ -1175,20 +1237,45 @@ class GroupUserDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
messages.success(request, success_message) messages.success(request, success_message)
return HttpResponseRedirect(success_url) return HttpResponseRedirect(success_url)
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy('dashboard.index')
class GroupRemoveAclUserView(GroupRemoveUserView):
class GroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): def remove_member(self, pk):
container = self.get_object().profile
container.set_level(User.objects.get(pk=pk), None)
def get_success_message(self):
return _("Acl user successfully removed from group!")
class GroupRemoveAclGroupView(GroupRemoveUserView):
def get_context_data(self, **kwargs):
context = super(GroupRemoveUserView, self).get_context_data(**kwargs)
try:
context['member'] = Group.objects.get(pk=self.member_pk)
except User.DoesNotExist:
raise Http404()
return context
def remove_member(self, pk):
container = self.get_object().profile
container.set_level(Group.objects.get(pk=pk), None)
def get_success_message(self):
return _("Acl group successfully removed from group!")
class GroupDelete(CheckedDetailView, DeleteView):
"""This stuff deletes the group. """This stuff deletes the group.
""" """
model = Group model = Group
template_name = "dashboard/confirm/base-delete.html" template_name = "dashboard/confirm/base-delete.html"
read_level = 'operator'
def get_has_level(self):
return self.object.profile.has_level
def get_template_names(self): def get_template_names(self):
if self.request.is_ajax(): if self.request.is_ajax():
...@@ -1196,16 +1283,11 @@ class GroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): ...@@ -1196,16 +1283,11 @@ class GroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
else: else:
return ['dashboard/confirm/base-delete.html'] return ['dashboard/confirm/base-delete.html']
def get_context_data(self, **kwargs):
# this is redundant now, but if we wanna add more to print
# we'll need this
context = super(GroupDelete, self).get_context_data(**kwargs)
return context
# github.com/django/django/blob/master/django/views/generic/edit.py#L245 # github.com/django/django/blob/master/django/views/generic/edit.py#L245
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
object = self.get_object() object = self.get_object()
if not object.profile.has_level(request.user, 'owner'):
raise PermissionDenied()
object.delete() object.delete()
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Group successfully deleted!") success_message = _("Group successfully deleted!")
...@@ -1431,6 +1513,49 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView): ...@@ -1431,6 +1513,49 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
return redirect(path) return redirect(path)
class GroupCreate(LoginRequiredMixin, TemplateView):
form_class = GroupCreateForm
form = None
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/modal-wrapper.html']
else:
return ['dashboard/nojs-wrapper.html']
def get(self, request, form=None, *args, **kwargs):
if not request.user.has_module_perms('auth'):
raise PermissionDenied()
if form is None:
form = self.form_class()
context = self.get_context_data(**kwargs)
context.update({
'template': 'dashboard/group-create.html',
'box_title': 'Create a Group',
'form': form,
})
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
if not request.user.has_module_perms('auth'):
raise PermissionDenied()
form = self.form_class(request.POST)
if not form.is_valid():
return self.get(request, form, *args, **kwargs)
form.cleaned_data
savedform = form.save()
savedform.profile.set_level(request.user, 'owner')
messages.success(request, _('Group successfully created!'))
if request.is_ajax():
return HttpResponse(json.dumps({'redirect':
savedform.profile.get_absolute_url()}),
content_type="application/json")
else:
return redirect(savedform.profile.get_absolute_url())
class VmDelete(LoginRequiredMixin, DeleteView): class VmDelete(LoginRequiredMixin, DeleteView):
model = Instance model = Instance
template_name = "dashboard/confirm/base-delete.html" template_name = "dashboard/confirm/base-delete.html"
......
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