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
1e514d5b
authored
Feb 06, 2015
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-useradmin' into 'master'
Useradmin
✅
Closes
#372
See merge request
!286
parents
8c7786a6
ca4fcef5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
374 additions
and
69 deletions
+374
-69
circle/dashboard/forms.py
+49
-2
circle/dashboard/static/dashboard/dashboard.js
+0
-0
circle/dashboard/static/dashboard/dashboard.less
+23
-1
circle/dashboard/tables.py
+25
-18
circle/dashboard/templates/dashboard/group-detail.html
+1
-1
circle/dashboard/templates/dashboard/index-nodes.html
+1
-1
circle/dashboard/templates/dashboard/index-templates.html
+19
-7
circle/dashboard/templates/dashboard/index-users.html
+53
-0
circle/dashboard/templates/dashboard/index.html
+6
-0
circle/dashboard/templates/dashboard/profile.html
+19
-2
circle/dashboard/templates/dashboard/user-create.html
+1
-2
circle/dashboard/templates/dashboard/user-list.html
+45
-0
circle/dashboard/tests/test_views.py
+9
-6
circle/dashboard/urls.py
+6
-3
circle/dashboard/views/index.py
+9
-1
circle/dashboard/views/template.py
+13
-1
circle/dashboard/views/user.py
+94
-24
circle/dashboard/views/vm.py
+1
-0
circle/locale/hu/LC_MESSAGES/django.po
+0
-0
No files found.
circle/dashboard/forms.py
View file @
1e514d5b
...
...
@@ -59,7 +59,7 @@ from django.utils.translation import string_concat
from
.validators
import
domain_validator
from
dashboard.models
import
ConnectCommand
from
dashboard.models
import
ConnectCommand
,
create_profile
LANGUAGES_WITH_CODE
=
((
l
[
0
],
string_concat
(
l
[
1
],
" ("
,
l
[
0
],
")"
))
for
l
in
LANGUAGES
)
...
...
@@ -1257,10 +1257,19 @@ class CirclePasswordChangeForm(PasswordChangeForm):
class
UserCreationForm
(
OrgUserCreationForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
)
group
=
kwargs
.
pop
(
'default'
)
super
(
UserCreationForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
'groups'
]
=
forms
.
ModelMultipleChoiceField
(
queryset
=
choices
,
initial
=
[
group
],
required
=
False
,
label
=
_
(
'Groups'
))
class
Meta
:
model
=
User
fields
=
(
"username"
,
'email'
,
'first_name'
,
'last_name'
)
fields
=
(
"username"
,
'email'
,
'first_name'
,
'last_name'
,
'groups'
)
@property
def
helper
(
self
):
...
...
@@ -1275,8 +1284,39 @@ class UserCreationForm(OrgUserCreationForm):
user
.
set_password
(
self
.
cleaned_data
[
"password1"
])
if
commit
:
user
.
save
()
create_profile
(
user
)
user
.
groups
.
add
(
*
self
.
cleaned_data
[
"groups"
])
return
user
class
UserEditForm
(
forms
.
ModelForm
):
instance_limit
=
forms
.
IntegerField
(
label
=
_
(
'Instance limit'
),
min_value
=
0
,
widget
=
NumberInput
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
UserEditForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
"instance_limit"
]
.
initial
=
(
self
.
instance
.
profile
.
instance_limit
)
class
Meta
:
model
=
User
fields
=
(
'email'
,
'first_name'
,
'last_name'
,
'instance_limit'
,
'is_active'
)
def
save
(
self
,
commit
=
True
):
user
=
super
(
UserEditForm
,
self
)
.
save
()
user
.
profile
.
instance_limit
=
(
self
.
cleaned_data
[
'instance_limit'
]
or
None
)
user
.
profile
.
save
()
return
user
@property
def
helper
(
self
):
helper
=
FormHelper
()
helper
.
add_input
(
Submit
(
"submit"
,
_
(
"Save"
)))
return
helper
class
AclUserOrGroupAddForm
(
forms
.
Form
):
name
=
forms
.
CharField
(
widget
=
autocomplete_light
.
TextWidget
(
...
...
@@ -1497,3 +1537,10 @@ class TemplateListSearchForm(forms.Form):
data
=
self
.
data
.
copy
()
data
[
'stype'
]
=
"owned"
self
.
data
=
data
class
UserListSearchForm
(
forms
.
Form
):
s
=
forms
.
CharField
(
widget
=
forms
.
TextInput
(
attrs
=
{
'class'
:
"form-control input-tags"
,
'placeholder'
:
_
(
"Search..."
)
}))
circle/dashboard/static/dashboard/dashboard.js
View file @
1e514d5b
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/dashboard.less
View file @
1e514d5b
...
...
@@ -562,7 +562,7 @@ footer a, footer a:hover, footer a:visited {
}
#dashboard-vm-list, #dashboard-node-list, #dashboard-group-list,
#dashboard-template-list, #dashboard-files-toplist {
#dashboard-template-list, #dashboard-files-toplist
, #dashboard-user-list
{
min-height: 200px;
}
...
...
@@ -1168,6 +1168,28 @@ textarea[name="new_members"] {
}
}
#dashboard-user-list {
.list-group-item {
display: flex;
}
.index-user-list-name, .index-user-list-org {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.index-user-list-name {
max-width: 80%;
}
.index-user-list-org {
padding-left: 5px;
flex: 1;
}
}
.fa-fw-12 {
/* fa-fw is too wide */
width: 12px;
...
...
circle/dashboard/tables.py
View file @
1e514d5b
...
...
@@ -18,13 +18,16 @@
from
__future__
import
absolute_import
from
django.contrib.auth.models
import
Group
,
User
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.html
import
mark_safe
from
django_tables2
import
Table
,
A
from
django_tables2.columns
import
(
TemplateColumn
,
Column
,
LinkColumn
,
BooleanColumn
)
from
django_tables2.columns
import
(
TemplateColumn
,
Column
,
LinkColumn
,
BooleanColumn
)
from
django_sshkey.models
import
UserKey
from
vm.models
import
Node
,
InstanceTemplate
,
Lease
from
django.utils.translation
import
ugettext_lazy
as
_
from
django_sshkey.models
import
UserKey
from
dashboard.models
import
ConnectCommand
...
...
@@ -123,26 +126,30 @@ class GroupListTable(Table):
class
UserListTable
(
Table
):
pk
=
TemplateColumn
(
template_name
=
'dashboard/vm-list/column-id.html'
,
verbose_name
=
"ID"
,
attrs
=
{
'th'
:
{
'class'
:
'vm-list-table-thin'
}},
username
=
LinkColumn
(
'dashboard.views.profile'
,
args
=
[
A
(
'username'
)],
)
username
=
TemplateColumn
(
template_name
=
"dashboard/group-list/column-username.html"
profile__org_id
=
LinkColumn
(
'dashboard.views.profile'
,
accessor
=
'profile.org_id'
,
args
=
[
A
(
'username'
)],
verbose_name
=
_
(
'Organization ID'
)
)
class
Meta
:
model
=
User
attrs
=
{
'class'
:
(
'table table-bordered table-striped table-hover '
'vm-list-table'
)}
fields
=
(
'pk'
,
'username'
,
)
is_superuser
=
BooleanColumn
(
verbose_name
=
mark_safe
(
_
(
'<abbr data-placement="left" title="Superuser status">SU</abbr>'
)
)
)
is_active
=
BooleanColumn
()
class
UserListTablex
(
Table
):
class
Meta
:
model
=
User
template
=
"django_tables2/table_no_page.html"
attrs
=
{
'class'
:
(
'table table-bordered table-striped table-hover'
)}
fields
=
(
'username'
,
'last_name'
,
'first_name'
,
'profile__org_id'
,
'email'
,
'is_active'
,
'is_superuser'
)
class
TemplateListTable
(
Table
):
...
...
circle/dashboard/templates/dashboard/group-detail.html
View file @
1e514d5b
...
...
@@ -78,7 +78,7 @@
<h3>
{% trans "User list" %}
{% if perms.auth.add_user %}
<a
href=
"{% url "
dashboard
.
views
.
create-user
"
group
.
pk
%
}"
class=
"btn btn-success pull-right"
>
<a
href=
"{% url "
dashboard
.
views
.
user-create
"
%}?
group_pk=
{{
group
.
pk
}
}"
class=
"btn btn-success pull-right"
>
{% trans "Create user" %}
</a>
{% endif %}
...
...
circle/dashboard/templates/dashboard/index-nodes.html
View file @
1e514d5b
...
...
@@ -37,7 +37,7 @@
id=
"dashboard-node-search-form"
>
<div
class=
"input-group input-group-sm"
>
<input
id=
"dashboard-node-search-input"
type=
"text"
class=
"form-control"
placeholder=
"{% trans "
Search
..."
%}"
/>
name=
"s"
placeholder=
"{% trans "
Search
..."
%}"
/>
<div
class=
"input-group-btn"
>
<button
type=
"submit"
class=
"btn btn-primary"
title=
"{% trans "
Search
"
%}"
data-container=
"body"
>
<i
class=
"fa fa-search"
></i>
...
...
circle/dashboard/templates/dashboard/index-templates.html
View file @
1e514d5b
...
...
@@ -33,13 +33,25 @@
{% endfor %}
</div>
<div
class=
"list-group-item list-group-footer"
>
<div
class=
"text-right"
>
<a
href=
"{% url "
dashboard
.
views
.
template-list
"
%}"
class=
"btn btn-primary btn-xs"
>
<i
class=
"fa fa-chevron-circle-right"
></i>
{% trans "show all" %}
</a>
<a
href=
"{% url "
dashboard
.
views
.
template-choose
"
%}"
class=
"btn btn-success btn-xs template-choose"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
</a>
<div
class=
"row"
>
<div
class=
"col-xs-6"
>
<form
action=
"{% url "
dashboard
.
views
.
template-list
"
%}"
method=
"GET"
id=
"dashboard-template-search-form"
>
<div
class=
"input-group input-group-sm"
>
<input
id=
"dashboard-group-search-input"
name=
"s"
type=
"text"
class=
"form-control"
placeholder=
"{% trans "
Search
..."
%}"
/>
<div
class=
"input-group-btn"
>
<button
type=
"submit"
class=
"btn btn-primary"
><i
class=
"fa fa-search"
></i></button>
</div>
</div>
</form>
</div>
<div
class=
"col-xs-6 text-right"
>
<a
href=
"{% url "
dashboard
.
views
.
template-list
"
%}"
class=
"btn btn-primary btn-xs"
>
<i
class=
"fa fa-chevron-circle-right"
></i>
{% trans "show all" %}
</a>
<a
href=
"{% url "
dashboard
.
views
.
template-choose
"
%}"
class=
"btn btn-success btn-xs template-choose"
>
<i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
</a>
</div>
</div>
</div>
</div>
...
...
circle/dashboard/templates/dashboard/index-users.html
0 → 100644
View file @
1e514d5b
{% load i18n %}
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<div
class=
"pull-right toolbar"
>
<span
class=
"btn btn-default btn-xs infobtn"
data-container=
"body"
title=
"{% trans "
List
of
CIRCLE
users
."
%}"
><i
class=
"fa fa-info-circle"
></i></span>
</div>
<h3
class=
"no-margin"
><i
class=
"fa fa-users"
></i>
{% trans "Users" %}
</h3>
</div>
<div
class=
"list-group"
id=
"user-list-view"
>
<div
id=
"dashboard-user-list"
>
{% for i in users %}
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.username
%}"
class=
"list-group-item real-link
{% if forloop.last and users|length < 5 %} list-group-item-last{% endif %}"
>
<span
class=
"index-user-list-name"
>
<i
class=
"fa fa-user"
></i>
{% firstof i.get_full_name|safe i.username|safe %}
</span>
<span
class=
"index-user-list-org"
>
<small
class=
"text-muted"
>
{{ i.profile.org_id|default:"" }}
</small>
</span>
</a>
{% endfor %}
</div>
<div
class=
"list-group-item list-group-footer text-right"
>
<div
class=
"row"
>
<div
class=
"col-xs-6"
>
<form
action=
"{% url "
dashboard
.
views
.
user-list
"
%}"
method=
"GET"
id=
"dashboard-user-search-form"
>
<div
class=
"input-group input-group-sm"
>
<input
id=
"dashboard-group-search-input"
name=
"s"
type=
"text"
class=
"form-control"
placeholder=
"{% trans "
Search
..."
%}"
/>
<div
class=
"input-group-btn"
>
<button
type=
"submit"
class=
"btn btn-primary"
><i
class=
"fa fa-search"
></i></button>
</div>
</div>
</form>
</div>
<div
class=
"col-xs-6 text-right"
>
<a
class=
"btn btn-primary btn-xs"
href=
"{% url "
dashboard
.
views
.
user-list
"
%}"
>
<i
class=
"fa fa-chevron-circle-right"
></i>
{% if more_users > 0 %}
{% blocktrans count more=more_users %}
<strong>
{{ more }}
</strong>
more
{% plural %}
<strong>
{{ more }}
</strong>
more
{% endblocktrans %}
{% else %}
{% trans "list" %}
{% endif %}
</a>
<a
class=
"btn btn-success btn-xs user-create"
href=
"{% url "
dashboard
.
views
.
user-create
"
%}"
><i
class=
"fa fa-plus-circle"
></i>
{% trans "new" %}
</a>
</div>
</div>
</div>
</div>
</div>
circle/dashboard/templates/dashboard/index.html
View file @
1e514d5b
...
...
@@ -48,6 +48,12 @@
{% include "dashboard/index-nodes.html" %}
</div>
{% endif %}
{% if perms.auth.change_user %}
<div
class=
"col-lg-4 col-sm-6"
>
{% include "dashboard/index-users.html" %}
</div>
{% endif %}
</div>
</div>
{% endblock %}
circle/dashboard/templates/dashboard/profile.html
View file @
1e514d5b
...
...
@@ -8,7 +8,7 @@
{% block content %}
<div
class=
"row"
>
<div
class=
"col-md-
12
"
>
<div
class=
"col-md-
{% if perms.auth.change_user %}8{% else %}12{% endif %}
"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
{% if request.user.is_superuser %}
...
...
@@ -17,7 +17,7 @@
title=
"{% trans "
Log
in
as
this
user
.
Recommended
to
open
in
an
incognito
window
."
%}"
>
{% trans "Login as this user" %}
</a>
{% endif %}
<a
class=
"pull-right btn btn-default btn-xs"
href=
"{% url "
dashboard
.
index
"
%}"
>
{% trans "Back" %}
</a>
<a
class=
"pull-right btn btn-default btn-xs"
href=
"{% url "
dashboard
.
views
.
user-list
"
%}"
>
{% trans "Back" %}
</a>
<h3
class=
"no-margin"
>
<i
class=
"fa fa-user"
></i>
{% include "dashboard/_display-name.html" with user=profile show_org=True %}
...
...
@@ -109,6 +109,23 @@
</div>
</div>
</div>
{% if perms.auth.change_user %}
<div
class=
"col-md-4"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h3
class=
"no-margin"
>
<i
class=
"fa fa-user"
></i>
{% trans "Edit user" %}
</h3>
</div>
<div
class=
"panel-body"
>
{% crispy form %}
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
circle/dashboard/templates/dashboard/user-create.html
View file @
1e514d5b
{% extends "dashboard/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block content %}
{% crispy form %}
{% crispy form %}
{% endblock %}
circle/dashboard/templates/dashboard/user-list.html
0 → 100644
View file @
1e514d5b
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block title-page %}{% trans "Users" %}{% endblock %}
{% block content %}
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<a
href=
"{% url "
dashboard
.
views
.
user-create
"
%}"
class=
"pull-right btn btn-success btn-xs"
>
<i
class=
"fa fa-plus"
></i>
{% trans "new user" %}
</a>
<h3
class=
"no-margin"
><i
class=
"fa fa-user"
></i>
{% trans "Users" %}
</h3>
</div>
<div
class=
"panel-body"
>
<div
class=
"row"
>
<div
class=
"col-md-offset-8 col-md-4"
id=
"user-list-search"
>
<form
action=
""
method=
"GET"
>
<div
class=
"input-group"
>
{{ search_form.s }}
<div
class=
"input-group-btn"
>
{{ search_form.stype }}
<button
type=
"submit"
class=
"btn btn-primary input-tags"
>
<i
class=
"fa fa-search"
></i>
</button>
</div>
</div>
<!-- .input-group -->
</form>
</div>
<!-- .col-md-4 #user-list-search -->
</div>
</div>
<div
class=
"panel-body"
>
<div
class=
"table-responsive"
>
{% render_table table %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
circle/dashboard/tests/test_views.py
View file @
1e514d5b
...
...
@@ -1293,24 +1293,26 @@ class GroupDetailTest(LoginMixin, TestCase):
self
.
login
(
c
,
'user1'
)
self
.
u1
.
user_permissions
.
add
(
Permission
.
objects
.
get
(
name
=
'Can add user'
))
response
=
c
.
post
(
'/dashboard/
group/
%
d/create/'
%
self
.
g1
.
pk
,
response
=
c
.
post
(
'/dashboard/
profile/create/'
,
{
'username'
:
'userx1'
,
'groups'
:
self
.
g1
.
pk
,
'password1'
:
'test123'
,
'password2'
:
'test123'
})
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
user_count
,
self
.
g1
.
user_set
.
count
())
def
test_permitted_user_add_wo_can_add_user_perm
(
self
):
user_count
=
self
.
g1
.
user_set
.
count
()
c
=
Client
()
self
.
login
(
c
,
'user0'
)
response
=
c
.
post
(
'/dashboard/
group/
%
d/create/'
%
self
.
g1
.
pk
,
response
=
c
.
post
(
'/dashboard/
profile/create/'
,
{
'username'
:
'userx2'
,
'groups'
:
self
.
g1
.
pk
,
'password1'
:
'test123'
,
'password2'
:
'test123'
})
self
.
assertRedirects
(
response
,
'/accounts/login/?next=/dashboard/
group/
%
d/create/'
%
self
.
g1
.
pk
)
'/accounts/login/?next=/dashboard/
profile/create/'
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
user_count
,
self
.
g1
.
user_set
.
count
())
...
...
@@ -1320,11 +1322,12 @@ class GroupDetailTest(LoginMixin, TestCase):
name
=
'Can add user'
))
c
=
Client
()
self
.
login
(
c
,
'user0'
)
response
=
c
.
post
(
'/dashboard/
group/
%
d/create/'
%
self
.
g1
.
pk
,
response
=
c
.
post
(
'/dashboard/
profile/create/'
,
{
'username'
:
'userx2'
,
'groups'
:
self
.
g1
.
pk
,
'password1'
:
'test123'
,
'password2'
:
'test123'
})
self
.
assertRedirects
(
response
,
'/dashboard/
group/
%
d/'
%
self
.
g1
.
pk
)
self
.
assertRedirects
(
response
,
'/dashboard/
profile/userx2/'
)
self
.
assertEqual
(
user_count
+
1
,
self
.
g1
.
user_set
.
count
())
self
.
assertEqual
(
response
.
status_code
,
302
)
...
...
circle/dashboard/urls.py
View file @
1e514d5b
...
...
@@ -52,6 +52,7 @@ from .views import (
TransferTemplateOwnershipView
,
TransferTemplateOwnershipConfirmView
,
OpenSearchDescriptionView
,
NodeActivityView
,
UserList
,
)
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.node
import
node_ops
...
...
@@ -61,6 +62,11 @@ autocomplete_light.autodiscover()
urlpatterns
=
patterns
(
''
,
url
(
r'^$'
,
IndexView
.
as_view
(),
name
=
"dashboard.index"
),
url
(
r"^profile/list/$"
,
UserList
.
as_view
(),
name
=
"dashboard.views.user-list"
),
url
(
r'^profile/create/$'
,
UserCreationView
.
as_view
(),
name
=
"dashboard.views.user-create"
),
url
(
r'^lease/(?P<pk>\d+)/$'
,
LeaseDetail
.
as_view
(),
name
=
"dashboard.views.lease-detail"
),
url
(
r'^lease/create/$'
,
LeaseCreate
.
as_view
(),
...
...
@@ -174,9 +180,6 @@ urlpatterns = patterns(
name
=
"dashboard.views.remove-future-user"
),
url
(
r'^group/create/$'
,
GroupCreate
.
as_view
(),
name
=
'dashboard.views.group-create'
),
url
(
r'^group/(?P<group_pk>\d+)/create/$'
,
UserCreationView
.
as_view
(),
name
=
"dashboard.views.create-user"
),
url
(
r'^group/(?P<group_pk>\d+)/permissions/$'
,
GroupPermissionsView
.
as_view
(),
name
=
"dashboard.views.group-permissions"
),
...
...
circle/dashboard/views/index.py
View file @
1e514d5b
...
...
@@ -21,7 +21,7 @@ import logging
from
django.core.cache
import
get_cache
from
django.core.urlresolvers
import
reverse
from
django.conf
import
settings
from
django.contrib.auth.models
import
Group
from
django.contrib.auth.models
import
Group
,
User
from
django.views.generic
import
TemplateView
from
braces.views
import
LoginRequiredMixin
...
...
@@ -86,6 +86,14 @@ class IndexView(LoginRequiredMixin, TemplateView):
'more_groups'
:
groups
.
count
()
-
len
(
groups
[:
5
]),
})
# users
if
user
.
has_module_perms
(
'auth.change_user'
):
users
=
User
.
objects
.
all
()
context
.
update
({
'users'
:
users
[:
5
],
'more_users'
:
users
.
count
()
-
len
(
users
[:
5
]),
})
# template
if
user
.
has_perm
(
'vm.create_template'
):
context
[
'templates'
]
=
InstanceTemplate
.
get_objects_with_level
(
...
...
circle/dashboard/views/template.py
View file @
1e514d5b
...
...
@@ -207,7 +207,19 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
def
get
(
self
,
*
args
,
**
kwargs
):
self
.
search_form
=
TemplateListSearchForm
(
self
.
request
.
GET
)
self
.
search_form
.
full_clean
()
return
super
(
TemplateList
,
self
)
.
get
(
*
args
,
**
kwargs
)
if
self
.
request
.
is_ajax
():
templates
=
[{
'icon'
:
i
.
os_type
,
'system'
:
i
.
system
,
'url'
:
reverse
(
"dashboard.views.template-detail"
,
kwargs
=
{
'pk'
:
i
.
pk
}),
'name'
:
i
.
name
}
for
i
in
self
.
get_queryset
()]
return
HttpResponse
(
json
.
dumps
(
templates
),
content_type
=
"application/json"
,
)
else
:
return
super
(
TemplateList
,
self
)
.
get
(
*
args
,
**
kwargs
)
def
create_acl_queryset
(
self
,
model
):
queryset
=
super
(
TemplateList
,
self
)
.
create_acl_queryset
(
model
)
...
...
circle/dashboard/views/user.py
View file @
1e514d5b
...
...
@@ -31,25 +31,31 @@ from django.core.exceptions import (
)
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.core.paginator
import
Paginator
,
InvalidPage
from
django.db.models
import
Q
from
django.http
import
HttpResponse
,
HttpResponseRedirect
,
Http404
from
django.shortcuts
import
redirect
,
get_object_or_404
from
django.utils.translation
import
ugettext
as
_
from
django.views.decorators.http
import
require_POST
from
django.views.generic
import
(
TemplateView
,
DetailView
,
View
,
UpdateView
,
CreateView
,
TemplateView
,
View
,
UpdateView
,
CreateView
,
)
from
django_sshkey.models
import
UserKey
from
braces.views
import
LoginRequiredMixin
,
PermissionRequiredMixin
from
django_tables2
import
SingleTableView
from
vm.models
import
Instance
,
InstanceTemplate
from
..forms
import
(
CircleAuthenticationForm
,
MyProfileForm
,
UserCreationForm
,
UnsubscribeForm
,
UserKeyForm
,
CirclePasswordChangeForm
,
ConnectCommandForm
,
UserListSearchForm
,
UserEditForm
,
)
from
..models
import
Profile
,
GroupProfile
,
ConnectCommand
from
..tables
import
(
UserKeyListTable
,
ConnectCommandListTable
,
UserListTable
,
)
from
..models
import
Profile
,
GroupProfile
,
ConnectCommand
,
create_profile
from
..tables
import
UserKeyListTable
,
ConnectCommandListTable
from
.util
import
saml_available
,
DeleteViewBase
...
...
@@ -267,36 +273,46 @@ class UserCreationView(LoginRequiredMixin, PermissionRequiredMixin,
template_name
=
'dashboard/user-create.html'
permission_required
=
"auth.add_user"
def
get_
success_url
(
self
):
re
verse
(
'dashboard.views.group-detail'
,
args
=
[
self
.
group
.
pk
])
def
get_
template_names
(
self
):
re
turn
[
'dashboard/nojs-wrapper.html'
]
def
get_group
(
self
,
group_pk
):
self
.
group
=
get_object_or_404
(
Group
,
pk
=
group_pk
)
if
not
self
.
group
.
profile
.
has_level
(
self
.
request
.
user
,
'owner'
):
raise
PermissionDenied
()
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
context
=
super
(
UserCreationView
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
.
update
({
'template'
:
self
.
template_name
,
'box_title'
:
_
(
'Create a User'
),
})
return
context
def
get
(
self
,
*
args
,
**
kwargs
):
self
.
get_group
(
kwargs
.
pop
(
'group_pk'
)
)
return
super
(
UserCreationView
,
self
)
.
get
(
*
args
,
**
kwargs
)
def
post
(
self
,
*
args
,
**
kwargs
):
group_pk
=
kwargs
.
pop
(
'group_pk'
)
self
.
get_group
(
group_pk
)
ret
=
super
(
UserCreationView
,
self
)
.
post
(
*
args
,
**
kwargs
)
if
self
.
object
:
create_profile
(
self
.
object
)
self
.
object
.
groups
.
add
(
self
.
group
)
return
redirect
(
r
everse
(
'dashboard.views.group-detail'
,
args
=
[
group_pk
])
)
def
get
_success_url
(
self
):
return
reverse
(
'dashboard.views.profile'
,
args
=
[
self
.
object
.
username
]
)
def
get_form_kwargs
(
self
):
profiles
=
GroupProfile
.
get_objects_with_level
(
'owner'
,
self
.
request
.
user
)
choices
=
Group
.
objects
.
filter
(
groupprofile__in
=
profiles
)
group_pk
=
self
.
request
.
GET
.
get
(
'group_pk'
)
if
group_pk
:
try
:
default
=
choices
.
get
(
pk
=
group_pk
)
except
(
ValueError
,
Group
.
DoesNotExist
):
r
aise
Http404
(
)
else
:
return
ret
default
=
None
val
=
super
(
UserCreationView
,
self
)
.
get_form_kwargs
()
val
.
update
({
'choices'
:
choices
,
'default'
:
default
})
return
val
class
ProfileView
(
LoginRequiredMixin
,
DetailView
):
class
ProfileView
(
LoginRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
template_name
=
"dashboard/profile.html"
model
=
User
slug_field
=
"username"
slug_url_kwarg
=
"username"
form_class
=
UserEditForm
success_message
=
_
(
"Successfully modified user."
)
def
get
(
self
,
*
args
,
**
kwargs
):
user
=
self
.
request
.
user
...
...
@@ -357,6 +373,15 @@ class ProfileView(LoginRequiredMixin, DetailView):
user
,
self
.
request
.
user
)
return
context
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
request
.
user
.
has_perm
(
'auth.change_user'
):
raise
PermissionDenied
()
return
super
(
ProfileView
,
self
)
.
post
(
self
,
request
,
*
args
,
**
kwargs
)
def
get_success_url
(
self
):
return
reverse
(
'dashboard.views.profile'
,
kwargs
=
self
.
kwargs
)
@require_POST
def
toggle_use_gravatar
(
request
,
**
kwargs
):
...
...
@@ -480,3 +505,48 @@ class ConnectCommandCreate(LoginRequiredMixin, SuccessMessageMixin,
kwargs
=
super
(
ConnectCommandCreate
,
self
)
.
get_form_kwargs
()
kwargs
[
'user'
]
=
self
.
request
.
user
return
kwargs
class
UserList
(
LoginRequiredMixin
,
PermissionRequiredMixin
,
SingleTableView
):
template_name
=
"dashboard/user-list.html"
permission_required
=
"auth.change_user"
model
=
User
table_class
=
UserListTable
table_pagination
=
True
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
context
=
super
(
UserList
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
[
'search_form'
]
=
self
.
search_form
return
context
def
get
(
self
,
*
args
,
**
kwargs
):
self
.
search_form
=
UserListSearchForm
(
self
.
request
.
GET
)
self
.
search_form
.
full_clean
()
if
self
.
request
.
is_ajax
():
users
=
[
{
'url'
:
reverse
(
"dashboard.views.profile"
,
args
=
[
i
.
username
]),
'name'
:
i
.
get_full_name
()
or
i
.
username
,
'org_id'
:
i
.
profile
.
org_id
,
}
for
i
in
self
.
get_queryset
()]
return
HttpResponse
(
json
.
dumps
(
users
),
content_type
=
"application/json"
)
else
:
return
super
(
UserList
,
self
)
.
get
(
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
logger
.
debug
(
'UserList.get_queryset() called. User:
%
s'
,
unicode
(
self
.
request
.
user
))
qs
=
User
.
objects
.
all
()
.
order_by
(
"-pk"
)
q
=
self
.
search_form
.
cleaned_data
.
get
(
's'
)
if
q
:
filters
=
(
Q
(
username__icontains
=
q
)
|
Q
(
email__icontains
=
q
)
|
Q
(
profile__org_id__icontains
=
q
))
for
w
in
q
.
split
()[:
3
]:
filters
|=
(
Q
(
first_name__icontains
=
w
)
|
Q
(
last_name__icontains
=
w
))
qs
=
qs
.
filter
(
filters
)
return
qs
.
select_related
(
"profile"
)
circle/dashboard/views/vm.py
View file @
1e514d5b
...
...
@@ -950,6 +950,7 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
destroyed_at
=
None
)
.
all
()
instances
=
[{
'pk'
:
i
.
pk
,
'url'
:
reverse
(
'dashboard.views.detail'
,
args
=
[
i
.
pk
]),
'name'
:
i
.
name
,
'icon'
:
i
.
get_status_icon
(),
'host'
:
i
.
short_hostname
,
...
...
circle/locale/hu/LC_MESSAGES/django.po
View file @
1e514d5b
This source diff could not be displayed because it is too large. You can
view the blob
instead.
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