Commit dfb15f98 by Őry Máté

Merge remote-tracking branch 'origin/acl'

parents be07eae3 6b43a7c3
...@@ -18,6 +18,6 @@ _build ...@@ -18,6 +18,6 @@ _build
# Logs: # Logs:
*.log *.log
.ropeproject .ropeproject
#celery
celerybeat-schedule celerybeat-schedule
.coverage
*,cover
"""
Creates Levels for all installed apps that have levels.
"""
from django.db.models import get_models, signals
from django.db import DEFAULT_DB_ALIAS
from django.core.exceptions import ImproperlyConfigured
from ..models import Level, AclBase
def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
**kwargs):
"""Create and set the weights of the configured Levels.
Based on django.contrib.auth.management.__init__.create_permissions"""
# if not router.allow_migrate(db, auth_app.Permission):
# return
from django.contrib.contenttypes.models import ContentType
app_models = [k for k in get_models(app) if AclBase in k.__bases__]
print "Creating levels for models: %s." % ", ".join([m.__name__ for m in app_models])
# This will hold the levels we're looking for as
# (content_type, (codename, name))
searched_levels = list()
level_weights = list()
# The codenames and ctypes that should exist.
ctypes = set()
for klass in app_models:
# Force looking up the content types in the current database
# before creating foreign keys to them.
ctype = ContentType.objects.db_manager(db).get_for_model(klass)
ctypes.add(ctype)
weight = 0
try:
for codename, name in klass.ACL_LEVELS:
searched_levels.append((ctype, (codename, name)))
level_weights.append((ctype, codename, weight))
weight += 1
except AttributeError:
raise ImproperlyConfigured(
"Class %s doesn't have ACL_LEVELS attribute." % klass)
# Find all the Levels that have a content_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.
all_levels = set(Level.objects.using(db).filter(
content_type__in=ctypes,
).values_list(
"content_type", "codename"
))
levels = [
Level(codename=codename, name=name, content_type=ctype)
for ctype, (codename, name) in searched_levels
if (ctype.pk, codename) not in all_levels
]
Level.objects.using(db).bulk_create(levels)
if verbosity >= 2:
print("Adding levels [%s]." % ", ".join(levels))
print("Searched: [%s]." % ", ".join([unicode(l) for l in searched_levels]))
print("All: [%s]." % ", ".join([unicode(l) for l in all_levels]))
# set weights
for ctype, codename, weight in level_weights:
Level.objects.filter(codename=codename,
content_type=ctype).update(weight=weight)
signals.post_syncdb.connect(
create_levels, dispatch_uid="circle.acl.management.create_levels")
from django.core.management.base import BaseCommand
from .. import create_levels
class Command(BaseCommand):
args = ''
help = 'Regenerates Levels'
def handle(self, *args, **options):
create_levels(None, None, 3)
import logging
from django.contrib.auth.models import User, Group
from django.contrib.contenttypes.generic import (
GenericForeignKey, GenericRelation
)
from django.contrib.contenttypes.models import ContentType
from django.db.models import (
ManyToManyField, ForeignKey, CharField, Model, IntegerField
)
logger = logging.getLogger(__name__)
class Level(Model):
"""Definition of a permission level.
Instances are automatically populated based on AclBase."""
name = CharField('name', max_length=50)
content_type = ForeignKey(ContentType)
codename = CharField('codename', max_length=100)
weight = IntegerField('weight', null=True)
def __unicode__(self):
return "<%s/%s>" % (unicode(self.content_type), self.name)
class Meta:
unique_together = (('content_type', 'codename'),
# ('content_type', 'weight'),
# TODO find a way of temp. disabling this constr.
)
class ObjectLevel(Model):
"""Permission level for a specific object."""
level = ForeignKey(Level)
content_type = ForeignKey(ContentType)
object_id = CharField(max_length=255)
content_object = GenericForeignKey()
users = ManyToManyField(User)
groups = ManyToManyField(Group)
def __unicode__(self):
return "<%s: %s>" % (unicode(self.content_object), unicode(self.level))
class Meta:
unique_together = (('content_type', 'object_id', 'level'),)
class AclBase(Model):
"""Define permission levels for Users/Groups per object."""
object_level_set = GenericRelation(ObjectLevel)
@classmethod
def get_level_object(cls, level):
"""Get Level object for this model by codename."""
ct = ContentType.objects.get_for_model(cls)
return Level.objects.get(codename=level, content_type=ct)
def set_level(self, whom, level):
"""Set level of object for a user or group.
:param whom: user or group the level is set for
:type whom: User or Group
:param level: codename of level to set
:type level: Level or str or unicode
"""
if isinstance(whom, User):
self.set_user_level(whom, level)
elif isinstance(whom, Group):
self.set_group_level(whom, level)
else:
raise AttributeError('"whom" must be a User or Group object.')
def set_user_level(self, user, level):
"""Set level of object for a user.
:param whom: user the level is set for
:type whom: User
:param level: codename of level to set
:type level: Level or str or unicode
"""
logger.info('%s.set_user_level(%s, %s) called',
*[unicode(p) for p in [self, user, level]])
if isinstance(level, basestring):
level = self.get_level_object(level)
if not self.object_level_set.filter(level_id=level.pk).exists():
self.object_level_set.create(level=level)
for i in self.object_level_set.all():
if i.level_id != level.pk:
i.users.remove(user)
else:
i.users.add(user)
i.save()
def set_group_level(self, group, level):
"""Set level of object for a user.
:param whom: user the level is set for
:type whom: User or unicode or str
:param level: codename of level to set
:type level: str or unicode
"""
logger.info('%s.set_group_level(%s, %s) called',
*[unicode(p) for p in [self, group, level]])
if isinstance(level, basestring):
level = self.get_level_object(level)
#self.object_level_set.get_or_create(level=level, content_object=self)
if not self.object_level_set.filter(level_id=level.pk).exists():
self.object_level_set.create(level=level)
for i in self.object_level_set.all():
if i.level_id != level.pk:
i.groups.remove(group)
else:
i.groups.add(group)
i.save()
def has_level(self, user, level, group_also=True):
logger.debug('%s.has_level(%s, %s, %s) called',
*[unicode(p) for p in [self, user, level, group_also]])
if getattr(user, 'is_superuser', False):
logger.debug('- superuser granted')
return True
if isinstance(level, basestring):
level = self.get_level_object(level)
logger.debug("- level set by str: %s", unicode(level))
object_levels = self.object_level_set.filter(
level__weight__gte=level.weight).all()
groups = user.groups.values_list('id', flat=True) if group_also else []
for i in object_levels:
if i.users.filter(pk=user.pk).exists():
return True
if group_also and i.groups.filter(pk__in=groups).exists():
return True
return False
def get_users_with_level(self):
logger.debug('%s.get_users_with_level() called', unicode(self))
object_levels = (self.object_level_set.select_related(
'users', 'level').all())
users = []
for object_level in object_levels:
name = object_level.level.codename
olusers = object_level.users.all()
users.extend([(u, name) for u in olusers])
logger.debug('- %s: %s' % (name, [u.username for u in olusers]))
return users
def get_groups_with_level(self):
logger.debug('%s.get_groups_with_level() called', unicode(self))
object_levels = (self.object_level_set.select_related(
'groups', 'level').all())
groups = []
for object_level in object_levels:
name = object_level.level.codename
olgroups = object_level.groups.all()
groups.extend([(g, name) for g in olgroups])
logger.debug('- %s: %s' % (name, [g.name for g in olgroups]))
return groups
class Meta:
abstract = True
from django.db.models import TextField
from ..models import AclBase
class TestModel(AclBase):
normal_field = TextField()
ACL_LEVELS = (
('alfa', 'Alfa'),
('bravo', 'Bravo'),
('charlie', 'Charlie'),
)
class Test2Model(AclBase):
normal2_field = TextField()
ACL_LEVELS = (
('one', 'One'),
('two', 'Two'),
('three', 'Three'),
)
from django.test import TestCase
from django.contrib.auth.models import User, Group, AnonymousUser
from ..models import ObjectLevel
from .models import TestModel, Test2Model
class AclUserTest(TestCase):
def setUp(self):
self.u1 = User.objects.create(username='user1')
self.u2 = User.objects.create(username='user2', is_staff=True)
self.us = User.objects.create(username='superuser', is_superuser=True)
self.g1 = Group.objects.create(name='group1')
self.g1.user_set.add(self.u1)
self.g1.user_set.add(self.u2)
self.g1.save()
def test_level_exists(self):
for codename, name in TestModel.ACL_LEVELS:
level = TestModel.get_level_object(codename)
self.assertEqual(level.codename, codename)
for codename, name in Test2Model.ACL_LEVELS:
level = Test2Model.get_level_object(codename)
self.assertEqual(level.codename, codename)
def test_lowest_user_level(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa', False))
self.assertFalse(i.has_level(self.u1, 'bravo', False))
i.set_level(self.u1, 'alfa')
i.set_level(self.g1, 'bravo')
self.assertTrue(i.has_level(self.u1, 'alfa', False))
self.assertFalse(i.has_level(self.u1, 'bravo', False))
def test_anonymous_user_level(self):
i = TestModel.objects.create(normal_field='Hello')
anon = AnonymousUser()
self.assertFalse(i.has_level(anon, 'alfa'))
self.assertFalse(i.has_level(anon, 'bravo'))
def test_middle_user_level(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
i.set_level(self.u1, 'bravo')
self.assertTrue(i.has_level(self.u1, 'alfa'))
self.assertTrue(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
def test_level_set_twice_same(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
i.set_level(self.u1, 'bravo')
i.set_level(self.u1, 'bravo')
self.assertTrue(i.has_level(self.u1, 'alfa'))
self.assertTrue(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
def test_level_set_twice_different(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
i.set_level(self.u1, 'charlie')
i.set_level(self.u1, 'bravo')
self.assertTrue(i.has_level(self.u1, 'alfa'))
self.assertTrue(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
def test_superuser(self):
i = TestModel.objects.create(normal_field='Hello')
for u, v in [(self.u1, False), (self.u2, False), (self.us, True)]:
self.assertEqual(i.has_level(u, 'alfa'), v)
self.assertEqual(i.has_level(u, 'bravo'), v)
self.assertEqual(i.has_level(u, 'charlie'), v)
def test_check_group_membership(self):
groups = self.u1.groups.values_list('id', flat=True)
self.assertIn(self.g1.id, groups)
self.assertTrue(self.g1.user_set.filter(id=self.u2.id).exists())
def test_lowest_group_level(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
i.set_level(self.g1, 'alfa')
self.assertTrue(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
def test_middle_group_level(self):
i = TestModel.objects.create(normal_field='Hello')
self.assertFalse(i.has_level(self.u1, 'alfa'))
self.assertFalse(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
i.set_level(self.g1, 'bravo')
self.assertTrue(i.has_level(self.u1, 'alfa'))
self.assertTrue(i.has_level(self.u1, 'bravo'))
self.assertFalse(i.has_level(self.u1, 'charlie'))
def test_set_level_error_handling(self):
with self.assertRaises(AttributeError):
TestModel.objects.create().set_level('wrong arg', 'level')
def test_get_users_with_level(self):
i1 = TestModel.objects.create(normal_field='Hello')
i2 = Test2Model.objects.create(normal2_field='Hello2')
i1.set_level(self.u1, 'bravo')
i1.set_level(self.u2, 'charlie')
i2.set_level(self.u1, 'one')
i2.set_level(self.us, u'three')
res1 = i1.get_users_with_level()
self.assertEqual([(self.u1, u'bravo'), (self.u2, u'charlie')], res1)
res2 = i2.get_users_with_level()
self.assertEqual([(self.u1, u'one'), (self.us, u'three')], res2)
def test_get_groups_with_level(self):
i1 = TestModel.objects.create(normal_field='Hello')
i2 = Test2Model.objects.create(normal2_field='Hello2')
i1.set_level(self.g1, 'bravo')
i1.set_level(self.u2, 'charlie')
i2.set_level(self.g1, 'one')
i2.set_level(self.us, u'three')
res1 = i1.get_groups_with_level()
self.assertEqual([(self.g1, u'bravo')], res1)
res2 = i2.get_groups_with_level()
self.assertEqual([(self.g1, u'one')], res2)
def test_object_level_unicode(self):
i1 = TestModel.objects.create(normal_field='Hello')
i1.set_level(self.g1, 'bravo')
unicode(ObjectLevel.objects.all()[0])
# Create your views here.
"""Common settings and globals.""" """Common settings and globals."""
from datetime import timedelta
from os import environ from os import environ
from os.path import abspath, basename, dirname, join, normpath from os.path import abspath, basename, dirname, join, normpath
from json import loads from json import loads
# from socket import SOCK_STREAM # from socket import SOCK_STREAM
from sys import path from sys import path
# Normally you should not import ANYTHING from Django directly # Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception. # into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
...@@ -236,6 +237,7 @@ LOCAL_APPS = ( ...@@ -236,6 +237,7 @@ LOCAL_APPS = (
'network', 'network',
'dashboard', 'dashboard',
'manager', 'manager',
'acl',
) )
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
...@@ -306,5 +308,12 @@ VM_ACCESS_PROTOCOLS = loads(get_env_variable('DJANGO_VM_ACCESS_PROTOCOLS', ...@@ -306,5 +308,12 @@ VM_ACCESS_PROTOCOLS = loads(get_env_variable('DJANGO_VM_ACCESS_PROTOCOLS',
"ssh": ["SSH", 22, "tcp"]}''')) "ssh": ["SSH", 22, "tcp"]}'''))
VM_SCHEDULER = 'manager.scheduler' VM_SCHEDULER = 'manager.scheduler'
BROKER_URL = get_env_variable('AMQP_URI')
BROKER_URL=get_env_variable('AMQP_URI') # Set up periodic firewall tasks
CELERYBEAT_SCHEDULE = {
'blabla': {
'task': 'firewall.tasks.local_tasks.periodic_task',
'schedule': timedelta(seconds=5),
},
}
...@@ -16,3 +16,9 @@ DATABASES = { ...@@ -16,3 +16,9 @@ DATABASES = {
"PORT": "", "PORT": "",
}, },
} }
SOUTH_TESTS_MIGRATE = False
INSTALLED_APPS += (
'acl.tests',
)
[
{
"pk": 1,
"model": "sites.site",
"fields": {
"domain": "example.com",
"name": "example.com"
}
},
{
"pk": 1,
"model": "vm.lease",
"fields": {
"suspend_interval_seconds": 18000,
"name": "lab",
"delete_interval_seconds": 180000
}
},
{
"pk": 1,
"model": "storage.datastore",
"fields": {
"path": "/disks",
"hostname": "wut",
"name": "diszkek"
}
},
{
"pk": 1,
"model": "storage.disk",
"fields": {
"name": "diszk",
"created": "2013-09-16T09:05:56.926Z",
"modified": "2013-09-19T09:10:25.117Z",
"filename": "disc.img",
"destroyed": null,
"base": null,
"ready": true,
"datastore": 1,
"dev_num": "a",
"type": "raw-rw",
"size": 8589934592
}
},
{
"pk": 1,
"model": "acl.level",
"fields": {
"codename": "owner",
"weight": 2,
"name": "owner",
"content_type": 15
}
},
{
"pk": 2,
"model": "acl.level",
"fields": {
"codename": "operator",
"weight": 1,
"name": "operator",
"content_type": 15
}
},
{
"pk": 3,
"model": "acl.level",
"fields": {
"codename": "user",
"weight": 0,
"name": "user",
"content_type": 15
}
},
{
"pk": 1,
"model": "auth.permission",
"fields": {
"codename": "add_permission",
"name": "Can add permission",
"content_type": 1
}
},
{
"pk": 2,
"model": "auth.permission",
"fields": {
"codename": "change_permission",
"name": "Can change permission",
"content_type": 1
}
},
{
"pk": 3,
"model": "auth.permission",
"fields": {
"codename": "delete_permission",
"name": "Can delete permission",
"content_type": 1
}
},
{
"pk": 4,
"model": "auth.permission",
"fields": {
"codename": "add_group",
"name": "Can add group",
"content_type": 2
}
},
{
"pk": 5,
"model": "auth.permission",
"fields": {
"codename": "change_group",
"name": "Can change group",
"content_type": 2
}
},
{
"pk": 6,
"model": "auth.permission",
"fields": {
"codename": "delete_group",
"name": "Can delete group",
"content_type": 2
}
},
{
"pk": 7,
"model": "auth.permission",
"fields": {
"codename": "add_user",
"name": "Can add user",
"content_type": 3
}
},
{
"pk": 8,
"model": "auth.permission",
"fields": {
"codename": "change_user",
"name": "Can change user",
"content_type": 3
}
},
{
"pk": 9,
"model": "auth.permission",
"fields": {
"codename": "delete_user",
"name": "Can delete user",
"content_type": 3
}
},
{
"pk": 10,
"model": "auth.permission",
"fields": {
"codename": "add_contenttype",
"name": "Can add content type",
"content_type": 4
}
},
{
"pk": 11,
"model": "auth.permission",
"fields": {
"codename": "change_contenttype",
"name": "Can change content type",
"content_type": 4
}
},
{
"pk": 12,
"model": "auth.permission",
"fields": {
"codename": "delete_contenttype",
"name": "Can delete content type",
"content_type": 4
}
},
{
"pk": 13,
"model": "auth.permission",
"fields": {
"codename": "add_session",
"name": "Can add session",
"content_type": 5
}
},
{
"pk": 14,
"model": "auth.permission",
"fields": {
"codename": "change_session",
"name": "Can change session",
"content_type": 5
}
},
{
"pk": 15,
"model": "auth.permission",
"fields": {
"codename": "delete_session",
"name": "Can delete session",
"content_type": 5
}
},
{
"pk": 16,
"model": "auth.permission",
"fields": {
"codename": "add_site",
"name": "Can add site",
"content_type": 6
}
},
{
"pk": 17,
"model": "auth.permission",
"fields": {
"codename": "change_site",
"name": "Can change site",
"content_type": 6
}
},
{
"pk": 18,
"model": "auth.permission",
"fields": {
"codename": "delete_site",
"name": "Can delete site",
"content_type": 6
}
},
{
"pk": 19,
"model": "auth.permission",
"fields": {
"codename": "add_logentry",
"name": "Can add log entry",
"content_type": 7
}
},
{
"pk": 20,
"model": "auth.permission",
"fields": {
"codename": "change_logentry",
"name": "Can change log entry",
"content_type": 7
}
},
{
"pk": 21,
"model": "auth.permission",
"fields": {
"codename": "delete_logentry",
"name": "Can delete log entry",
"content_type": 7
}
},
{
"pk": 22,
"model": "auth.permission",
"fields": {
"codename": "add_migrationhistory",
"name": "Can add migration history",
"content_type": 8
}
},
{
"pk": 23,
"model": "auth.permission",
"fields": {
"codename": "change_migrationhistory",
"name": "Can change migration history",
"content_type": 8
}
},
{
"pk": 24,
"model": "auth.permission",
"fields": {
"codename": "delete_migrationhistory",
"name": "Can delete migration history",
"content_type": 8
}
},
{
"pk": 25,
"model": "auth.permission",
"fields": {
"codename": "add_namedbaseresourceconfig",
"name": "Can add named base resource config",
"content_type": 9
}
},
{
"pk": 26,
"model": "auth.permission",
"fields": {
"codename": "change_namedbaseresourceconfig",
"name": "Can change named base resource config",
"content_type": 9
}
},
{
"pk": 27,
"model": "auth.permission",
"fields": {
"codename": "delete_namedbaseresourceconfig",
"name": "Can delete named base resource config",
"content_type": 9
}
},
{
"pk": 28,
"model": "auth.permission",
"fields": {
"codename": "add_node",
"name": "Can add node",
"content_type": 10
}
},
{
"pk": 29,
"model": "auth.permission",
"fields": {
"codename": "change_node",
"name": "Can change node",
"content_type": 10
}
},
{
"pk": 30,
"model": "auth.permission",
"fields": {
"codename": "delete_node",
"name": "Can delete node",
"content_type": 10
}
},
{
"pk": 31,
"model": "auth.permission",
"fields": {
"codename": "add_nodeactivity",
"name": "Can add node activity",
"content_type": 11
}
},
{
"pk": 32,
"model": "auth.permission",
"fields": {
"codename": "change_nodeactivity",
"name": "Can change node activity",
"content_type": 11
}
},
{
"pk": 33,
"model": "auth.permission",
"fields": {
"codename": "delete_nodeactivity",
"name": "Can delete node activity",
"content_type": 11
}
},
{
"pk": 34,
"model": "auth.permission",
"fields": {
"codename": "add_lease",
"name": "Can add lease",
"content_type": 12
}
},
{
"pk": 35,
"model": "auth.permission",
"fields": {
"codename": "change_lease",
"name": "Can change lease",
"content_type": 12
}
},
{
"pk": 36,
"model": "auth.permission",
"fields": {
"codename": "delete_lease",
"name": "Can delete lease",
"content_type": 12
}
},
{
"pk": 37,
"model": "auth.permission",
"fields": {
"codename": "add_instancetemplate",
"name": "Can add template",
"content_type": 13
}
},
{
"pk": 38,
"model": "auth.permission",
"fields": {
"codename": "change_instancetemplate",
"name": "Can change template",
"content_type": 13
}
},
{
"pk": 39,
"model": "auth.permission",
"fields": {
"codename": "delete_instancetemplate",
"name": "Can delete template",
"content_type": 13
}
},
{
"pk": 40,
"model": "auth.permission",
"fields": {
"codename": "add_interfacetemplate",
"name": "Can add interface template",
"content_type": 14
}
},
{
"pk": 41,
"model": "auth.permission",
"fields": {
"codename": "change_interfacetemplate",
"name": "Can change interface template",
"content_type": 14
}
},
{
"pk": 42,
"model": "auth.permission",
"fields": {
"codename": "delete_interfacetemplate",
"name": "Can delete interface template",
"content_type": 14
}
},
{
"pk": 43,
"model": "auth.permission",
"fields": {
"codename": "add_instance",
"name": "Can add instance",
"content_type": 15
}
},
{
"pk": 44,
"model": "auth.permission",
"fields": {
"codename": "change_instance",
"name": "Can change instance",
"content_type": 15
}
},
{
"pk": 45,
"model": "auth.permission",
"fields": {
"codename": "delete_instance",
"name": "Can delete instance",
"content_type": 15
}
},
{
"pk": 46,
"model": "auth.permission",
"fields": {
"codename": "add_instanceactivity",
"name": "Can add instance activity",
"content_type": 16
}
},
{
"pk": 47,
"model": "auth.permission",
"fields": {
"codename": "change_instanceactivity",
"name": "Can change instance activity",
"content_type": 16
}
},
{
"pk": 48,
"model": "auth.permission",
"fields": {
"codename": "delete_instanceactivity",
"name": "Can delete instance activity",
"content_type": 16
}
},
{
"pk": 49,
"model": "auth.permission",
"fields": {
"codename": "add_interface",
"name": "Can add interface",
"content_type": 17
}
},
{
"pk": 50,
"model": "auth.permission",
"fields": {
"codename": "change_interface",
"name": "Can change interface",
"content_type": 17
}
},
{
"pk": 51,
"model": "auth.permission",
"fields": {
"codename": "delete_interface",
"name": "Can delete interface",
"content_type": 17
}
},
{
"pk": 52,
"model": "auth.permission",
"fields": {
"codename": "add_datastore",
"name": "Can add datastore",
"content_type": 18
}
},
{
"pk": 53,
"model": "auth.permission",
"fields": {
"codename": "change_datastore",
"name": "Can change datastore",
"content_type": 18
}
},
{
"pk": 54,
"model": "auth.permission",
"fields": {
"codename": "delete_datastore",
"name": "Can delete datastore",
"content_type": 18
}
},
{
"pk": 55,
"model": "auth.permission",
"fields": {
"codename": "add_disk",
"name": "Can add disk",
"content_type": 19
}
},
{
"pk": 56,
"model": "auth.permission",
"fields": {
"codename": "change_disk",
"name": "Can change disk",
"content_type": 19
}
},
{
"pk": 57,
"model": "auth.permission",
"fields": {
"codename": "delete_disk",
"name": "Can delete disk",
"content_type": 19
}
},
{
"pk": 58,
"model": "auth.permission",
"fields": {
"codename": "add_rule",
"name": "Can add rule",
"content_type": 20
}
},
{
"pk": 59,
"model": "auth.permission",
"fields": {
"codename": "change_rule",
"name": "Can change rule",
"content_type": 20
}
},
{
"pk": 60,
"model": "auth.permission",
"fields": {
"codename": "delete_rule",
"name": "Can delete rule",
"content_type": 20
}
},
{
"pk": 61,
"model": "auth.permission",
"fields": {
"codename": "add_vlan",
"name": "Can add vlan",
"content_type": 21
}
},
{
"pk": 62,
"model": "auth.permission",
"fields": {
"codename": "change_vlan",
"name": "Can change vlan",
"content_type": 21
}
},
{
"pk": 63,
"model": "auth.permission",
"fields": {
"codename": "delete_vlan",
"name": "Can delete vlan",
"content_type": 21
}
},
{
"pk": 64,
"model": "auth.permission",
"fields": {
"codename": "add_vlangroup",
"name": "Can add vlan group",
"content_type": 22
}
},
{
"pk": 65,
"model": "auth.permission",
"fields": {
"codename": "change_vlangroup",
"name": "Can change vlan group",
"content_type": 22
}
},
{
"pk": 66,
"model": "auth.permission",
"fields": {
"codename": "delete_vlangroup",
"name": "Can delete vlan group",
"content_type": 22
}
},
{
"pk": 67,
"model": "auth.permission",
"fields": {
"codename": "add_group",
"name": "Can add group",
"content_type": 23
}
},
{
"pk": 68,
"model": "auth.permission",
"fields": {
"codename": "change_group",
"name": "Can change group",
"content_type": 23
}
},
{
"pk": 69,
"model": "auth.permission",
"fields": {
"codename": "delete_group",
"name": "Can delete group",
"content_type": 23
}
},
{
"pk": 70,
"model": "auth.permission",
"fields": {
"codename": "add_host",
"name": "Can add host",
"content_type": 24
}
},
{
"pk": 71,
"model": "auth.permission",
"fields": {
"codename": "change_host",
"name": "Can change host",
"content_type": 24
}
},
{
"pk": 72,
"model": "auth.permission",
"fields": {
"codename": "delete_host",
"name": "Can delete host",
"content_type": 24
}
},
{
"pk": 73,
"model": "auth.permission",
"fields": {
"codename": "add_firewall",
"name": "Can add firewall",
"content_type": 25
}
},
{
"pk": 74,
"model": "auth.permission",
"fields": {
"codename": "change_firewall",
"name": "Can change firewall",
"content_type": 25
}
},
{
"pk": 75,
"model": "auth.permission",
"fields": {
"codename": "delete_firewall",
"name": "Can delete firewall",
"content_type": 25
}
},
{
"pk": 76,
"model": "auth.permission",
"fields": {
"codename": "add_domain",
"name": "Can add domain",
"content_type": 26
}
},
{
"pk": 77,
"model": "auth.permission",
"fields": {
"codename": "change_domain",
"name": "Can change domain",
"content_type": 26
}
},
{
"pk": 78,
"model": "auth.permission",
"fields": {
"codename": "delete_domain",
"name": "Can delete domain",
"content_type": 26
}
},
{
"pk": 79,
"model": "auth.permission",
"fields": {
"codename": "add_record",
"name": "Can add record",
"content_type": 27
}
},
{
"pk": 80,
"model": "auth.permission",
"fields": {
"codename": "change_record",
"name": "Can change record",
"content_type": 27
}
},
{
"pk": 81,
"model": "auth.permission",
"fields": {
"codename": "delete_record",
"name": "Can delete record",
"content_type": 27
}
},
{
"pk": 82,
"model": "auth.permission",
"fields": {
"codename": "add_blacklist",
"name": "Can add blacklist",
"content_type": 28
}
},
{
"pk": 83,
"model": "auth.permission",
"fields": {
"codename": "change_blacklist",
"name": "Can change blacklist",
"content_type": 28
}
},
{
"pk": 84,
"model": "auth.permission",
"fields": {
"codename": "delete_blacklist",
"name": "Can delete blacklist",
"content_type": 28
}
},
{
"pk": 85,
"model": "auth.permission",
"fields": {
"codename": "add_taskmeta",
"name": "Can add task state",
"content_type": 29
}
},
{
"pk": 86,
"model": "auth.permission",
"fields": {
"codename": "change_taskmeta",
"name": "Can change task state",
"content_type": 29
}
},
{
"pk": 87,
"model": "auth.permission",
"fields": {
"codename": "delete_taskmeta",
"name": "Can delete task state",
"content_type": 29
}
},
{
"pk": 88,
"model": "auth.permission",
"fields": {
"codename": "add_tasksetmeta",
"name": "Can add saved group result",
"content_type": 30
}
},
{
"pk": 89,
"model": "auth.permission",
"fields": {
"codename": "change_tasksetmeta",
"name": "Can change saved group result",
"content_type": 30
}
},
{
"pk": 90,
"model": "auth.permission",
"fields": {
"codename": "delete_tasksetmeta",
"name": "Can delete saved group result",
"content_type": 30
}
},
{
"pk": 91,
"model": "auth.permission",
"fields": {
"codename": "add_intervalschedule",
"name": "Can add interval",
"content_type": 31
}
},
{
"pk": 92,
"model": "auth.permission",
"fields": {
"codename": "change_intervalschedule",
"name": "Can change interval",
"content_type": 31
}
},
{
"pk": 93,
"model": "auth.permission",
"fields": {
"codename": "delete_intervalschedule",
"name": "Can delete interval",
"content_type": 31
}
},
{
"pk": 94,
"model": "auth.permission",
"fields": {
"codename": "add_crontabschedule",
"name": "Can add crontab",
"content_type": 32
}
},
{
"pk": 95,
"model": "auth.permission",
"fields": {
"codename": "change_crontabschedule",
"name": "Can change crontab",
"content_type": 32
}
},
{
"pk": 96,
"model": "auth.permission",
"fields": {
"codename": "delete_crontabschedule",
"name": "Can delete crontab",
"content_type": 32
}
},
{
"pk": 97,
"model": "auth.permission",
"fields": {
"codename": "add_periodictasks",
"name": "Can add periodic tasks",
"content_type": 33
}
},
{
"pk": 98,
"model": "auth.permission",
"fields": {
"codename": "change_periodictasks",
"name": "Can change periodic tasks",
"content_type": 33
}
},
{
"pk": 99,
"model": "auth.permission",
"fields": {
"codename": "delete_periodictasks",
"name": "Can delete periodic tasks",
"content_type": 33
}
},
{
"pk": 100,
"model": "auth.permission",
"fields": {
"codename": "add_periodictask",
"name": "Can add periodic task",
"content_type": 34
}
},
{
"pk": 101,
"model": "auth.permission",
"fields": {
"codename": "change_periodictask",
"name": "Can change periodic task",
"content_type": 34
}
},
{
"pk": 102,
"model": "auth.permission",
"fields": {
"codename": "delete_periodictask",
"name": "Can delete periodic task",
"content_type": 34
}
},
{
"pk": 103,
"model": "auth.permission",
"fields": {
"codename": "add_workerstate",
"name": "Can add worker",
"content_type": 35
}
},
{
"pk": 104,
"model": "auth.permission",
"fields": {
"codename": "change_workerstate",
"name": "Can change worker",
"content_type": 35
}
},
{
"pk": 105,
"model": "auth.permission",
"fields": {
"codename": "delete_workerstate",
"name": "Can delete worker",
"content_type": 35
}
},
{
"pk": 106,
"model": "auth.permission",
"fields": {
"codename": "add_taskstate",
"name": "Can add task",
"content_type": 36
}
},
{
"pk": 107,
"model": "auth.permission",
"fields": {
"codename": "change_taskstate",
"name": "Can change task",
"content_type": 36
}
},
{
"pk": 108,
"model": "auth.permission",
"fields": {
"codename": "delete_taskstate",
"name": "Can delete task",
"content_type": 36
}
},
{
"pk": 109,
"model": "auth.permission",
"fields": {
"codename": "add_userobjectpermission",
"name": "Can add user object permission",
"content_type": 37
}
},
{
"pk": 110,
"model": "auth.permission",
"fields": {
"codename": "change_userobjectpermission",
"name": "Can change user object permission",
"content_type": 37
}
},
{
"pk": 111,
"model": "auth.permission",
"fields": {
"codename": "delete_userobjectpermission",
"name": "Can delete user object permission",
"content_type": 37
}
},
{
"pk": 112,
"model": "auth.permission",
"fields": {
"codename": "add_groupobjectpermission",
"name": "Can add group object permission",
"content_type": 38
}
},
{
"pk": 113,
"model": "auth.permission",
"fields": {
"codename": "change_groupobjectpermission",
"name": "Can change group object permission",
"content_type": 38
}
},
{
"pk": 114,
"model": "auth.permission",
"fields": {
"codename": "delete_groupobjectpermission",
"name": "Can delete group object permission",
"content_type": 38
}
},
{
"pk": 115,
"model": "auth.permission",
"fields": {
"codename": "own_instance",
"name": "owner",
"content_type": 15
}
},
{
"pk": 116,
"model": "auth.permission",
"fields": {
"codename": "operate_instance",
"name": "operator",
"content_type": 15
}
},
{
"pk": 117,
"model": "auth.permission",
"fields": {
"codename": "use_instance",
"name": "user",
"content_type": 15
}
},
{
"pk": 118,
"model": "auth.permission",
"fields": {
"codename": "add_diskactivity",
"name": "Can add disk activity",
"content_type": 39
}
},
{
"pk": 119,
"model": "auth.permission",
"fields": {
"codename": "change_diskactivity",
"name": "Can change disk activity",
"content_type": 39
}
},
{
"pk": 120,
"model": "auth.permission",
"fields": {
"codename": "delete_diskactivity",
"name": "Can delete disk activity",
"content_type": 39
}
},
{
"pk": 121,
"model": "auth.permission",
"fields": {
"codename": "add_level",
"name": "Can add level",
"content_type": 40
}
},
{
"pk": 122,
"model": "auth.permission",
"fields": {
"codename": "change_level",
"name": "Can change level",
"content_type": 40
}
},
{
"pk": 123,
"model": "auth.permission",
"fields": {
"codename": "delete_level",
"name": "Can delete level",
"content_type": 40
}
},
{
"pk": 127,
"model": "auth.permission",
"fields": {
"codename": "add_objectlevel",
"name": "Can add object level",
"content_type": 42
}
},
{
"pk": 128,
"model": "auth.permission",
"fields": {
"codename": "change_objectlevel",
"name": "Can change object level",
"content_type": 42
}
},
{
"pk": 129,
"model": "auth.permission",
"fields": {
"codename": "delete_objectlevel",
"name": "Can delete object level",
"content_type": 42
}
},
{
"pk": 130,
"model": "auth.permission",
"fields": {
"codename": "add_switchport",
"name": "Can add switch port",
"content_type": 43
}
},
{
"pk": 131,
"model": "auth.permission",
"fields": {
"codename": "change_switchport",
"name": "Can change switch port",
"content_type": 43
}
},
{
"pk": 132,
"model": "auth.permission",
"fields": {
"codename": "delete_switchport",
"name": "Can delete switch port",
"content_type": 43
}
},
{
"pk": 133,
"model": "auth.permission",
"fields": {
"codename": "add_ethernetdevice",
"name": "Can add ethernet device",
"content_type": 44
}
},
{
"pk": 134,
"model": "auth.permission",
"fields": {
"codename": "change_ethernetdevice",
"name": "Can change ethernet device",
"content_type": 44
}
},
{
"pk": 135,
"model": "auth.permission",
"fields": {
"codename": "delete_ethernetdevice",
"name": "Can delete ethernet device",
"content_type": 44
}
},
{
"pk": 1,
"model": "auth.group",
"fields": {
"name": "csopi",
"permissions": []
}
},
{
"pk": 2,
"model": "auth.group",
"fields": {
"name": "akkorszia",
"permissions": []
}
},
{
"pk": 3,
"model": "auth.group",
"fields": {
"name": "akkountsoherek",
"permissions": []
}
},
{
"pk": 4,
"model": "auth.group",
"fields": {
"name": "helog",
"permissions": []
}
},
{
"pk": -1,
"model": "auth.user",
"fields": {
"username": "AnonymousUser",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2013-09-30T12:37:38.484Z",
"groups": [],
"user_permissions": [],
"password": "",
"email": "",
"date_joined": "2013-09-30T12:37:38.484Z"
}
},
{
"pk": 1,
"model": "auth.user",
"fields": {
"username": "test",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"last_login": "2013-11-09T03:40:23.157Z",
"groups": [],
"user_permissions": [
115
],
"password": "pbkdf2_sha256$10000$KIoeMs78MiOj$PnVXn3YJMehbOciBO32CMzqL0ZnQrzrdb7+b5dE13os=",
"email": "test@example.org",
"date_joined": "2013-09-04T15:29:49.914Z"
}
},
{
"pk": 3,
"model": "auth.user",
"fields": {
"username": "proba",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2013-10-14T06:59:48Z",
"groups": [
1
],
"user_permissions": [],
"password": "",
"email": "",
"date_joined": "2013-10-14T06:59:48Z"
}
},
{
"pk": 4,
"model": "auth.user",
"fields": {
"username": "helo",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2013-11-09T01:11:41.534Z",
"groups": [
4
],
"user_permissions": [],
"password": "",
"email": "",
"date_joined": "2013-11-09T01:11:41.534Z"
}
},
{
"pk": 1,
"model": "vm.instance",
"fields": {
"destoryed": null,
"disks": [
1
],
"boot_menu": false,
"owner": 1,
"time_of_delete": null,
"max_ram_size": 200,
"pw": "ads",
"time_of_suspend": null,
"ram_size": 200,
"priority": 4,
"active_since": null,
"state": "NOSTATE",
"template": null,
"access_method": "nx",
"lease": 1,
"node": null,
"description": "",
"arch": "x86_64",
"name": "vanneve",
"created": "2013-09-16T09:05:59.991Z",
"raw_data": "",
"vnc_port": 1234,
"num_cores": 2,
"modified": "2013-10-14T07:27:38.192Z"
}
}
]
{% load i18n %}<!DOCTYPE html>
<html lang="{{lang}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>{% block title %}{% block title-page %}{% endblock %} | {% block title-site %}Circle{% endblock %}{% endblock %}</title>
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css">
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<script src="{{ STATIC_URL }}dashboard/js/jquery.knob.js"></script>
<script src="{{ STATIC_URL}}dashboard/bootstrap-slider/bootstrap-slider.js"></script>
<link rel="stylesheet" href="{{ STATIC_URL }}dashboard/bootstrap-slider/slider.css"/>
<link href="{{ STATIC_URL }}dashboard/dashboard.css" rel="stylesheet">
<script src="{{ STATIC_URL }}dashboard/dashboard.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<a class="navbar-brand" href="/dashboard/">{% block header-site %}Circle{% endblock %}</a>
</div>
<div class="container">
{% block content %}
<h1 class="alert alert-error">Please override "content" block.</h1>
{% endblock %}
<hr />
<footer>
<p>&copy; Company 2013</p>
</footer>
</div> <!-- /container -->
</body>
{% block extra_js %}
{% endblock %}
</html>
...@@ -5,16 +5,40 @@ ...@@ -5,16 +5,40 @@
<a href="#" class="btn btn-link">{% trans "Transfer ownership..." %}</a> <a href="#" class="btn btn-link">{% trans "Transfer ownership..." %}</a>
</p> </p>
<h3>{% trans "Permissions"|capfirst %}</h3> <h3>{% trans "Permissions"|capfirst %}</h3>
<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">
<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></th></tr></thead>
<tbody> <tbody>
<tr><td><i class="icon-user"></i></td><td>NEP123 (Gipsz Jakab)</td><td><select class="form-control"><option>owner</option></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> {% for i in acl.users %}
<tr><td><i class="icon-user"></i></td><td>NEP123 (Gipsz Jakab)</td><td><select class="form-control"><option>control</option></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> <tr><td><i class="icon-user"></i></td><td>{{i.user}}</td>
<tr><td><i class="icon-group"></i></td><td>Cloud-fejlesztők</td><td><select class="form-control"><option>view</option></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> <td><select class="form-control" name="perm-u-{{i.user.id}}">
<tr><td><i class="icon-plus"></i></td><td><input type="text" class="form-control"></td> {% for id, name in acl.levels %}
<td><select class="form-control"><option>owner</option></select></td><td></td></tr> <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> </tbody>
</table> </table>
<div class="form-actions"> <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>
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)
from django.test import TestCase
from django.test.client import Client
from django.contrib.auth.models import User, Group
class VmDetailTest(TestCase):
fixtures = ['test-vm-fixture.json']
def setUp(self):
self.u1 = User.objects.create(username='user1')
self.u2 = User.objects.create(username='user2', is_staff=True)
self.us = User.objects.create(username='superuser', is_superuser=True)
self.g1 = Group.objects.create(name='group1')
self.g1.user_set.add(self.u1)
self.g1.user_set.add(self.u2)
self.g1.save()
def test_404_vm_page(self):
c = Client()
response = c.get('/dashboard/vm/235555/')
self.assertEqual(response.status_code, 404)
def test_vm_page(self):
c = Client()
response = c.get('/dashboard/vm/1/')
self.assertEqual(response.status_code, 200)
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from .views import IndexView, VmDetailView, VmList, VmCreate, TemplateDetail from vm.models import Instance
from .views import (
IndexView, VmDetailView, VmList, VmCreate, TemplateDetail, AclUpdateView
)
urlpatterns = patterns( urlpatterns = patterns(
'', '',
...@@ -9,6 +12,8 @@ urlpatterns = patterns( ...@@ -9,6 +12,8 @@ urlpatterns = patterns(
name='dashboard.views.template-detail'), name='dashboard.views.template-detail'),
url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(), url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(),
name='dashboard.views.detail'), name='dashboard.views.detail'),
url(r'^vm/(?P<pk>\d+)/acl/$', AclUpdateView.as_view(model=Instance),
name='dashboard.views.vm-acl'),
url(r'^vm/list/$', VmList.as_view(), name='dashboard.views.vm-list'), url(r'^vm/list/$', VmList.as_view(), name='dashboard.views.vm-list'),
url(r'^vm/create/$', VmCreate.as_view(), url(r'^vm/create/$', VmCreate.as_view(),
name='dashboard.views.vm-create'), name='dashboard.views.vm-create'),
......
from os import getenv
import json
import logging
import re
from django.contrib.auth.models import User, Group
from django.contrib.messages import warning
from django.core import signing
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView, DetailView, View
from django.views.generic.detail import SingleObjectMixin
from django.http import HttpResponse from django.http import HttpResponse
from django.views.generic import TemplateView, DetailView from django.views.generic import TemplateView, DetailView
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
...@@ -6,13 +20,12 @@ from django.shortcuts import redirect ...@@ -6,13 +20,12 @@ from django.shortcuts import redirect
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from tables import VmListTable from tables import VmListTable
from .tables import VmListTable
from vm.models import Instance, InstanceTemplate, InterfaceTemplate from vm.models import Instance, InstanceTemplate, InterfaceTemplate
from firewall.models import Vlan from firewall.models import Vlan
from storage.models import Disk from storage.models import Disk
from django.core import signing
from os import getenv
import json logger = logging.getLogger(__name__)
class IndexView(TemplateView): class IndexView(TemplateView):
...@@ -40,12 +53,22 @@ class IndexView(TemplateView): ...@@ -40,12 +53,22 @@ class IndexView(TemplateView):
return context return context
def get_acl_data(obj):
levels = obj.ACL_LEVELS
users = obj.get_users_with_level()
users = [{'user': u, 'level': l} for u, l in users]
groups = obj.get_groups_with_level()
groups = [{'group': g, 'level': l} for g, l in groups]
return {'users': users, 'groups': groups, 'levels': levels,
'url': reverse('dashboard.views.vm-acl', args=[obj.pk])}
class VmDetailView(DetailView): class VmDetailView(DetailView):
template_name = "dashboard/vm-detail.html" template_name = "dashboard/vm-detail.html"
queryset = Instance.objects.all() model = Instance
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs) context = super(VmDetailView, self).get_context_data(**kwargs)
instance = context['instance'] instance = context['instance']
if instance.node: if instance.node:
port = instance.vnc_port port = instance.vnc_port
...@@ -56,9 +79,55 @@ class VmDetailView(DetailView): ...@@ -56,9 +79,55 @@ class VmDetailView(DetailView):
context.update({ context.update({
'vnc_url': '%s' % value 'vnc_url': '%s' % value
}) })
context['acl'] = get_acl_data(instance)
return context return context
class AclUpdateView(View, SingleObjectMixin):
def post(self, request, *args, **kwargs):
instance = self.get_object()
if not (instance.has_level(request.user, "owner") or
getattr(instance, 'owner', None) == request.user):
logger.warning('Tried to set permissions of %s by non-owner %s.',
unicode(instance), unicode(request.user))
raise PermissionDenied()
self.set_levels(request, instance)
self.add_levels(request, instance)
return redirect(instance)
def set_levels(self, request, instance):
for key, value in request.POST.items():
m = re.match('perm-([ug])-(\d+)', key)
if m:
type, id = m.groups()
entity = {'u': User, 'g': Group}[type].objects.get(id=id)
instance.set_level(entity, value)
logger.info("Set %s's acl level for %s to %s by %s.",
unicode(entity), unicode(instance),
value, unicode(request.user))
def add_levels(self, request, instance):
name = request.POST['perm-new-name']
value = request.POST['perm-new']
if not name:
return
try:
entity = User.objects.get(username=name)
except User.DoesNotExist:
entity = None
try:
entity = Group.objects.get(name=name)
except Group.DoesNotExist:
warning(request, _('User or group "%s" not found.') % name)
return
instance.set_level(entity, value)
logger.info("Set %s's new acl level for %s to %s by %s.",
unicode(entity), unicode(instance),
value, unicode(request.user))
class TemplateDetail(DetailView): class TemplateDetail(DetailView):
model = InstanceTemplate model = InstanceTemplate
......
...@@ -10,7 +10,7 @@ class Migration(SchemaMigration): ...@@ -10,7 +10,7 @@ class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'Rule.owner' # Adding field 'Rule.owner'
db.add_column('firewall_rule', 'owner', db.add_column('firewall_rule', 'owner',
self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['auth.User']), self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['auth.User']),
keep_default=False) keep_default=False)
...@@ -120,4 +120,4 @@ class Migration(SchemaMigration): ...@@ -120,4 +120,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['firewall'] complete_apps = ['firewall']
\ No newline at end of file
...@@ -21,7 +21,7 @@ class Migration(SchemaMigration): ...@@ -21,7 +21,7 @@ class Migration(SchemaMigration):
# Adding field 'Host.vlan' # Adding field 'Host.vlan'
db.add_column('firewall_host', 'vlan', db.add_column('firewall_host', 'vlan',
self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['firewall.Vlan']), self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['firewall.Vlan']),
keep_default=False) keep_default=False)
# Removing M2M table for field vlan on 'Host' # Removing M2M table for field vlan on 'Host'
...@@ -142,4 +142,4 @@ class Migration(SchemaMigration): ...@@ -142,4 +142,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['firewall'] complete_apps = ['firewall']
\ No newline at end of file
...@@ -15,7 +15,7 @@ class Migration(SchemaMigration): ...@@ -15,7 +15,7 @@ class Migration(SchemaMigration):
# Adding field 'Rule.nat_dport' # Adding field 'Rule.nat_dport'
db.add_column('firewall_rule', 'nat_dport', db.add_column('firewall_rule', 'nat_dport',
self.gf('django.db.models.fields.IntegerField')(default=None), self.gf('django.db.models.fields.IntegerField')(default=1),
keep_default=False) keep_default=False)
...@@ -126,4 +126,4 @@ class Migration(SchemaMigration): ...@@ -126,4 +126,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['firewall'] complete_apps = ['firewall']
\ No newline at end of file
...@@ -58,7 +58,7 @@ class Migration(SchemaMigration): ...@@ -58,7 +58,7 @@ class Migration(SchemaMigration):
# Adding field 'Rule.foreign_network' # Adding field 'Rule.foreign_network'
db.add_column('firewall_rule', 'foreign_network', db.add_column('firewall_rule', 'foreign_network',
self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='ForeignRules', to=orm['firewall.VlanGroup']), self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='ForeignRules', to=orm['firewall.VlanGroup']),
keep_default=False) keep_default=False)
# Adding field 'Rule.vlan' # Adding field 'Rule.vlan'
...@@ -295,4 +295,4 @@ class Migration(SchemaMigration): ...@@ -295,4 +295,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['firewall'] complete_apps = ['firewall']
\ No newline at end of file
...@@ -10,7 +10,7 @@ class Migration(SchemaMigration): ...@@ -10,7 +10,7 @@ class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'Vlan.domain' # Adding field 'Vlan.domain'
db.add_column('firewall_vlan', 'domain', db.add_column('firewall_vlan', 'domain',
self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['firewall.Domain']), self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['firewall.Domain']),
keep_default=False) keep_default=False)
...@@ -187,4 +187,4 @@ class Migration(SchemaMigration): ...@@ -187,4 +187,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['firewall'] complete_apps = ['firewall']
\ No newline at end of file
...@@ -21,7 +21,7 @@ class Migration(SchemaMigration): ...@@ -21,7 +21,7 @@ class Migration(SchemaMigration):
# Adding field 'Disk.datastore' # Adding field 'Disk.datastore'
db.add_column('storage_disk', 'datastore', db.add_column('storage_disk', 'datastore',
self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['storage.DataStore']), self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['storage.DataStore']),
keep_default=False) keep_default=False)
...@@ -56,4 +56,4 @@ class Migration(SchemaMigration): ...@@ -56,4 +56,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['storage'] complete_apps = ['storage']
\ No newline at end of file
{% load i18n %}
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Page not found" %}{% endblock %} {% block title %}{% trans "Page not found" %}{% endblock %}
......
{% load i18n %}
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %}
{% block title %}HTTP 500{% endblock %} {% block title %}HTTP 500{% endblock %}
......
...@@ -20,8 +20,7 @@ from .tasks import local_tasks, vm_tasks, net_tasks ...@@ -20,8 +20,7 @@ from .tasks import local_tasks, vm_tasks, net_tasks
from firewall.models import Vlan, Host from firewall.models import Vlan, Host
from storage.models import Disk from storage.models import Disk
from common.models import ActivityModel, activitycontextimpl from common.models import ActivityModel, activitycontextimpl
from django.core import signing from acl.models import AclBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
pwgen = User.objects.make_random_password pwgen = User.objects.make_random_password
...@@ -271,7 +270,7 @@ class InterfaceTemplate(Model): ...@@ -271,7 +270,7 @@ class InterfaceTemplate(Model):
verbose_name_plural = _('interface templates') verbose_name_plural = _('interface templates')
class Instance(VirtualMachineDescModel, TimeStampedModel): class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
"""Virtual machine instance. """Virtual machine instance.
...@@ -297,6 +296,11 @@ class Instance(VirtualMachineDescModel, TimeStampedModel): ...@@ -297,6 +296,11 @@ class Instance(VirtualMachineDescModel, TimeStampedModel):
('SHUTOFF', _('shutoff')), ('SHUTOFF', _('shutoff')),
('CRASHED', _('crashed')), ('CRASHED', _('crashed')),
('PMSUSPENDED', _('pmsuspended'))] # libvirt domain states ('PMSUSPENDED', _('pmsuspended'))] # libvirt domain states
ACL_LEVELS = (
('user', _('user')), # see all details
('operator', _('operator')), # console, networking, change state
('owner', _('owner')), # superuser, can delete, delegate perms
)
name = CharField(blank=True, max_length=100, verbose_name=_('name'), name = CharField(blank=True, max_length=100, verbose_name=_('name'),
help_text=_("Human readable name of instance.")) help_text=_("Human readable name of instance."))
description = TextField(blank=True, verbose_name=_('description')) description = TextField(blank=True, verbose_name=_('description'))
...@@ -337,7 +341,6 @@ class Instance(VirtualMachineDescModel, TimeStampedModel): ...@@ -337,7 +341,6 @@ class Instance(VirtualMachineDescModel, TimeStampedModel):
class Meta: class Meta:
ordering = ['pk', ] ordering = ['pk', ]
permissions = ()
verbose_name = _('instance') verbose_name = _('instance')
verbose_name_plural = _('instances') verbose_name_plural = _('instances')
......
from django.test import TestCase from django.test import TestCase
from .models import Template from ..models import InstanceTemplate
class TemplateTestCase(TestCase): class TemplateTestCase(TestCase):
def test_template_creation(self): def test_template_creation(self):
template = Template(name='My first template', template = InstanceTemplate(name='My first template',
access_method='ssh', ) # TODO add images & net access_method='ssh', )
# TODO add images & net
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