Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Fukász Rómeó Ervin
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
f6687581
authored
Mar 02, 2014
by
Őry Máté
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of git.cloud.ik.bme.hu:circle/cloud
parents
741f4e4a
031f3fcc
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
137 additions
and
44 deletions
+137
-44
circle/dashboard/templates/dashboard/_notifications-timeline.html
+1
-1
circle/dashboard/templates/dashboard/notifications/ownership-accepted.html
+4
-0
circle/dashboard/templates/dashboard/notifications/ownership-offer.html
+5
-0
circle/dashboard/templates/dashboard/vm-detail/access.html
+10
-1
circle/dashboard/templates/dashboard/vm-detail/tx-owner.html
+1
-0
circle/dashboard/tests/test_views.py
+78
-12
circle/dashboard/urls.py
+1
-1
circle/dashboard/views.py
+37
-29
No files found.
circle/dashboard/templates/dashboard/_notifications-timeline.html
View file @
f6687581
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
</span>
</span>
<div
style=
"clear: both;"
></div>
<div
style=
"clear: both;"
></div>
<div
class=
"notification-message-text"
>
<div
class=
"notification-message-text"
>
{{ n.message }}
{{ n.message
|safe
}}
</div>
</div>
</li>
</li>
{% empty %}
{% empty %}
...
...
circle/dashboard/templates/dashboard/notifications/ownership-accepted.html
0 → 100644
View file @
f6687581
{%load i18n%}
{%blocktrans with instance=instance.name user=user.name%}
Your ownership offer of {{instance}} has been accepted by {{user}}.
{%endblocktrans%}
circle/dashboard/templates/dashboard/notifications/ownership-offer.html
0 → 100644
View file @
f6687581
{%load i18n%}
{%blocktrans with instance=instance.name user=user.name%}
{{user}} offered you to take the ownership of his/her virtual machine
called {{instance}}.{%endblocktrans%}
<a
href=
"{{token}}"
class=
"btn btn-success btn-small"
>
{%trans "Accept"%}
</a>
circle/dashboard/templates/dashboard/vm-detail/access.html
View file @
f6687581
{% load i18n %}
{% load i18n %}
<h3>
{% trans "Owner" %}
</h3>
<h3>
{% trans "Owner" %}
</h3>
<p>
<p>
{% if user == instance.owner %}
{% blocktrans %}You are the current owner of this instance.{% endblocktrans %}
{% blocktrans %}You are the current owner of this instance.{% endblocktrans %}
<a
href=
"#"
class=
"btn btn-link"
>
{% trans "Transfer ownership..." %}
</a>
{% else %}
{% blocktrans with owner=instance.owner %}
The current owner of this instance is {{owner}}.
{% endblocktrans %}
{% endif %}
{% if user == instance.owner or user.is_superuser %}
<a
href=
"{% url "
dashboard
.
views
.
vm-transfer-ownership
"
instance
.
pk
%}"
class=
"btn btn-link"
>
{% trans "Transfer ownership..." %}
</a>
{% endif %}
</p>
</p>
<h3>
{% trans "Permissions"|capfirst %}
</h3>
<h3>
{% trans "Permissions"|capfirst %}
</h3>
<form
action=
"{{acl.url}}"
method=
"post"
>
{% csrf_token %}
<form
action=
"{{acl.url}}"
method=
"post"
>
{% csrf_token %}
...
...
circle/dashboard/templates/dashboard/vm-detail/tx-owner.html
View file @
f6687581
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
<div
class=
"pull-right"
>
<div
class=
"pull-right"
>
<form
action=
""
method=
"POST"
>
<form
action=
""
method=
"POST"
>
{% csrf_token %}
{% csrf_token %}
E-mail address or identifier of user:
<input
name=
"name"
>
<input
name=
"name"
>
<input
type=
"submit"
>
<input
type=
"submit"
>
</form>
</form>
...
...
circle/dashboard/tests/test_views.py
View file @
f6687581
from
django.test
import
TestCase
from
django.test
import
TestCase
from
django.test.client
import
Client
from
django.test.client
import
Client
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
django.core.exceptions
import
SuspiciousOperation
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
from
..models
import
Profile
from
storage.models
import
Disk
from
storage.models
import
Disk
from
firewall.models
import
Vlan
from
firewall.models
import
Vlan
class
VmDetailTest
(
TestCase
):
class
LoginMixin
(
object
):
def
login
(
self
,
client
,
username
,
password
=
'password'
):
response
=
client
.
post
(
'/accounts/login/'
,
{
'username'
:
username
,
'password'
:
password
})
self
.
assertNotEqual
(
response
.
status_code
,
403
)
class
VmDetailTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
]
fixtures
=
[
'test-vm-fixture.json'
]
def
setUp
(
self
):
def
setUp
(
self
):
...
@@ -32,11 +41,6 @@ class VmDetailTest(TestCase):
...
@@ -32,11 +41,6 @@ class VmDetailTest(TestCase):
self
.
us
.
delete
()
self
.
us
.
delete
()
self
.
g1
.
delete
()
self
.
g1
.
delete
()
def
login
(
self
,
client
,
username
,
password
=
'password'
):
response
=
client
.
post
(
'/accounts/login/'
,
{
'username'
:
username
,
'password'
:
password
})
self
.
assertNotEqual
(
response
.
status_code
,
403
)
def
test_404_vm_page
(
self
):
def
test_404_vm_page
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
...
@@ -236,7 +240,7 @@ class VmDetailTest(TestCase):
...
@@ -236,7 +240,7 @@ class VmDetailTest(TestCase):
assert
self
.
u1
.
notification_set
.
get
()
.
status
==
'read'
assert
self
.
u1
.
notification_set
.
get
()
.
status
==
'read'
class
VmDetailVncTest
(
TestCase
):
class
VmDetailVncTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
def
setUp
(
self
):
def
setUp
(
self
):
...
@@ -244,11 +248,6 @@ class VmDetailVncTest(TestCase):
...
@@ -244,11 +248,6 @@ class VmDetailVncTest(TestCase):
self
.
u1
.
set_password
(
'password'
)
self
.
u1
.
set_password
(
'password'
)
self
.
u1
.
save
()
self
.
u1
.
save
()
def
login
(
self
,
client
,
username
,
password
=
'password'
):
response
=
client
.
post
(
'/accounts/login/'
,
{
'username'
:
username
,
'password'
:
password
})
self
.
assertNotEqual
(
response
.
status_code
,
403
)
def
test_permitted_vm_console
(
self
):
def
test_permitted_vm_console
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
...
@@ -268,3 +267,70 @@ class VmDetailVncTest(TestCase):
...
@@ -268,3 +267,70 @@ class VmDetailVncTest(TestCase):
inst
.
set_level
(
self
.
u1
,
'user'
)
inst
.
set_level
(
self
.
u1
,
'user'
)
response
=
c
.
get
(
'/dashboard/vm/1/vnctoken/'
)
response
=
c
.
get
(
'/dashboard/vm/1/vnctoken/'
)
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
403
)
class
TransferOwnershipViewTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
]
def
setUp
(
self
):
self
.
u1
=
User
.
objects
.
create
(
username
=
'user1'
)
self
.
u1
.
set_password
(
'password'
)
self
.
u1
.
save
()
Profile
.
objects
.
create
(
user
=
self
.
u1
)
self
.
u2
=
User
.
objects
.
create
(
username
=
'user2'
,
is_staff
=
True
)
self
.
u2
.
set_password
(
'password'
)
self
.
u2
.
save
()
Profile
.
objects
.
create
(
user
=
self
.
u2
)
self
.
us
=
User
.
objects
.
create
(
username
=
'superuser'
,
is_superuser
=
True
)
self
.
us
.
set_password
(
'password'
)
self
.
us
.
save
()
Profile
.
objects
.
create
(
user
=
self
.
us
)
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
.
owner
=
self
.
u1
inst
.
save
()
def
test_non_owner_offer
(
self
):
c2
=
self
.
u2
.
notification_set
.
count
()
c
=
Client
()
self
.
login
(
c
,
'user2'
)
with
self
.
assertRaises
(
SuspiciousOperation
):
c
.
post
(
'/dashboard/vm/1/tx/'
)
self
.
assertEqual
(
self
.
u2
.
notification_set
.
count
(),
c2
)
def
test_owned_offer
(
self
):
c2
=
self
.
u2
.
notification_set
.
count
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
response
=
c
.
get
(
'/dashboard/vm/1/tx/'
)
assert
response
.
status_code
==
200
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
self
.
assertEqual
(
self
.
u2
.
notification_set
.
count
(),
c2
+
1
)
def
test_transfer
(
self
):
c
=
Client
()
self
.
login
(
c
,
'user1'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
c
=
Client
()
self
.
login
(
c
,
'user2'
)
response
=
c
.
post
(
url
)
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u2
.
pk
)
def
test_transfer_token_used_by_others
(
self
):
c
=
Client
()
self
.
login
(
c
,
'user1'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
response
=
c
.
post
(
url
)
# token is for user2
assert
response
.
status_code
==
403
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u1
.
pk
)
def
test_transfer_by_superuser
(
self
):
c
=
Client
()
self
.
login
(
c
,
'superuser'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
c
=
Client
()
self
.
login
(
c
,
'user2'
)
response
=
c
.
post
(
url
)
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u2
.
pk
)
circle/dashboard/urls.py
View file @
f6687581
...
@@ -57,7 +57,7 @@ urlpatterns = patterns(
...
@@ -57,7 +57,7 @@ urlpatterns = patterns(
url
(
r'^node/list/$'
,
NodeList
.
as_view
(),
name
=
'dashboard.views.node-list'
),
url
(
r'^node/list/$'
,
NodeList
.
as_view
(),
name
=
'dashboard.views.node-list'
),
url
(
r'^node/(?P<pk>\d+)/$'
,
NodeDetailView
.
as_view
(),
url
(
r'^node/(?P<pk>\d+)/$'
,
NodeDetailView
.
as_view
(),
name
=
'dashboard.views.node-detail'
),
name
=
'dashboard.views.node-detail'
),
url
(
r'^tx/$'
,
TransferOwnershipConfirmView
.
as_view
(),
url
(
r'^tx/
(?P<key>.*)/?
$'
,
TransferOwnershipConfirmView
.
as_view
(),
name
=
'dashboard.views.vm-transfer-ownership-confirm'
),
name
=
'dashboard.views.vm-transfer-ownership-confirm'
),
url
(
r'^node/delete/(?P<pk>\d+)/$'
,
NodeDelete
.
as_view
(),
url
(
r'^node/delete/(?P<pk>\d+)/$'
,
NodeDelete
.
as_view
(),
name
=
"dashboard.views.delete-node"
),
name
=
"dashboard.views.delete-node"
),
...
...
circle/dashboard/views.py
View file @
f6687581
...
@@ -37,7 +37,7 @@ from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
...
@@ -37,7 +37,7 @@ from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
InstanceActivity
,
Node
,
instance_activity
,
Lease
,
InstanceActivity
,
Node
,
instance_activity
,
Lease
,
Interface
,
NodeActivity
)
Interface
,
NodeActivity
)
from
firewall.models
import
Vlan
,
Host
,
Rule
from
firewall.models
import
Vlan
,
Host
,
Rule
from
dashboard.models
import
Favourite
from
dashboard.models
import
Favourite
,
Profile
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -1490,7 +1490,12 @@ class TransferOwnershipView(LoginRequiredMixin, DetailView):
...
@@ -1490,7 +1490,12 @@ class TransferOwnershipView(LoginRequiredMixin, DetailView):
try
:
try
:
new_owner
=
User
.
objects
.
get
(
username
=
request
.
POST
[
'name'
])
new_owner
=
User
.
objects
.
get
(
username
=
request
.
POST
[
'name'
])
except
User
.
DoesNotExist
:
except
User
.
DoesNotExist
:
raise
Http404
()
new_owner
=
User
.
objects
.
get
(
email
=
request
.
POST
[
'name'
])
except
User
.
DoesNotExist
:
new_owner
=
User
.
objects
.
get
(
profile__org_id
=
request
.
POST
[
'name'
])
except
User
.
DoesNotExist
:
messages
.
error
(
request
,
_
(
'Can not find specified user.'
))
return
self
.
get
(
request
,
*
args
,
**
kwargs
)
except
KeyError
:
except
KeyError
:
raise
SuspiciousOperation
()
raise
SuspiciousOperation
()
...
@@ -1501,29 +1506,41 @@ class TransferOwnershipView(LoginRequiredMixin, DetailView):
...
@@ -1501,29 +1506,41 @@ class TransferOwnershipView(LoginRequiredMixin, DetailView):
token
=
signing
.
dumps
((
obj
.
pk
,
new_owner
.
pk
),
token
=
signing
.
dumps
((
obj
.
pk
,
new_owner
.
pk
),
salt
=
TransferOwnershipConfirmView
.
get_salt
())
salt
=
TransferOwnershipConfirmView
.
get_salt
())
return
HttpResponse
(
"
%
s?key=
%
s"
%
(
token_path
=
reverse
(
reverse
(
'dashboard.views.vm-transfer-ownership-confirm'
),
token
),
'dashboard.views.vm-transfer-ownership-confirm'
,
args
=
[
token
])
content_type
=
"text/plain"
)
try
:
new_owner
.
profile
.
notify
(
_
(
'Ownership offer'
),
'dashboard/notifications/ownership-offer.html'
,
{
'instance'
:
obj
,
'token'
:
token_path
})
except
Profile
.
DoesNotExist
:
messages
.
error
(
request
,
_
(
'Can not notify selected user.'
))
else
:
messages
.
success
(
request
,
_
(
'User
%
s is notified about the offer.'
)
%
(
unicode
(
new_owner
),
))
return
redirect
(
reverse_lazy
(
"dashboard.views.detail"
,
kwargs
=
{
'pk'
:
obj
.
pk
}))
class
TransferOwnershipConfirmView
(
LoginRequiredMixin
,
View
):
class
TransferOwnershipConfirmView
(
LoginRequiredMixin
,
View
):
"""User can accept an ownership offer."""
max_age
=
3
*
24
*
3600
max_age
=
3
*
24
*
3600
success_message
=
_
(
"Ownership successfully transferred."
)
success_message
=
_
(
"Ownership successfully transferred
to you
."
)
@classmethod
@classmethod
def
get_salt
(
cls
):
def
get_salt
(
cls
):
return
unicode
(
cls
)
return
unicode
(
cls
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
key
,
*
args
,
**
kwargs
):
"""Confirm ownership transfer based on token.
"""Confirm ownership transfer based on token.
"""
"""
logger
.
debug
(
'Confirm dialog for token
%
s.'
,
key
)
try
:
try
:
key
=
request
.
GET
[
'key'
]
logger
.
debug
(
'Confirm dialog for token
%
s.'
,
key
)
instance
,
new_owner
=
self
.
get_instance
(
key
,
request
.
user
)
instance
,
new_owner
=
self
.
get_instance
(
key
,
request
.
user
)
except
KeyError
:
except
PermissionDenied
:
raise
Http404
()
except
PermissionDenied
():
messages
.
error
(
request
,
_
(
'This token is for an other user.'
))
messages
.
error
(
request
,
_
(
'This token is for an other user.'
))
raise
raise
except
SuspiciousOperation
:
except
SuspiciousOperation
:
...
@@ -1533,16 +1550,10 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
...
@@ -1533,16 +1550,10 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
"dashboard/confirm/base-transfer-ownership.html"
,
"dashboard/confirm/base-transfer-ownership.html"
,
dictionary
=
{
'instance'
:
instance
,
'key'
:
key
})
dictionary
=
{
'instance'
:
instance
,
'key'
:
key
})
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
def
post
(
self
,
request
,
key
,
*
args
,
**
kwargs
):
"""Really transfer ownership based on token.
"""Really transfer ownership based on token.
"""
"""
try
:
instance
,
owner
=
self
.
get_instance
(
key
,
request
.
user
)
key
=
request
.
POST
[
'key'
]
instance
,
owner
=
self
.
get_instance
(
key
,
request
.
user
)
except
KeyError
:
logger
.
debug
(
'Posted to
%
s without key field.'
,
unicode
(
self
.
__class__
))
raise
SuspiciousOperation
()
old
=
instance
.
owner
old
=
instance
.
owner
with
instance_activity
(
code_suffix
=
'ownership-transferred'
,
with
instance_activity
(
code_suffix
=
'ownership-transferred'
,
...
@@ -1553,6 +1564,11 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
...
@@ -1553,6 +1564,11 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
messages
.
success
(
request
,
self
.
success_message
)
messages
.
success
(
request
,
self
.
success_message
)
logger
.
info
(
'Ownership of
%
s transferred from
%
s to
%
s.'
,
logger
.
info
(
'Ownership of
%
s transferred from
%
s to
%
s.'
,
unicode
(
instance
),
unicode
(
old
),
unicode
(
request
.
user
))
unicode
(
instance
),
unicode
(
old
),
unicode
(
request
.
user
))
if
old
.
profile
:
old
.
profile
.
notify
(
_
(
'Ownership accepted'
),
'dashboard/notifications/ownership-accepted.html'
,
{
'instance'
:
instance
})
return
HttpResponseRedirect
(
instance
.
get_absolute_url
())
return
HttpResponseRedirect
(
instance
.
get_absolute_url
())
def
get_instance
(
self
,
key
,
user
):
def
get_instance
(
self
,
key
,
user
):
...
@@ -1562,15 +1578,7 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
...
@@ -1562,15 +1578,7 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
instance
,
new_owner
=
(
instance
,
new_owner
=
(
signing
.
loads
(
key
,
max_age
=
self
.
max_age
,
signing
.
loads
(
key
,
max_age
=
self
.
max_age
,
salt
=
self
.
get_salt
()))
salt
=
self
.
get_salt
()))
except
signing
.
BadSignature
as
e
:
except
(
signing
.
BadSignature
,
ValueError
,
TypeError
)
as
e
:
logger
.
error
(
'Tried invalid token. Token:
%
s, user:
%
s.
%
s'
,
key
,
unicode
(
user
),
unicode
(
e
))
raise
SuspiciousOperation
()
except
ValueError
as
e
:
logger
.
error
(
'Tried invalid token. Token:
%
s, user:
%
s.
%
s'
,
key
,
unicode
(
user
),
unicode
(
e
))
raise
SuspiciousOperation
()
except
TypeError
as
e
:
logger
.
error
(
'Tried invalid token. Token:
%
s, user:
%
s.
%
s'
,
logger
.
error
(
'Tried invalid token. Token:
%
s, user:
%
s.
%
s'
,
key
,
unicode
(
user
),
unicode
(
e
))
key
,
unicode
(
user
),
unicode
(
e
))
raise
SuspiciousOperation
()
raise
SuspiciousOperation
()
...
...
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