Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
a170119d
authored
Jul 23, 2014
by
Bach Dániel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-template-fixes' into 'master'
Template ACL fixes
👌
tests fixes
#195
fixes
#194
fixes
#208
parents
f0353c75
ce33b51c
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
418 additions
and
576 deletions
+418
-576
circle/circle/settings/base.py
+1
-0
circle/dashboard/autocomplete_light_registry.py
+21
-0
circle/dashboard/forms.py
+20
-7
circle/dashboard/models.py
+5
-0
circle/dashboard/templates/base.html
+1
-0
circle/dashboard/templates/dashboard/_disk-list-element.html
+2
-0
circle/dashboard/templates/dashboard/_manage_access.html
+75
-0
circle/dashboard/templates/dashboard/group-detail.html
+1
-70
circle/dashboard/templates/dashboard/template-edit.html
+1
-69
circle/dashboard/templates/dashboard/vm-detail/access.html
+1
-61
circle/dashboard/tests/test_mockedviews.py
+74
-0
circle/dashboard/tests/test_views.py
+24
-107
circle/dashboard/urls.py
+6
-7
circle/dashboard/views.py
+162
-156
circle/network/templates/network/vlan-edit.html
+1
-55
circle/network/tests/test_views.py
+9
-9
circle/network/urls.py
+1
-1
circle/network/views.py
+4
-12
circle/storage/models.py
+8
-15
circle/vm/models/instance.py
+0
-7
requirements/base.txt
+1
-0
No files found.
circle/circle/settings/base.py
View file @
a170119d
...
@@ -260,6 +260,7 @@ THIRD_PARTY_APPS = (
...
@@ -260,6 +260,7 @@ THIRD_PARTY_APPS = (
'taggit'
,
'taggit'
,
'statici18n'
,
'statici18n'
,
'django_sshkey'
,
'django_sshkey'
,
'autocomplete_light'
,
)
)
# Apps specific for this project go here.
# Apps specific for this project go here.
...
...
circle/dashboard/autocomplete_light_registry.py
0 → 100644
View file @
a170119d
import
autocomplete_light
from
django.utils.translation
import
ugettext
as
_
from
.views
import
AclUpdateView
class
AclUserAutocomplete
(
autocomplete_light
.
AutocompleteGenericBase
):
search_fields
=
(
(
'^first_name'
,
'last_name'
,
'username'
,
'^email'
,
'profile__org_id'
),
(
'^name'
,
'groupprofile__org_id'
),
)
autocomplete_js_attributes
=
{
'placeholder'
:
_
(
"Name of group or user"
)}
def
choices_for_request
(
self
):
user
=
self
.
request
.
user
self
.
choices
=
(
AclUpdateView
.
get_allowed_users
(
user
),
AclUpdateView
.
get_allowed_groups
(
user
))
return
super
(
AclUserAutocomplete
,
self
)
.
choices_for_request
()
autocomplete_light
.
register
(
AclUserAutocomplete
)
circle/dashboard/forms.py
View file @
a170119d
...
@@ -27,6 +27,7 @@ from django.contrib.auth.models import User, Group
...
@@ -27,6 +27,7 @@ from django.contrib.auth.models import User, Group
from
django.core.validators
import
URLValidator
from
django.core.validators
import
URLValidator
from
django.core.exceptions
import
PermissionDenied
,
ValidationError
from
django.core.exceptions
import
PermissionDenied
,
ValidationError
import
autocomplete_light
from
crispy_forms.helper
import
FormHelper
from
crispy_forms.helper
import
FormHelper
from
crispy_forms.layout
import
(
from
crispy_forms.layout
import
(
Layout
,
Div
,
BaseInput
,
Field
,
HTML
,
Submit
,
Fieldset
,
TEMPLATE_PACK
,
Layout
,
Div
,
BaseInput
,
Field
,
HTML
,
Submit
,
Fieldset
,
TEMPLATE_PACK
,
...
@@ -44,7 +45,6 @@ from django.core.urlresolvers import reverse_lazy
...
@@ -44,7 +45,6 @@ from django.core.urlresolvers import reverse_lazy
from
django_sshkey.models
import
UserKey
from
django_sshkey.models
import
UserKey
from
firewall.models
import
Vlan
,
Host
from
firewall.models
import
Vlan
,
Host
from
storage.models
import
Disk
from
vm.models
import
(
from
vm.models
import
(
InstanceTemplate
,
Lease
,
InterfaceTemplate
,
Node
,
Trait
,
Instance
InstanceTemplate
,
Lease
,
InterfaceTemplate
,
Node
,
Trait
,
Instance
)
)
...
@@ -78,7 +78,7 @@ class VmCustomizeForm(forms.Form):
...
@@ -78,7 +78,7 @@ class VmCustomizeForm(forms.Form):
amount
=
forms
.
IntegerField
(
min_value
=
0
,
initial
=
1
)
amount
=
forms
.
IntegerField
(
min_value
=
0
,
initial
=
1
)
disks
=
forms
.
ModelMultipleChoiceField
(
disks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
None
,
required
=
Tru
e
)
queryset
=
None
,
required
=
Fals
e
)
networks
=
forms
.
ModelMultipleChoiceField
(
networks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
None
,
required
=
False
)
queryset
=
None
,
required
=
False
)
...
@@ -91,8 +91,7 @@ class VmCustomizeForm(forms.Form):
...
@@ -91,8 +91,7 @@ class VmCustomizeForm(forms.Form):
super
(
VmCustomizeForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
VmCustomizeForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
# set displayed disk and network list
# set displayed disk and network list
self
.
fields
[
'disks'
]
.
queryset
=
Disk
.
get_objects_with_level
(
self
.
fields
[
'disks'
]
.
queryset
=
self
.
template
.
disks
.
all
()
'user'
,
self
.
user
)
.
exclude
(
type
=
"qcow2-snap"
)
self
.
fields
[
'networks'
]
.
queryset
=
Vlan
.
get_objects_with_level
(
self
.
fields
[
'networks'
]
.
queryset
=
Vlan
.
get_objects_with_level
(
'user'
,
self
.
user
)
'user'
,
self
.
user
)
...
@@ -596,8 +595,12 @@ class TemplateForm(forms.ModelForm):
...
@@ -596,8 +595,12 @@ class TemplateForm(forms.ModelForm):
n
=
self
.
instance
.
interface_set
.
values_list
(
"vlan"
,
flat
=
True
)
n
=
self
.
instance
.
interface_set
.
values_list
(
"vlan"
,
flat
=
True
)
self
.
initial
[
'networks'
]
=
n
self
.
initial
[
'networks'
]
=
n
self
.
allowed_fields
=
(
if
self
.
instance
.
pk
and
not
self
.
instance
.
has_level
(
self
.
user
,
'name'
,
'access_method'
,
'description'
,
'system'
,
'tags'
)
'owner'
):
self
.
allowed_fields
=
()
else
:
self
.
allowed_fields
=
(
'name'
,
'access_method'
,
'description'
,
'system'
,
'tags'
)
if
self
.
user
.
has_perm
(
'vm.change_template_resources'
):
if
self
.
user
.
has_perm
(
'vm.change_template_resources'
):
self
.
allowed_fields
+=
tuple
(
set
(
self
.
fields
.
keys
())
-
self
.
allowed_fields
+=
tuple
(
set
(
self
.
fields
.
keys
())
-
set
([
'raw_data'
]))
set
([
'raw_data'
]))
...
@@ -675,6 +678,11 @@ class TemplateForm(forms.ModelForm):
...
@@ -675,6 +678,11 @@ class TemplateForm(forms.ModelForm):
@property
@property
def
helper
(
self
):
def
helper
(
self
):
submit_kwargs
=
{}
if
self
.
instance
.
pk
and
not
self
.
instance
.
has_level
(
self
.
user
,
'owner'
):
submit_kwargs
[
'disabled'
]
=
None
helper
=
FormHelper
()
helper
=
FormHelper
()
helper
.
layout
=
Layout
(
helper
.
layout
=
Layout
(
Field
(
"name"
),
Field
(
"name"
),
...
@@ -739,7 +747,7 @@ class TemplateForm(forms.ModelForm):
...
@@ -739,7 +747,7 @@ class TemplateForm(forms.ModelForm):
Field
(
"tags"
),
Field
(
"tags"
),
),
),
)
)
helper
.
add_input
(
Submit
(
'submit'
,
'Save changes'
))
helper
.
add_input
(
Submit
(
'submit'
,
'Save changes'
,
**
submit_kwargs
))
return
helper
return
helper
class
Meta
:
class
Meta
:
...
@@ -1178,6 +1186,11 @@ class UserCreationForm(OrgUserCreationForm):
...
@@ -1178,6 +1186,11 @@ class UserCreationForm(OrgUserCreationForm):
return
user
return
user
class
AclUserAddForm
(
forms
.
Form
):
name
=
forms
.
CharField
(
widget
=
autocomplete_light
.
TextWidget
(
'AclUserAutocomplete'
,
attrs
=
{
'class'
:
'form-control'
}))
class
UserKeyForm
(
forms
.
ModelForm
):
class
UserKeyForm
(
forms
.
ModelForm
):
name
=
forms
.
CharField
(
required
=
True
,
label
=
_
(
'Name'
))
name
=
forms
.
CharField
(
required
=
True
,
label
=
_
(
'Name'
))
key
=
forms
.
CharField
(
key
=
forms
.
CharField
(
...
...
circle/dashboard/models.py
View file @
a170119d
...
@@ -142,6 +142,11 @@ class Profile(Model):
...
@@ -142,6 +142,11 @@ class Profile(Model):
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
get_display_name
()
return
self
.
get_display_name
()
class
Meta
:
permissions
=
(
(
'use_autocomplete'
,
_
(
'Can use autocomplete.'
)),
)
class
FutureMember
(
Model
):
class
FutureMember
(
Model
):
org_id
=
CharField
(
max_length
=
64
,
help_text
=
_
(
org_id
=
CharField
(
max_length
=
64
,
help_text
=
_
(
...
...
circle/dashboard/templates/base.html
View file @
a170119d
...
@@ -70,6 +70,7 @@
...
@@ -70,6 +70,7 @@
<script
src=
"//code.jquery.com/jquery-1.11.1.min.js"
></script>
<script
src=
"//code.jquery.com/jquery-1.11.1.min.js"
></script>
<script
src=
"//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"
></script>
<script
src=
"//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"
></script>
<script
src=
"{{ STATIC_URL }}jsi18n/{{ LANGUAGE_CODE }}/djangojs.js"
></script>
<script
src=
"{{ STATIC_URL }}jsi18n/{{ LANGUAGE_CODE }}/djangojs.js"
></script>
{% include 'autocomplete_light/static.html' %}
{% block extra_script %}
{% block extra_script %}
{% endblock %}
{% endblock %}
...
...
circle/dashboard/templates/dashboard/_disk-list-element.html
View file @
a170119d
...
@@ -10,10 +10,12 @@
...
@@ -10,10 +10,12 @@
<div
class=
"label label-danger"
{%
if
user
.
is_superuser
%}
title=
"{{ d.get_latest_activity_result }}"
{%
endif
%}
>
{% trans "failed" %}
</div>
<div
class=
"label label-danger"
{%
if
user
.
is_superuser
%}
title=
"{{ d.get_latest_activity_result }}"
{%
endif
%}
>
{% trans "failed" %}
</div>
{% endif %}
{% endif %}
{% else %}
<span
class=
"disk-list-disk-percentage"
data-disk-pk=
"{{ d.pk }}"
>
{{ d.get_download_percentage }}
</span>
%{% endif %}
{% else %}
<span
class=
"disk-list-disk-percentage"
data-disk-pk=
"{{ d.pk }}"
>
{{ d.get_download_percentage }}
</span>
%{% endif %}
{% if is_owner != False %}
<a
href=
"{% url "
dashboard
.
views
.
disk-remove
"
pk=
d.pk
%}?
next=
{{
request
.
path
}}"
<a
href=
"{% url "
dashboard
.
views
.
disk-remove
"
pk=
d.pk
%}?
next=
{{
request
.
path
}}"
data-disk-pk=
"{{ d.pk }}"
class=
"btn btn-xs btn-danger pull-right disk-remove"
data-disk-pk=
"{{ d.pk }}"
class=
"btn btn-xs btn-danger pull-right disk-remove"
{%
if
not
long_remove
%}
title=
"{% trans "
Remove
"
%}"{%
endif
%}
{%
if
not
long_remove
%}
title=
"{% trans "
Remove
"
%}"{%
endif
%}
>
>
<i
class=
"fa fa-times"
></i>
{% if long_remove %} {% trans "Remove" %}{% endif %}
<i
class=
"fa fa-times"
></i>
{% if long_remove %} {% trans "Remove" %}{% endif %}
</a>
</a>
{% endif %}
<div
style=
"clear: both;"
></div>
<div
style=
"clear: both;"
></div>
circle/dashboard/templates/dashboard/_manage_access.html
0 → 100644
View file @
a170119d
{% load i18n %}
<form
action=
"{{ acl.url }}"
method=
"post"
>
{% csrf_token %}
<table
class=
"table table-striped table-with-form-fields"
id=
"{{table_id}}"
>
<thead>
<tr>
<th></th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "What" %}
</th>
<th><i
class=
"fa fa-times"
></i></th>
</tr>
</thead>
<tbody>
{% for i in acl.users %}
<tr>
<td>
<i
class=
"fa fa-user"
></i>
</td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"
title=
"{{ i.user.username }}"
>
{% include "dashboard/_display-name.html" with user=i.user show_org=True %}
</a>
</td>
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
{%
if
i
.
level
not
in
acl
.
allowed_levels
%}
disabled
{%
endif
%}
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
{%
if
id
not
in
acl
.
allowed_levels
%}
disabled
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td>
<input
type=
"checkbox"
name=
"remove-u-{{i.user.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
{% for i in acl.groups %}
<tr>
<td><i
class=
"fa fa-group"
></i></td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
i.group.pk
%}"
>
{{i.group}}
</a>
</td>
<td>
<select
class=
"form-control"
name=
"perm-g-{{i.group.id}}{% if i.level not in acl.allowed_levels %} disabled{% endif %}"
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
{%
if
id
not
in
acl
.
allowed_levels
%}
disabled
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td>
<input
type=
"checkbox"
name=
"remove-g-{{i.group.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
<tr><td><i
class=
"fa fa-plus"
></i></td>
<td>
{{aclform.name }}
</td>
<td><select
class=
"form-control"
name=
"level"
>
{% for id, name in acl.levels %}
{% if id in acl.allowed_levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endif %}
{% endfor %}
</select></td><td></td>
</tr>
</tbody>
</table>
<div
class=
"form-actions"
>
<button
type=
"submit"
class=
"btn btn-success"
>
{% trans "Save" %}
</button>
</div>
</form>
circle/dashboard/templates/dashboard/group-detail.html
View file @
a170119d
...
@@ -104,76 +104,7 @@
...
@@ -104,76 +104,7 @@
<hr
/>
<hr
/>
<h3
id=
"group-detail-perm-header"
>
{% trans "Access permissions"|capfirst %}
</h3>
<h3
id=
"group-detail-perm-header"
>
{% trans "Access permissions"|capfirst %}
</h3>
<form
action=
"{{acl.url}}"
method=
"post"
>
{% csrf_token %}
{% include "dashboard/_manage_access.html" with table_id="group-detail-perm-table" %}
<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>
{% trans "Remove" %}
</th>
</tr>
</thead>
<tbody>
{% for i in acl.users %}
<tr>
<td>
<i
class=
"fa fa-user"
></i>
</td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"
title=
"{{ i.user.username }}"
>
{% include "dashboard/_display-name.html" with user=i.user show_org=True %}
</a>
</td>
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td
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=
"fa fa-times"
><span
class=
"sr-only"
>
{% trans "remove" %}
</span></i></a></td>
</tr>
{% endfor %}
{% for i in acl.groups %}
<tr>
<td>
<i
class=
"fa fa-group"
></i>
</td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
i.group.pk
%}"
>
{{ i.group }}
</a>
</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=
"fa fa-times"
><span
class=
"sr-only"
>
{% trans "remove" %}
</span></i></a>
</td>
</tr>
{% endfor %}
<tr>
<td><i
class=
"fa fa-plus"
></i></td>
<td>
<input
type=
"text"
class=
"form-control"
name=
"perm-new-name"
placeholder=
"{% trans "
Name
of
group
or
user
"
%}"
>
</td>
<td>
<select
class=
"form-control"
name=
"perm-new"
>
{% for id, name in acl.levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td></td>
</tr>
</tbody>
</table>
<div
class=
"form-actions"
>
<button
type=
"submit"
class=
"btn btn-success"
>
{% trans "Save" %}
</button>
</div>
</form>
{% if user.is_superuser %}
{% if user.is_superuser %}
<hr
/>
<hr
/>
...
...
circle/dashboard/templates/dashboard/template-edit.html
View file @
a170119d
...
@@ -29,75 +29,7 @@
...
@@ -29,75 +29,7 @@
<h4
class=
"no-margin"
><i
class=
"fa fa-group"
></i>
{% trans "Manage access" %}
</h4>
<h4
class=
"no-margin"
><i
class=
"fa fa-group"
></i>
{% trans "Manage access" %}
</h4>
</div>
</div>
<div
class=
"panel-body"
>
<div
class=
"panel-body"
>
<form
action=
"{% url "
dashboard
.
views
.
template-acl
"
pk=
object.pk
%}"
method=
"post"
>
{% csrf_token %}
{% include "dashboard/_manage_access.html" with table_id="template-access-table" %}
<table
class=
"table table-striped table-with-form-fields"
id=
"template-access-table"
>
<thead>
<tr>
<th></th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "What" %}
</th>
<th><i
class=
"fa fa-times"
></i></th>
</tr>
</thead>
<tbody>
{% for i in acl.users %}
<tr>
<td>
<i
class=
"fa fa-user"
></i>
</td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"
title=
"{{ i.user.username }}"
>
{% include "dashboard/_display-name.html" with user=i.user show_org=True %}
</a>
</td>
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td>
<input
type=
"checkbox"
name=
"remove-u-{{i.user.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
{% for i in acl.groups %}
<tr>
<td><i
class=
"fa fa-group"
></i></td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
i.group.pk
%}"
>
{{i.group}}
</a>
</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>
<input
type=
"checkbox"
name=
"remove-g-{{i.group.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
<tr><td><i
class=
"fa fa-plus"
></i></td>
<td><input
type=
"text"
class=
"form-control"
name=
"perm-new-name"
placeholder=
"{% trans "
Name
of
group
or
user
"
%}"
></td>
<td><select
class=
"form-control"
name=
"perm-new"
>
{% for id, name in acl.levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select></td><td></td>
</tr>
</tbody>
</table>
<div
class=
"form-actions"
>
<button
type=
"submit"
class=
"btn btn-success"
>
{% trans "Save" %}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
...
...
circle/dashboard/templates/dashboard/vm-detail/access.html
View file @
a170119d
...
@@ -14,64 +14,4 @@
...
@@ -14,64 +14,4 @@
{% endif %}
{% endif %}
</p>
</p>
<h3>
{% trans "Permissions"|capfirst %}
</h3>
<h3>
{% trans "Permissions"|capfirst %}
</h3>
<form
action=
"{{acl.url}}"
method=
"post"
>
{% csrf_token %}
{% include "dashboard/_manage_access.html" with table_id="vm-access-table" %}
<table
class=
"table table-striped table-with-form-fields"
id=
"vm-access-table"
>
<thead><tr>
<th></th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "What" %}
</th>
<th>
{% trans "Remove" %}
</th>
</tr></thead>
<tbody>
{% for i in acl.users %}
<tr>
<td><i
class=
"fa fa-user"
></i></td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"
title=
"{{ i.user.username }}"
>
{% include "dashboard/_display-name.html" with user=i.user show_org=True %}
</a>
</td>
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td>
<input
type=
"checkbox"
name=
"remove-u-{{i.user.id}}"
/>
</td>
</tr>
{% endfor %}
{% for i in acl.groups %}
<tr>
<td><i
class=
"fa fa-group"
></i></td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
i.group.pk
%}"
>
{{ i.group.name }}
</a>
</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>
<input
type=
"checkbox"
name=
"remove-g-{{i.group.id}}"
/>
</td>
</tr>
{% endfor %}
<tr><td><i
class=
"fa fa-plus"
></i></td>
<td><input
type=
"text"
class=
"form-control"
name=
"perm-new-name"
placeholder=
"{% trans "
Name
of
group
or
user
"
%}"
></td>
<td><select
class=
"form-control"
name=
"perm-new"
>
{% for id, name in acl.levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select></td><td></td>
</tr>
</tbody>
</table>
<div
class=
"form-actions"
>
<button
type=
"submit"
class=
"btn btn-success"
>
{% trans "Save" %}
</button>
</div>
</form>
circle/dashboard/tests/test_mockedviews.py
View file @
a170119d
...
@@ -30,6 +30,7 @@ from django.utils import baseconv
...
@@ -30,6 +30,7 @@ from django.utils import baseconv
from
..models
import
Profile
from
..models
import
Profile
from
..views
import
InstanceActivityDetail
,
InstanceActivity
from
..views
import
InstanceActivityDetail
,
InstanceActivity
from
..views
import
vm_ops
,
Instance
,
UnsubscribeFormView
from
..views
import
vm_ops
,
Instance
,
UnsubscribeFormView
from
..views
import
AclUpdateView
from
..
import
views
from
..
import
views
...
@@ -429,6 +430,79 @@ class RenewViewTest(unittest.TestCase):
...
@@ -429,6 +430,79 @@ class RenewViewTest(unittest.TestCase):
view
.
as_view
()(
request
,
pk
=
1234
)[
'location'
])
view
.
as_view
()(
request
,
pk
=
1234
)[
'location'
])
class
AclUpdateViewTest
(
unittest
.
TestCase
):
def
test_has_next_level
(
self
):
data
=
{
None
:
'user'
,
'user'
:
'operator'
,
'operator'
:
'owner'
,
'owner'
:
'owner'
}
for
k
,
v
in
data
.
items
():
inst
=
MagicMock
(
spec
=
Instance
)
inst
.
has_level
.
return_value
=
True
inst
.
ACL_LEVELS
=
Instance
.
ACL_LEVELS
self
.
assertTrue
(
AclUpdateView
.
has_next_level
(
'dummy'
,
inst
,
k
))
inst
.
has_level
.
assert_called_with
(
'dummy'
,
v
)
def
test_set_level_mod_owner
(
self
):
with
patch
(
'dashboard.views.messages'
)
as
msg
:
request
=
FakeRequestFactory
(
POST
=
{})
inst
=
MagicMock
(
spec
=
Instance
)
inst
.
owner
=
request
.
user
v
=
AclUpdateView
()
v
.
instance
=
inst
v
.
request
=
request
v
.
get_level
=
MagicMock
(
return_value
=
'owner'
)
v
.
check_auth
=
MagicMock
(
side_effect
=
Exception
(
''
))
v
.
set_level
(
request
.
user
,
'user'
)
v
.
get_level
.
assert_called_with
(
request
.
user
)
assert
not
v
.
check_auth
.
called
assert
msg
.
warning
.
called
def
test_set_level_permitted
(
self
):
data
=
((
'user'
,
'owner'
,
(
'user'
,
'operator'
,
'owner'
),
False
),
(
None
,
None
,
(
'user'
,
),
True
),
(
'user'
,
None
,
(
'user'
,
),
True
),
(
None
,
'user'
,
(
'user'
,
),
True
),
(
'operator'
,
'owner'
,
(
'user'
,
'operator'
),
True
),
(
None
,
'user'
,
(
'user'
,
'operator'
),
False
))
for
old_level
,
new_level
,
allowed_levels
,
fail
in
data
:
with
patch
(
'dashboard.views.messages'
)
as
msg
:
def
has_level
(
user
,
level
):
return
level
in
allowed_levels
request
=
FakeRequestFactory
(
POST
=
{})
inst
=
MagicMock
(
spec
=
Instance
)
inst
.
has_level
.
side_effect
=
has_level
inst
.
ACL_LEVELS
=
Instance
.
ACL_LEVELS
v
=
AclUpdateView
()
v
.
instance
=
inst
v
.
request
=
request
v
.
is_owner
=
True
v
.
get_level
=
MagicMock
(
return_value
=
old_level
)
v
.
set_level
(
request
.
user
,
new_level
)
v
.
get_level
.
assert_called_with
(
request
.
user
)
assert
(
new_level
==
old_level
)
^
inst
.
has_level
.
called
assert
fail
^
inst
.
set_level
.
called
assert
fail
^
msg
.
success
.
called
def
test_readd
(
self
):
request
=
FakeRequestFactory
(
POST
=
{
'name'
:
'user0'
,
'level'
:
'user'
})
with
patch
(
'dashboard.views.messages'
)
as
msg
:
with
patch
.
object
(
AclUpdateView
,
'get_object'
)
as
go
:
view
=
AclUpdateView
.
as_view
()
inst
=
MagicMock
(
spec
=
Instance
)
go
.
return_value
=
inst
view
(
request
)
assert
msg
.
warning
.
called
def
FakeRequestFactory
(
user
=
None
,
**
kwargs
):
def
FakeRequestFactory
(
user
=
None
,
**
kwargs
):
''' FakeRequestFactory, FakeMessages and FakeRequestContext are good for
''' FakeRequestFactory, FakeMessages and FakeRequestContext are good for
mocking out django views; they are MUCH faster than the Django test client.
mocking out django views; they are MUCH faster than the Django test client.
...
...
circle/dashboard/tests/test_views.py
View file @
a170119d
...
@@ -27,7 +27,6 @@ from django.contrib.auth import authenticate
...
@@ -27,7 +27,6 @@ from django.contrib.auth import authenticate
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
,
Trait
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
,
Trait
from
vm.operations
import
WakeUpOperation
from
vm.operations
import
WakeUpOperation
from
..models
import
Profile
from
..models
import
Profile
from
storage.models
import
Disk
from
firewall.models
import
Vlan
,
Host
,
VlanGroup
from
firewall.models
import
Vlan
,
Host
,
VlanGroup
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
django_sshkey.models
import
UserKey
from
django_sshkey.models
import
UserKey
...
@@ -249,7 +248,6 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -249,7 +248,6 @@ class VmDetailTest(LoginMixin, TestCase):
def
test_use_unpermitted_template
(
self
):
def
test_use_unpermitted_template
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
Disk
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
response
=
c
.
post
(
'/dashboard/vm/create/'
,
response
=
c
.
post
(
'/dashboard/vm/create/'
,
{
'template'
:
1
,
{
'template'
:
1
,
...
@@ -261,7 +259,6 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -261,7 +259,6 @@ class VmDetailTest(LoginMixin, TestCase):
def
test_use_permitted_template
(
self
):
def
test_use_permitted_template
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
Disk
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
InstanceTemplate
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
InstanceTemplate
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
response
=
c
.
post
(
'/dashboard/vm/create/'
,
response
=
c
.
post
(
'/dashboard/vm/create/'
,
...
@@ -293,7 +290,6 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -293,7 +290,6 @@ class VmDetailTest(LoginMixin, TestCase):
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
tmpl
=
InstanceTemplate
.
objects
.
get
(
id
=
1
)
tmpl
=
InstanceTemplate
.
objects
.
get
(
id
=
1
)
tmpl
.
set_level
(
self
.
u1
,
'owner'
)
tmpl
.
set_level
(
self
.
u1
,
'owner'
)
tmpl
.
disks
.
get
()
.
set_level
(
self
.
u1
,
'owner'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
Vlan
.
objects
.
get
(
id
=
1
)
.
set_level
(
self
.
u1
,
'user'
)
kwargs
=
tmpl
.
__dict__
.
copy
()
kwargs
=
tmpl
.
__dict__
.
copy
()
kwargs
.
update
(
name
=
't1'
,
lease
=
1
,
disks
=
1
,
raw_data
=
'tst1'
)
kwargs
.
update
(
name
=
't1'
,
lease
=
1
,
disks
=
1
,
raw_data
=
'tst1'
)
...
@@ -591,7 +587,6 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -591,7 +587,6 @@ class VmDetailTest(LoginMixin, TestCase):
'template'
:
1
,
'template'
:
1
,
'cpu_priority'
:
1
,
'cpu_count'
:
1
,
'ram_size'
:
1
,
'cpu_priority'
:
1
,
'cpu_count'
:
1
,
'ram_size'
:
1
,
'network'
:
[],
'network'
:
[],
'disks'
:
[
Disk
.
objects
.
get
(
id
=
1
)
.
pk
],
})
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1248,7 +1243,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1248,7 +1243,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_users
=
len
(
gp
.
get_users_with_level
())
acl_users
=
len
(
gp
.
get_users_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'user3'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'user3'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_users
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
acl_users
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1259,9 +1254,9 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1259,9 +1254,9 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_users
=
len
(
gp
.
get_users_with_level
())
acl_users
=
len
(
gp
.
get_users_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'user3'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'user3'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_users
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
acl_users
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
302
)
def
test_superuser_add_acluser_to_group
(
self
):
def
test_superuser_add_acluser_to_group
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -1270,7 +1265,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1270,7 +1265,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_users
=
len
(
gp
.
get_users_with_level
())
acl_users
=
len
(
gp
.
get_users_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'user3'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'user3'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_users
+
1
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
acl_users
+
1
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1281,7 +1276,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1281,7 +1276,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_users
=
len
(
gp
.
get_users_with_level
())
acl_users
=
len
(
gp
.
get_users_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'user3'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'user3'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_users
+
1
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
acl_users
+
1
,
len
(
gp
.
get_users_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1291,7 +1286,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1291,7 +1286,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_groups
=
len
(
gp
.
get_groups_with_level
())
acl_groups
=
len
(
gp
.
get_groups_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'group2'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'group2'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_groups
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
acl_groups
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1302,9 +1297,9 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1302,9 +1297,9 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_groups
=
len
(
gp
.
get_groups_with_level
())
acl_groups
=
len
(
gp
.
get_groups_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'group2'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'group2'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_groups
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
acl_groups
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
302
)
def
test_superuser_add_aclgroup_to_group
(
self
):
def
test_superuser_add_aclgroup_to_group
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -1313,7 +1308,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1313,7 +1308,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_groups
=
len
(
gp
.
get_groups_with_level
())
acl_groups
=
len
(
gp
.
get_groups_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'group2'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'group2'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_groups
+
1
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
acl_groups
+
1
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1324,7 +1319,7 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1324,7 +1319,7 @@ class GroupDetailTest(LoginMixin, TestCase):
acl_groups
=
len
(
gp
.
get_groups_with_level
())
acl_groups
=
len
(
gp
.
get_groups_with_level
())
response
=
c
.
post
(
'/dashboard/group/'
+
response
=
c
.
post
(
'/dashboard/group/'
+
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
str
(
self
.
g1
.
pk
)
+
'/acl/'
,
{
'
perm-new-name'
:
'group2'
,
'perm-new
'
:
'owner'
})
{
'
name'
:
'group2'
,
'level
'
:
'owner'
})
self
.
assertEqual
(
acl_groups
+
1
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
acl_groups
+
1
,
len
(
gp
.
get_groups_with_level
()))
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
...
@@ -1366,84 +1361,6 @@ class GroupDetailTest(LoginMixin, TestCase):
...
@@ -1366,84 +1361,6 @@ class GroupDetailTest(LoginMixin, TestCase):
self
.
assertEqual
(
user_in_group
-
1
,
self
.
g1
.
user_set
.
count
())
self
.
assertEqual
(
user_in_group
-
1
,
self
.
g1
.
user_set
.
count
())
self
.
assertEqual
(
response
.
status_code
,
302
)
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
)
def
test_unpermitted_user_add_wo_group_perm
(
self
):
def
test_unpermitted_user_add_wo_group_perm
(
self
):
user_count
=
self
.
g1
.
user_set
.
count
()
user_count
=
self
.
g1
.
user_set
.
count
()
c
=
Client
()
c
=
Client
()
...
@@ -1772,8 +1689,8 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1772,8 +1689,8 @@ class AclViewTest(LoginMixin, TestCase):
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertFalse
((
self
.
u1
,
"user"
)
in
inst
.
get_users_with_level
())
self
.
assertFalse
((
self
.
u1
,
"user"
)
in
inst
.
get_users_with_level
())
self
.
assertEqual
(
resp
.
status_code
,
302
)
self
.
assertEqual
(
resp
.
status_code
,
302
)
...
@@ -1786,11 +1703,11 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1786,11 +1703,11 @@ class AclViewTest(LoginMixin, TestCase):
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
inst
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
inst
.
get_users_with_level
())
self
.
assertEqual
(
resp
.
status_code
,
403
)
self
.
assertEqual
(
resp
.
status_code
,
302
)
def
test_instance_original_owner_access_revoke
(
self
):
def
test_instance_original_owner_access_revoke
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -1800,8 +1717,8 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1800,8 +1717,8 @@ class AclViewTest(LoginMixin, TestCase):
inst
.
set_level
(
self
.
ut
,
"owner"
)
inst
.
set_level
(
self
.
ut
,
"owner"
)
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/vm/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
ut
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
ut
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertEqual
(
self
.
ut
,
Instance
.
objects
.
get
(
id
=
1
)
.
owner
)
self
.
assertEqual
(
self
.
ut
,
Instance
.
objects
.
get
(
id
=
1
)
.
owner
)
self
.
assertTrue
((
self
.
ut
,
"owner"
)
in
inst
.
get_users_with_level
())
self
.
assertTrue
((
self
.
ut
,
"owner"
)
in
inst
.
get_users_with_level
())
...
@@ -1816,8 +1733,8 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1816,8 +1733,8 @@ class AclViewTest(LoginMixin, TestCase):
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertFalse
((
self
.
u1
,
"user"
)
in
tmpl
.
get_users_with_level
())
self
.
assertFalse
((
self
.
u1
,
"user"
)
in
tmpl
.
get_users_with_level
())
self
.
assertEqual
(
resp
.
status_code
,
302
)
self
.
assertEqual
(
resp
.
status_code
,
302
)
...
@@ -1830,11 +1747,11 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1830,11 +1747,11 @@ class AclViewTest(LoginMixin, TestCase):
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
tmpl
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
tmpl
.
get_users_with_level
())
self
.
assertEqual
(
resp
.
status_code
,
403
)
self
.
assertEqual
(
resp
.
status_code
,
302
)
def
test_template_original_owner_access_revoke
(
self
):
def
test_template_original_owner_access_revoke
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -1844,8 +1761,8 @@ class AclViewTest(LoginMixin, TestCase):
...
@@ -1844,8 +1761,8 @@ class AclViewTest(LoginMixin, TestCase):
tmpl
.
set_level
(
self
.
ut
,
"owner"
)
tmpl
.
set_level
(
self
.
ut
,
"owner"
)
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
resp
=
c
.
post
(
"/dashboard/template/1/acl/"
,
{
'remove-u-
%
d'
%
self
.
ut
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
ut
.
pk
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
})
})
self
.
assertEqual
(
self
.
ut
,
InstanceTemplate
.
objects
.
get
(
id
=
1
)
.
owner
)
self
.
assertEqual
(
self
.
ut
,
InstanceTemplate
.
objects
.
get
(
id
=
1
)
.
owner
)
self
.
assertTrue
((
self
.
ut
,
"owner"
)
in
tmpl
.
get_users_with_level
())
self
.
assertTrue
((
self
.
ut
,
"owner"
)
in
tmpl
.
get_users_with_level
())
...
...
circle/dashboard/urls.py
View file @
a170119d
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
from
__future__
import
absolute_import
from
__future__
import
absolute_import
from
django.conf.urls
import
patterns
,
url
,
include
from
django.conf.urls
import
patterns
,
url
,
include
import
autocomplete_light
from
vm.models
import
Instance
from
vm.models
import
Instance
from
.views
import
(
from
.views
import
(
AclUpdateView
,
FavouriteView
,
GroupAclUpdateView
,
GroupDelete
,
AclUpdateView
,
FavouriteView
,
GroupAclUpdateView
,
GroupDelete
,
...
@@ -30,7 +31,7 @@ from .views import (
...
@@ -30,7 +31,7 @@ from .views import (
TransferOwnershipView
,
vm_activity
,
VmCreate
,
VmDelete
,
VmDetailView
,
TransferOwnershipView
,
vm_activity
,
VmCreate
,
VmDelete
,
VmDetailView
,
VmDetailVncTokenView
,
VmGraphView
,
VmList
,
VmMassDelete
,
VmDetailVncTokenView
,
VmGraphView
,
VmList
,
VmMassDelete
,
DiskRemoveView
,
get_disk_download_status
,
InterfaceDeleteView
,
DiskRemoveView
,
get_disk_download_status
,
InterfaceDeleteView
,
GroupRemove
AclUserView
,
GroupRemoveAclGroupView
,
GroupRemove
UserView
,
GroupRemoveUserView
,
GroupRemoveFutureUserView
,
GroupRemoveFutureUserView
,
GroupCreate
,
GroupProfileUpdate
,
GroupCreate
,
GroupProfileUpdate
,
TemplateChoose
,
TemplateChoose
,
...
@@ -43,7 +44,10 @@ from .views import (
...
@@ -43,7 +44,10 @@ from .views import (
LeaseAclUpdateView
,
LeaseAclUpdateView
,
)
)
autocomplete_light
.
autodiscover
()
urlpatterns
=
patterns
(
urlpatterns
=
patterns
(
''
,
''
,
url
(
r'^$'
,
IndexView
.
as_view
(),
name
=
"dashboard.index"
),
url
(
r'^$'
,
IndexView
.
as_view
(),
name
=
"dashboard.index"
),
url
(
r'^lease/(?P<pk>\d+)/$'
,
LeaseDetail
.
as_view
(),
url
(
r'^lease/(?P<pk>\d+)/$'
,
LeaseDetail
.
as_view
(),
...
@@ -151,12 +155,6 @@ urlpatterns = patterns(
...
@@ -151,12 +155,6 @@ urlpatterns = patterns(
name
=
"dashboard.views.profile"
),
name
=
"dashboard.views.profile"
),
url
(
r'^profile/(?P<username>[^/]+)/use_gravatar/$'
,
toggle_use_gravatar
),
url
(
r'^profile/(?P<username>[^/]+)/use_gravatar/$'
,
toggle_use_gravatar
),
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+)/$'
,
url
(
r'^group/(?P<group_pk>\d+)/remove/user/(?P<member_pk>\d+)/$'
,
GroupRemoveUserView
.
as_view
(),
GroupRemoveUserView
.
as_view
(),
name
=
"dashboard.views.remove-user"
),
name
=
"dashboard.views.remove-user"
),
...
@@ -181,4 +179,5 @@ urlpatterns = patterns(
...
@@ -181,4 +179,5 @@ urlpatterns = patterns(
url
(
r'^sshkey/create/$'
,
url
(
r'^sshkey/create/$'
,
UserKeyCreate
.
as_view
(),
UserKeyCreate
.
as_view
(),
name
=
"dashboard.views.userkey-create"
),
name
=
"dashboard.views.userkey-create"
),
url
(
r'^autocomplete/'
,
include
(
'autocomplete_light.urls'
)),
)
)
circle/dashboard/views.py
View file @
a170119d
...
@@ -28,14 +28,13 @@ import requests
...
@@ -28,14 +28,13 @@ import requests
from
django.conf
import
settings
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.views
import
login
,
redirect_to_login
from
django.contrib.auth.views
import
login
,
redirect_to_login
from
django.contrib.messages
import
warning
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.core.exceptions
import
(
from
django.core.exceptions
import
(
PermissionDenied
,
SuspiciousOperation
,
PermissionDenied
,
SuspiciousOperation
,
)
)
from
django.core
import
signing
from
django.core
import
signing
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.db.models
import
Count
from
django.db.models
import
Count
,
Q
from
django.http
import
HttpResponse
,
HttpResponseRedirect
,
Http404
from
django.http
import
HttpResponse
,
HttpResponseRedirect
,
Http404
from
django.shortcuts
import
redirect
,
render
,
get_object_or_404
from
django.shortcuts
import
redirect
,
render
,
get_object_or_404
from
django.views.decorators.http
import
require_GET
,
require_POST
from
django.views.decorators.http
import
require_GET
,
require_POST
...
@@ -62,7 +61,7 @@ from .forms import (
...
@@ -62,7 +61,7 @@ from .forms import (
UserCreationForm
,
GroupProfileUpdateForm
,
UnsubscribeForm
,
UserCreationForm
,
GroupProfileUpdateForm
,
UnsubscribeForm
,
VmSaveForm
,
UserKeyForm
,
VmRenewForm
,
VmSaveForm
,
UserKeyForm
,
VmRenewForm
,
CirclePasswordChangeForm
,
VmCreateDiskForm
,
VmDownloadDiskForm
,
CirclePasswordChangeForm
,
VmCreateDiskForm
,
VmDownloadDiskForm
,
TraitsForm
,
RawDataForm
,
GroupPermissionForm
TraitsForm
,
RawDataForm
,
GroupPermissionForm
,
AclUserAddForm
)
)
from
.tables
import
(
from
.tables
import
(
...
@@ -219,27 +218,6 @@ class IndexView(LoginRequiredMixin, TemplateView):
...
@@ -219,27 +218,6 @@ class IndexView(LoginRequiredMixin, TemplateView):
return
context
return
context
def
get_vm_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
])}
def
get_group_acl_data
(
obj
):
aclobj
=
obj
.
profile
levels
=
aclobj
.
ACL_LEVELS
users
=
aclobj
.
get_users_with_level
()
users
=
[{
'user'
:
u
,
'level'
:
l
}
for
u
,
l
in
users
]
groups
=
aclobj
.
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.group-acl'
,
args
=
[
obj
.
pk
])}
class
CheckedDetailView
(
LoginRequiredMixin
,
DetailView
):
class
CheckedDetailView
(
LoginRequiredMixin
,
DetailView
):
read_level
=
'user'
read_level
=
'user'
...
@@ -303,7 +281,9 @@ class VmDetailView(CheckedDetailView):
...
@@ -303,7 +281,9 @@ class VmDetailView(CheckedDetailView):
pk__in
=
Interface
.
objects
.
filter
(
pk__in
=
Interface
.
objects
.
filter
(
instance
=
self
.
get_object
())
.
values_list
(
"vlan"
,
flat
=
True
)
instance
=
self
.
get_object
())
.
values_list
(
"vlan"
,
flat
=
True
)
)
.
all
()
)
.
all
()
context
[
'acl'
]
=
get_vm_acl_data
(
instance
)
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
instance
,
self
.
request
.
user
,
'dashboard.views.vm-acl'
)
context
[
'aclform'
]
=
AclUserAddForm
()
context
[
'os_type_icon'
]
=
instance
.
os_type
.
replace
(
"unknown"
,
context
[
'os_type_icon'
]
=
instance
.
os_type
.
replace
(
"unknown"
,
"question"
)
"question"
)
# ipv6 infos
# ipv6 infos
...
@@ -979,7 +959,10 @@ class GroupDetailView(CheckedDetailView):
...
@@ -979,7 +959,10 @@ class GroupDetailView(CheckedDetailView):
context
[
'users'
]
=
self
.
object
.
user_set
.
all
()
context
[
'users'
]
=
self
.
object
.
user_set
.
all
()
context
[
'future_users'
]
=
FutureMember
.
objects
.
filter
(
context
[
'future_users'
]
=
FutureMember
.
objects
.
filter
(
group
=
self
.
object
)
group
=
self
.
object
)
context
[
'acl'
]
=
get_group_acl_data
(
self
.
object
)
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
self
.
object
.
profile
,
self
.
request
.
user
,
'dashboard.views.group-acl'
)
context
[
'aclform'
]
=
AclUserAddForm
()
context
[
'group_profile_form'
]
=
GroupProfileUpdate
.
get_form_object
(
context
[
'group_profile_form'
]
=
GroupProfileUpdate
.
get_form_object
(
self
.
request
,
self
.
object
.
profile
)
self
.
request
,
self
.
object
.
profile
)
...
@@ -1022,7 +1005,7 @@ class GroupDetailView(CheckedDetailView):
...
@@ -1022,7 +1005,7 @@ class GroupDetailView(CheckedDetailView):
FutureMember
.
objects
.
get_or_create
(
org_id
=
name
,
FutureMember
.
objects
.
get_or_create
(
org_id
=
name
,
group
=
self
.
object
)
group
=
self
.
object
)
else
:
else
:
warning
(
request
,
_
(
'User "
%
s" not found.'
)
%
name
)
messages
.
warning
(
request
,
_
(
'User "
%
s" not found.'
)
%
name
)
def
__add_list
(
self
,
request
):
def
__add_list
(
self
,
request
):
if
not
self
.
get_has_level
()(
request
.
user
,
'operator'
):
if
not
self
.
get_has_level
()(
request
.
user
,
'operator'
):
...
@@ -1067,120 +1050,169 @@ class GroupPermissionsView(SuperuserRequiredMixin, UpdateView):
...
@@ -1067,120 +1050,169 @@ class GroupPermissionsView(SuperuserRequiredMixin, UpdateView):
class
AclUpdateView
(
LoginRequiredMixin
,
View
,
SingleObjectMixin
):
class
AclUpdateView
(
LoginRequiredMixin
,
View
,
SingleObjectMixin
):
def
send_success_message
(
self
,
whom
,
old_level
,
new_level
):
if
old_level
and
new_level
:
msg
=
_
(
"Acl user/group
%(w)
s successfully modified."
)
elif
not
old_level
and
new_level
:
msg
=
_
(
"Acl user/group
%(w)
s successfully added."
)
elif
old_level
and
not
new_level
:
msg
=
_
(
"Acl user/group
%(w)
s successfully removed."
)
if
msg
:
messages
.
success
(
self
.
request
,
msg
%
{
'w'
:
whom
})
def
get_level
(
self
,
whom
):
for
u
,
level
in
self
.
acl_data
:
if
u
==
whom
:
return
level
return
None
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
@classmethod
instance
=
self
.
get_object
()
def
get_acl_data
(
cls
,
obj
,
user
,
url
):
if
not
(
instance
.
has_level
(
request
.
user
,
"owner"
)
or
levels
=
obj
.
ACL_LEVELS
getattr
(
instance
,
'owner'
,
None
)
==
request
.
user
):
allowed_levels
=
list
(
l
for
l
in
OrderedDict
(
levels
)
logger
.
warning
(
'Tried to set permissions of
%
s by non-owner
%
s.'
,
if
cls
.
has_next_level
(
user
,
obj
,
l
))
unicode
(
instance
),
unicode
(
request
.
user
))
is_owner
=
'owner'
in
allowed_levels
raise
PermissionDenied
()
self
.
set_levels
(
request
,
instance
)
allowed_users
=
cls
.
get_allowed_users
(
user
)
self
.
remove_levels
(
request
,
instance
)
allowed_groups
=
cls
.
get_allowed_groups
(
user
)
self
.
add_levels
(
request
,
instance
)
return
redirect
(
"
%
s#access"
%
instance
.
get_absolute_url
())
user_levels
=
list
(
{
'user'
:
u
,
'level'
:
l
}
for
u
,
l
in
obj
.
get_users_with_level
()
def
set_levels
(
self
,
request
,
instance
):
if
is_owner
or
u
==
user
or
u
in
allowed_users
)
for
key
,
value
in
request
.
POST
.
items
():
m
=
re
.
match
(
'perm-([ug])-(
\
d+)'
,
key
)
group_levels
=
list
(
{
'group'
:
g
,
'level'
:
l
}
for
g
,
l
in
obj
.
get_groups_with_level
()
if
is_owner
or
g
in
allowed_groups
)
return
{
'users'
:
user_levels
,
'groups'
:
group_levels
,
'levels'
:
levels
,
'allowed_levels'
:
allowed_levels
,
'url'
:
reverse
(
url
,
args
=
[
obj
.
pk
])}
@classmethod
def
has_next_level
(
self
,
user
,
instance
,
level
):
levels
=
OrderedDict
(
instance
.
ACL_LEVELS
)
.
keys
()
next_levels
=
dict
(
zip
([
None
]
+
levels
,
levels
+
levels
[
-
1
:]))
# {None: 'user', 'user': 'operator', 'operator: 'owner',
# 'owner: 'owner'}
next_level
=
next_levels
[
level
]
return
instance
.
has_level
(
user
,
next_level
)
@classmethod
def
get_allowed_groups
(
cls
,
user
):
if
user
.
has_perm
(
'dashboard.use_autocomplete'
):
return
Group
.
objects
.
all
()
else
:
profiles
=
GroupProfile
.
get_objects_with_level
(
'owner'
,
user
)
return
Group
.
objects
.
filter
(
groupprofile__in
=
profiles
)
.
distinct
()
@classmethod
def
get_allowed_users
(
cls
,
user
):
if
user
.
has_perm
(
'dashboard.use_autocomplete'
):
return
User
.
objects
.
all
()
else
:
groups
=
cls
.
get_allowed_groups
(
user
)
return
User
.
objects
.
filter
(
Q
(
groups__in
=
groups
)
|
Q
(
pk
=
user
.
pk
))
.
distinct
()
def
check_auth
(
self
,
whom
,
old_level
,
new_level
):
if
isinstance
(
whom
,
Group
):
if
(
not
self
.
is_owner
and
whom
not
in
AclUpdateView
.
get_allowed_groups
(
self
.
request
.
user
)):
return
False
elif
isinstance
(
whom
,
User
):
if
(
not
self
.
is_owner
and
whom
not
in
AclUpdateView
.
get_allowed_users
(
self
.
request
.
user
)):
return
False
return
(
AclUpdateView
.
has_next_level
(
self
.
request
.
user
,
self
.
instance
,
new_level
)
and
AclUpdateView
.
has_next_level
(
self
.
request
.
user
,
self
.
instance
,
old_level
))
def
set_level
(
self
,
whom
,
new_level
):
user
=
self
.
request
.
user
old_level
=
self
.
get_level
(
whom
)
if
old_level
==
new_level
:
return
if
getattr
(
self
.
instance
,
"owner"
,
None
)
==
whom
:
logger
.
info
(
"Tried to set owner's acl level for
%
s by
%
s."
,
unicode
(
self
.
instance
),
unicode
(
user
))
msg
=
_
(
"The original owner cannot be removed, however "
"you can transfer ownership."
)
if
not
getattr
(
self
,
'hide_messages'
,
False
):
messages
.
warning
(
self
.
request
,
msg
)
elif
self
.
check_auth
(
whom
,
old_level
,
new_level
):
logger
.
info
(
u"Set
%
s's acl level for
%
s to
%
s by
%
s."
,
unicode
(
whom
),
unicode
(
self
.
instance
),
new_level
,
unicode
(
user
))
if
not
getattr
(
self
,
'hide_messages'
,
False
):
self
.
send_success_message
(
whom
,
old_level
,
new_level
)
self
.
instance
.
set_level
(
whom
,
new_level
)
else
:
logger
.
warning
(
u"Tried to set
%
s's acl_level for
%
s (
%
s->
%
s) by
%
s."
,
unicode
(
whom
),
unicode
(
self
.
instance
),
old_level
,
new_level
,
unicode
(
user
))
def
set_or_remove_levels
(
self
):
for
key
,
value
in
self
.
request
.
POST
.
items
():
m
=
re
.
match
(
'(perm|remove)-([ug])-(
\
d+)'
,
key
)
if
m
:
if
m
:
typ
,
id
=
m
.
groups
()
cmd
,
typ
,
id
=
m
.
groups
()
entity
=
{
'u'
:
User
,
'g'
:
Group
}[
typ
]
.
objects
.
get
(
id
=
id
)
if
cmd
==
'remove'
:
if
getattr
(
instance
,
"owner"
,
None
)
==
entity
:
value
=
None
logger
.
info
(
"Tried to set owner's acl level for
%
s by
%
s."
,
unicode
(
instance
),
unicode
(
request
.
user
))
continue
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
remove_levels
(
self
,
request
,
instance
):
for
key
,
value
in
request
.
POST
.
items
():
if
key
.
startswith
(
"remove"
):
typ
=
key
[
7
:
8
]
# len("remove-")
id
=
key
[
9
:]
# len("remove-x-")
entity
=
{
'u'
:
User
,
'g'
:
Group
}[
typ
]
.
objects
.
get
(
id
=
id
)
entity
=
{
'u'
:
User
,
'g'
:
Group
}[
typ
]
.
objects
.
get
(
id
=
id
)
if
getattr
(
instance
,
"owner"
,
None
)
==
entity
:
self
.
set_level
(
entity
,
value
)
logger
.
info
(
"Tried to remove owner from
%
s by
%
s."
,
unicode
(
instance
),
unicode
(
request
.
user
))
def
add_levels
(
self
):
msg
=
_
(
"The original owner cannot be removed, however "
name
=
self
.
request
.
POST
.
get
(
'name'
,
None
)
"you can transfer ownership."
)
level
=
self
.
request
.
POST
.
get
(
'level'
,
None
)
messages
.
warning
(
request
,
msg
)
if
not
name
or
not
level
:
continue
instance
.
set_level
(
entity
,
None
)
logger
.
info
(
"Revoked
%
s's access to
%
s by
%
s."
,
unicode
(
entity
),
unicode
(
instance
),
unicode
(
request
.
user
))
def
add_levels
(
self
,
request
,
instance
):
name
=
request
.
POST
[
'perm-new-name'
]
value
=
request
.
POST
[
'perm-new'
]
if
not
name
:
return
return
try
:
try
:
entity
=
search_user
(
name
)
entity
=
search_user
(
name
)
if
self
.
instance
.
object_level_set
.
filter
(
users__in
=
[
entity
]):
messages
.
warning
(
self
.
request
,
_
(
'User "
%
s" has already '
'access to this object.'
)
%
name
)
return
except
User
.
DoesNotExist
:
except
User
.
DoesNotExist
:
entity
=
None
entity
=
None
try
:
try
:
entity
=
Group
.
objects
.
get
(
name
=
name
)
entity
=
Group
.
objects
.
get
(
name
=
name
)
if
self
.
instance
.
object_level_set
.
filter
(
groups__in
=
[
entity
]):
messages
.
warning
(
self
.
request
,
_
(
'Group "
%
s" has already '
'access to this object.'
)
%
name
)
return
except
Group
.
DoesNotExist
:
except
Group
.
DoesNotExist
:
warning
(
request
,
_
(
'User or group "
%
s" not found.'
)
%
name
)
messages
.
warning
(
self
.
request
,
_
(
'User or group "
%
s" not found.'
)
%
name
)
return
return
self
.
set_level
(
entity
,
level
)
instance
.
set_level
(
entity
,
value
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
logger
.
info
(
"Set
%
s's new acl level for
%
s to
%
s by
%
s."
,
self
.
instance
=
self
.
get_object
()
unicode
(
entity
),
unicode
(
instance
),
self
.
is_owner
=
self
.
instance
.
has_level
(
request
.
user
,
'owner'
)
value
,
unicode
(
request
.
user
))
self
.
acl_data
=
(
self
.
instance
.
get_users_with_level
()
+
self
.
instance
.
get_groups_with_level
())
self
.
set_or_remove_levels
()
self
.
add_levels
()
return
redirect
(
"
%
s#access"
%
self
.
instance
.
get_absolute_url
())
class
TemplateAclUpdateView
(
AclUpdateView
):
class
TemplateAclUpdateView
(
AclUpdateView
):
model
=
InstanceTemplate
model
=
InstanceTemplate
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
template
=
self
.
get_object
()
if
not
(
template
.
has_level
(
request
.
user
,
"owner"
)
or
getattr
(
template
,
'owner'
,
None
)
==
request
.
user
):
logger
.
warning
(
'Tried to set permissions of
%
s by non-owner
%
s.'
,
unicode
(
template
),
unicode
(
request
.
user
))
raise
PermissionDenied
()
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
,
template
)
self
.
add_levels
(
request
,
template
)
self
.
remove_levels
(
request
,
template
)
post_for_disk
=
request
.
POST
.
copy
()
post_for_disk
[
'perm-new'
]
=
'user'
request
.
POST
=
post_for_disk
for
d
in
template
.
disks
.
all
():
self
.
set_levels
(
request
,
d
)
self
.
add_levels
(
request
,
d
)
self
.
remove_levels
(
request
,
d
)
return
redirect
(
template
)
class
GroupAclUpdateView
(
AclUpdateView
):
class
GroupAclUpdateView
(
AclUpdateView
):
model
=
Group
model
=
Group
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
def
get_object
(
self
):
instance
=
self
.
get_object
()
.
profile
return
super
(
GroupAclUpdateView
,
self
)
.
get_object
()
.
profile
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
(
reverse
(
"dashboard.views.group-detail"
,
kwargs
=
self
.
kwargs
))
class
TemplateChoose
(
LoginRequiredMixin
,
TemplateView
):
class
TemplateChoose
(
LoginRequiredMixin
,
TemplateView
):
...
@@ -1327,8 +1359,11 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
...
@@ -1327,8 +1359,11 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
obj
=
self
.
get_object
()
obj
=
self
.
get_object
()
context
=
super
(
TemplateDetail
,
self
)
.
get_context_data
(
**
kwargs
)
context
=
super
(
TemplateDetail
,
self
)
.
get_context_data
(
**
kwargs
)
context
[
'acl'
]
=
get_vm_acl_data
(
obj
)
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
obj
,
self
.
request
.
user
,
'dashboard.views.template-acl'
)
context
[
'disks'
]
=
obj
.
disks
.
all
()
context
[
'disks'
]
=
obj
.
disks
.
all
()
context
[
'is_owner'
]
=
obj
.
has_level
(
self
.
request
.
user
,
'owner'
)
context
[
'aclform'
]
=
AclUserAddForm
()
return
context
return
context
def
get_success_url
(
self
):
def
get_success_url
(
self
):
...
@@ -1627,34 +1662,6 @@ class GroupRemoveFutureUserView(GroupRemoveUserView):
...
@@ -1627,34 +1662,6 @@ class GroupRemoveFutureUserView(GroupRemoveUserView):
return
_
(
"Future user successfully removed from group."
)
return
_
(
"Future user successfully removed from group."
)
class
GroupRemoveAclUserView
(
GroupRemoveUserView
):
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
):
class
GroupDelete
(
CheckedDetailView
,
DeleteView
):
"""This stuff deletes the group.
"""This stuff deletes the group.
...
@@ -1781,13 +1788,12 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -1781,13 +1788,12 @@ class VmCreate(LoginRequiredMixin, TemplateView):
}
}
networks
=
[
InterfaceTemplate
(
vlan
=
l
,
managed
=
l
.
managed
)
networks
=
[
InterfaceTemplate
(
vlan
=
l
,
managed
=
l
.
managed
)
for
l
in
post
[
'networks'
]]
for
l
in
post
[
'networks'
]]
disks
=
post
[
'disks'
]
ikwargs
.
update
({
ikwargs
.
update
({
'template'
:
template
,
'template'
:
template
,
'owner'
:
user
,
'owner'
:
user
,
'networks'
:
networks
,
'networks'
:
networks
,
'disks'
:
disks
,
'disks'
:
list
(
template
.
disks
.
all
())
,
})
})
amount
=
post
[
'amount'
]
amount
=
post
[
'amount'
]
...
@@ -2319,7 +2325,8 @@ class LeaseDetail(LoginRequiredMixin, SuperuserRequiredMixin,
...
@@ -2319,7 +2325,8 @@ class LeaseDetail(LoginRequiredMixin, SuperuserRequiredMixin,
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
obj
=
self
.
get_object
()
obj
=
self
.
get_object
()
context
=
super
(
LeaseDetail
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
=
super
(
LeaseDetail
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
[
'acl'
]
=
get_vm_acl_data
(
obj
)
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
obj
,
self
.
request
.
user
,
'dashboard.views.lease-acl'
)
return
context
return
context
def
get_success_url
(
self
):
def
get_success_url
(
self
):
...
@@ -2792,12 +2799,11 @@ class DiskRemoveView(DeleteView):
...
@@ -2792,12 +2799,11 @@ class DiskRemoveView(DeleteView):
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
disk
=
self
.
get_object
()
disk
=
self
.
get_object
()
if
not
disk
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
disk
=
self
.
get_object
()
app
=
disk
.
get_appliance
()
app
=
disk
.
get_appliance
()
if
not
app
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
app
.
remove_disk
(
disk
=
disk
,
user
=
request
.
user
)
app
.
remove_disk
(
disk
=
disk
,
user
=
request
.
user
)
disk
.
destroy
()
disk
.
destroy
()
...
@@ -2818,7 +2824,7 @@ class DiskRemoveView(DeleteView):
...
@@ -2818,7 +2824,7 @@ class DiskRemoveView(DeleteView):
@require_GET
@require_GET
def
get_disk_download_status
(
request
,
pk
):
def
get_disk_download_status
(
request
,
pk
):
disk
=
Disk
.
objects
.
get
(
pk
=
pk
)
disk
=
Disk
.
objects
.
get
(
pk
=
pk
)
if
not
disk
.
has_level
(
request
.
user
,
'owner'
):
if
not
disk
.
get_appliance
()
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
return
HttpResponse
(
return
HttpResponse
(
...
...
circle/network/templates/network/vlan-edit.html
View file @
a170119d
...
@@ -23,61 +23,7 @@
...
@@ -23,61 +23,7 @@
<div
class=
"page-header"
>
<div
class=
"page-header"
>
<h3>
{% trans "Manage access" %}
</h3>
<h3>
{% trans "Manage access" %}
</h3>
</div>
</div>
<form
action=
"{% url "
network
.
vlan-acl
"
vid=
vlan_vid
%}"
method=
"post"
>
{% csrf_token %}
{% include "dashboard/_manage_access.html" with table_id="vlan-access-table" %}
<table
class=
"table table-striped table-with-form-fields"
id=
"vlan-access-table"
>
<thead>
<tr>
<th></th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "What" %}
</th>
<th><i
class=
"fa fa-times"
></i></th>
</tr></thead>
<tbody>
{% for i in acl.users %}
<tr>
<td><i
class=
"fa fa-user"
></i></td><td>
{{i.user}}
</td>
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
>
{% for id, name in acl.levels %}
<option
{%
if
id =
i.level%}
selected=
"selected"
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
<td>
<input
type=
"checkbox"
name=
"remove-u-{{i.user.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
{% for i in acl.groups %}
<tr>
<td><i
class=
"fa fa-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>
<input
type=
"checkbox"
name=
"remove-g-{{i.group.id}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</tr>
{% endfor %}
<tr><td><i
class=
"fa fa-plus"
></i></td>
<td><input
type=
"text"
class=
"form-control"
name=
"perm-new-name"
placeholder=
"{% trans "
Name
of
group
or
user
"
%}"
></td>
<td><select
class=
"form-control"
name=
"perm-new"
>
{% for id, name in acl.levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select></td><td></td>
</tr>
</tbody>
</table>
<div
class=
"form-actions"
>
<button
type=
"submit"
class=
"btn btn-success"
>
{% trans "Save" %}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
circle/network/tests/test_views.py
View file @
a170119d
...
@@ -63,9 +63,9 @@ class VlanAclTest(LoginMixin, TestCase):
...
@@ -63,9 +63,9 @@ class VlanAclTest(LoginMixin, TestCase):
vlan
=
Vlan
.
objects
.
get
(
vid
=
1
)
vlan
=
Vlan
.
objects
.
get
(
vid
=
1
)
self
.
assertEqual
([],
vlan
.
get_users_with_level
())
self
.
assertEqual
([],
vlan
.
get_users_with_level
())
resp
=
c
.
post
(
"/network/vlans/
1
/acl/"
,
{
resp
=
c
.
post
(
"/network/vlans/
2
/acl/"
,
{
'
perm-new-
name'
:
"user1"
,
'name'
:
"user1"
,
'
perm-new
'
:
"user"
,
'
level
'
:
"user"
,
})
})
vlan
=
Vlan
.
objects
.
get
(
vid
=
1
)
vlan
=
Vlan
.
objects
.
get
(
vid
=
1
)
...
@@ -80,10 +80,10 @@ class VlanAclTest(LoginMixin, TestCase):
...
@@ -80,10 +80,10 @@ class VlanAclTest(LoginMixin, TestCase):
vlan
.
set_level
(
self
.
u1
,
"user"
)
vlan
.
set_level
(
self
.
u1
,
"user"
)
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
vlan
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
vlan
.
get_users_with_level
())
resp
=
c
.
post
(
"/network/vlans/
1
/acl/"
,
{
resp
=
c
.
post
(
"/network/vlans/
2
/acl/"
,
{
'perm-u-
%
d'
%
self
.
u1
.
pk
:
"operator"
,
'perm-u-
%
d'
%
self
.
u1
.
pk
:
"operator"
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
})
})
self
.
assertTrue
((
self
.
u1
,
"operator"
)
in
vlan
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"operator"
)
in
vlan
.
get_users_with_level
())
...
@@ -97,10 +97,10 @@ class VlanAclTest(LoginMixin, TestCase):
...
@@ -97,10 +97,10 @@ class VlanAclTest(LoginMixin, TestCase):
vlan
.
set_level
(
self
.
u1
,
"user"
)
vlan
.
set_level
(
self
.
u1
,
"user"
)
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
vlan
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"user"
)
in
vlan
.
get_users_with_level
())
resp
=
c
.
post
(
"/network/vlans/
1
/acl/"
,
{
resp
=
c
.
post
(
"/network/vlans/
2
/acl/"
,
{
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'remove-u-
%
d'
%
self
.
u1
.
pk
:
""
,
'
perm-new
'
:
""
,
'
level
'
:
""
,
'
perm-new-
name'
:
""
,
'name'
:
""
,
})
})
self
.
assertTrue
((
self
.
u1
,
"user"
)
not
in
vlan
.
get_users_with_level
())
self
.
assertTrue
((
self
.
u1
,
"user"
)
not
in
vlan
.
get_users_with_level
())
...
...
circle/network/urls.py
View file @
a170119d
...
@@ -84,7 +84,7 @@ urlpatterns = patterns(
...
@@ -84,7 +84,7 @@ urlpatterns = patterns(
url
(
'^vlans/$'
,
VlanList
.
as_view
(),
name
=
'network.vlan_list'
),
url
(
'^vlans/$'
,
VlanList
.
as_view
(),
name
=
'network.vlan_list'
),
url
(
'^vlans/create$'
,
VlanCreate
.
as_view
(),
name
=
'network.vlan_create'
),
url
(
'^vlans/create$'
,
VlanCreate
.
as_view
(),
name
=
'network.vlan_create'
),
url
(
'^vlans/(?P<vid>
\
d+)/$'
,
VlanDetail
.
as_view
(),
name
=
'network.vlan'
),
url
(
'^vlans/(?P<vid>
\
d+)/$'
,
VlanDetail
.
as_view
(),
name
=
'network.vlan'
),
url
(
'^vlans/(?P<
vid
>
\
d+)/acl/$'
,
VlanAclUpdateView
.
as_view
(),
url
(
'^vlans/(?P<
pk
>
\
d+)/acl/$'
,
VlanAclUpdateView
.
as_view
(),
name
=
'network.vlan-acl'
),
name
=
'network.vlan-acl'
),
url
(
'^vlans/delete/(?P<vid>
\
d+)/$'
,
VlanDelete
.
as_view
(),
url
(
'^vlans/delete/(?P<vid>
\
d+)/$'
,
VlanDelete
.
as_view
(),
name
=
"network.vlan_delete"
),
name
=
"network.vlan_delete"
),
...
...
circle/network/views.py
View file @
a170119d
...
@@ -42,6 +42,7 @@ from operator import itemgetter
...
@@ -42,6 +42,7 @@ from operator import itemgetter
from
itertools
import
chain
from
itertools
import
chain
import
json
import
json
from
dashboard.views
import
AclUpdateView
from
dashboard.views
import
AclUpdateView
from
dashboard.forms
import
AclUserAddForm
class
SuccessMessageMixin
(
FormMixin
):
class
SuccessMessageMixin
(
FormMixin
):
...
@@ -629,19 +630,8 @@ class VlanList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
...
@@ -629,19 +630,8 @@ class VlanList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
table_pagination
=
False
table_pagination
=
False
def
get_vlan_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
}
class
VlanAclUpdateView
(
AclUpdateView
):
class
VlanAclUpdateView
(
AclUpdateView
):
model
=
Vlan
model
=
Vlan
slug_field
=
"vid"
slug_url_kwarg
=
"vid"
class
VlanDetail
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
class
VlanDetail
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
...
@@ -662,7 +652,9 @@ class VlanDetail(LoginRequiredMixin, SuperuserRequiredMixin,
...
@@ -662,7 +652,9 @@ class VlanDetail(LoginRequiredMixin, SuperuserRequiredMixin,
context
[
'host_list'
]
=
SmallHostTable
(
q
)
context
[
'host_list'
]
=
SmallHostTable
(
q
)
context
[
'vlan_vid'
]
=
self
.
kwargs
.
get
(
'vid'
)
context
[
'vlan_vid'
]
=
self
.
kwargs
.
get
(
'vid'
)
context
[
'acl'
]
=
get_vlan_acl_data
(
self
.
get_object
())
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
self
.
object
,
self
.
request
.
user
,
'network.vlan-acl'
)
context
[
'aclform'
]
=
AclUserAddForm
()
return
context
return
context
success_url
=
reverse_lazy
(
'network.vlan_list'
)
success_url
=
reverse_lazy
(
'network.vlan_list'
)
...
...
circle/storage/models.py
View file @
a170119d
...
@@ -31,7 +31,6 @@ from django.utils.translation import ugettext_lazy as _
...
@@ -31,7 +31,6 @@ from django.utils.translation import ugettext_lazy as _
from
model_utils.models
import
TimeStampedModel
from
model_utils.models
import
TimeStampedModel
from
sizefield.models
import
FileSizeField
from
sizefield.models
import
FileSizeField
from
acl.models
import
AclBase
from
.tasks
import
local_tasks
,
storage_tasks
from
.tasks
import
local_tasks
,
storage_tasks
from
celery.exceptions
import
TimeoutError
from
celery.exceptions
import
TimeoutError
from
common.models
import
WorkerNotFound
from
common.models
import
WorkerNotFound
...
@@ -76,15 +75,10 @@ class DataStore(Model):
...
@@ -76,15 +75,10 @@ class DataStore(Model):
destroyed__isnull
=
False
)
if
disk
.
is_deletable
]
destroyed__isnull
=
False
)
if
disk
.
is_deletable
]
class
Disk
(
AclBase
,
TimeStampedModel
):
class
Disk
(
TimeStampedModel
):
"""A virtual disk.
"""A virtual disk.
"""
"""
ACL_LEVELS
=
(
(
'user'
,
_
(
'user'
)),
# see all details
(
'operator'
,
_
(
'operator'
)),
(
'owner'
,
_
(
'owner'
)),
# superuser, can delete, delegate perms
)
TYPES
=
[(
'qcow2-norm'
,
'qcow2 normal'
),
(
'qcow2-snap'
,
'qcow2 snapshot'
),
TYPES
=
[(
'qcow2-norm'
,
'qcow2 normal'
),
(
'qcow2-snap'
,
'qcow2 snapshot'
),
(
'iso'
,
'iso'
),
(
'raw-ro'
,
'raw read-only'
),
(
'raw-rw'
,
'raw'
)]
(
'iso'
,
'iso'
),
(
'raw-ro'
,
'raw read-only'
),
(
'raw-rw'
,
'raw'
)]
name
=
CharField
(
blank
=
True
,
max_length
=
100
,
verbose_name
=
_
(
"name"
))
name
=
CharField
(
blank
=
True
,
max_length
=
100
,
verbose_name
=
_
(
"name"
))
...
@@ -225,15 +219,14 @@ class Disk(AclBase, TimeStampedModel):
...
@@ -225,15 +219,14 @@ class Disk(AclBase, TimeStampedModel):
return
any
(
i
.
state
!=
'STOPPED'
for
i
in
self
.
instance_set
.
all
())
return
any
(
i
.
state
!=
'STOPPED'
for
i
in
self
.
instance_set
.
all
())
def
get_appliance
(
self
):
def
get_appliance
(
self
):
"""Return an Instance or InstanceTemplate object where the disk is used
"""Return the Instance or InstanceTemplate object where the disk
is used
"""
"""
instance
=
self
.
instance_set
.
all
()
from
vm.models
import
Instance
template
=
self
.
template_set
.
all
()
try
:
app
=
list
(
instance
)
+
list
(
template
)
return
self
.
instance_set
.
get
()
if
len
(
app
)
>
0
:
except
Instance
.
DoesNotExist
:
return
app
[
0
]
return
self
.
template_set
.
get
()
else
:
return
None
def
get_exclusive
(
self
):
def
get_exclusive
(
self
):
"""Get an instance of the disk for exclusive usage.
"""Get an instance of the disk for exclusive usage.
...
...
circle/vm/models/instance.py
View file @
a170119d
...
@@ -405,13 +405,6 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
...
@@ -405,13 +405,6 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
"""
"""
disks
=
template
.
disks
.
all
()
if
disks
is
None
else
disks
disks
=
template
.
disks
.
all
()
if
disks
is
None
else
disks
for
disk
in
disks
:
if
not
disk
.
has_level
(
owner
,
'user'
):
raise
PermissionDenied
()
elif
(
disk
.
type
==
'qcow2-snap'
and
not
disk
.
has_level
(
owner
,
'owner'
)):
raise
PermissionDenied
()
networks
=
(
template
.
interface_set
.
all
()
if
networks
is
None
networks
=
(
template
.
interface_set
.
all
()
if
networks
is
None
else
networks
)
else
networks
)
...
...
requirements/base.txt
View file @
a170119d
...
@@ -4,6 +4,7 @@ billiard==3.3.0.17
...
@@ -4,6 +4,7 @@ billiard==3.3.0.17
bpython==0.12
bpython==0.12
celery==3.1.11
celery==3.1.11
Django==1.6.3
Django==1.6.3
django-autocomplete-light==1.4.14
django-braces==1.4.0
django-braces==1.4.0
django-celery==3.1.10
django-celery==3.1.10
django-crispy-forms==1.4.0
django-crispy-forms==1.4.0
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment