Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
5418d0b4
Commit
5418d0b4
authored
Apr 08, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Change] Using csv replace xlsx
parent
bcc065eb
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
92 additions
and
76 deletions
+92
-76
asset.py
apps/assets/models/asset.py
+0
-1
group.py
apps/assets/models/group.py
+1
-0
idc.py
apps/assets/models/idc.py
+1
-0
user.py
apps/assets/models/user.py
+0
-1
_asset_import_modal.html
apps/assets/templates/assets/_asset_import_modal.html
+4
-1
asset.py
apps/assets/views/asset.py
+0
-0
settings.py
apps/jumpserver/settings.py
+1
-1
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
_base_create_update.html
apps/templates/_base_create_update.html
+1
-1
base.html
apps/templates/base.html
+2
-2
first_login.html
apps/users/templates/users/first_login.html
+5
-3
user_detail.html
apps/users/templates/users/user_detail.html
+4
-0
user_pubkey_update.html
apps/users/templates/users/user_pubkey_update.html
+1
-0
group.py
apps/users/views/group.py
+1
-1
user.py
apps/users/views/user.py
+71
-65
No files found.
apps/assets/models/asset.py
View file @
5418d0b4
...
...
@@ -86,7 +86,6 @@ class Asset(models.Model):
def
__unicode__
(
self
):
return
'
%
s <
%
s:
%
s>'
%
(
self
.
hostname
,
self
.
ip
,
self
.
port
)
__str__
=
__unicode__
@property
...
...
apps/assets/models/group.py
View file @
5418d0b4
...
...
@@ -23,6 +23,7 @@ class AssetGroup(models.Model):
def
__unicode__
(
self
):
return
self
.
name
__str__
=
__unicode__
class
Meta
:
ordering
=
[
'name'
]
...
...
apps/assets/models/idc.py
View file @
5418d0b4
...
...
@@ -36,6 +36,7 @@ class IDC(models.Model):
def
__unicode__
(
self
):
return
self
.
name
__str__
=
__unicode__
@classmethod
def
initial
(
cls
):
...
...
apps/assets/models/user.py
View file @
5418d0b4
...
...
@@ -50,7 +50,6 @@ class AdminUser(models.Model):
def
__unicode__
(
self
):
return
self
.
name
__str__
=
__unicode__
@property
...
...
apps/assets/templates/assets/_asset_import_modal.html
View file @
5418d0b4
...
...
@@ -7,11 +7,14 @@
{% csrf_token %}
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_assets"
>
{% trans "Template" %}
</label>
<a
href=
"{
{ MEDIA_URL }}files/asset_import_template.xlsx
"
style=
"display: block"
>
{% trans 'Download' %}
</a>
<a
href=
"{
% url 'assets:asset-export' %}
"
style=
"display: block"
>
{% trans 'Download' %}
</a>
</div>
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_users"
>
{% trans "Asset excel file" %}
</label>
<input
id=
"id_assets"
type=
"file"
name=
"file"
/>
<span
class=
"help-block"
>
{% trans 'If set id, will use this id update asset existed' %}
</span>
</div>
</form>
<p>
...
...
apps/assets/views/asset.py
View file @
5418d0b4
This diff is collapsed.
Click to expand it.
apps/jumpserver/settings.py
View file @
5418d0b4
...
...
@@ -260,7 +260,7 @@ MEDIA_URL = '/media/'
MEDIA_ROOT
=
os
.
path
.
join
(
BASE_DIR
,
'media'
)
.
replace
(
'
\\
'
,
'/'
)
+
'/'
# Use django-bootstrap-form to format template, input max width arg
BOOTSTRAP_COLUMN_COUNT
=
11
#
BOOTSTRAP_COLUMN_COUNT = 11
# Init data or generate fake data source for development
FIXTURE_DIRS
=
[
os
.
path
.
join
(
BASE_DIR
,
'fixtures'
),
]
...
...
apps/locale/zh/LC_MESSAGES/django.mo
View file @
5418d0b4
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
5418d0b4
This diff is collapsed.
Click to expand it.
apps/templates/_base_create_update.html
View file @
5418d0b4
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% load bootstrap
3
%}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
...
...
apps/templates/base.html
View file @
5418d0b4
...
...
@@ -33,9 +33,9 @@
{% block update_public_key_message %}
{% if user.is_authenticated and not user.is_public_key_valid %}
<div
class=
"alert alert-danger"
style=
"margin: 20px auto 0px"
>
{% url 'users:user-p
rofile' as profile_url
%}
{% url 'users:user-p
ubkey-update' as user_pubkey_update
%}
{% blocktrans %}
Your ssh-public-key has been expired. Please click
<a
href=
"{{
profile_url
}}"
>
this link
</a>
to update your ssh-public-key.
Your ssh-public-key has been expired. Please click
<a
href=
"{{
user_pubkey_update
}}"
>
this link
</a>
to update your ssh-public-key.
{% endblocktrans %}
</div>
{% endif %}
...
...
apps/users/templates/users/first_login.html
View file @
5418d0b4
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% load bootstrap3 %}
{% load bootstrap3 %}
{% block custom_head_css_js %}
...
...
@@ -44,10 +44,12 @@
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form|bootstrap }}
{% bootstrap_form form %}
{# {{ form|bootstrap }}#}
{% endfor %}
{% else %}
{{ wizard.form|bootstrap }}
{# {{ wizard.form|bootstrap }}#}
{% bootstrap_form wizard.form %}
{% endif %}
</form>
</div>
...
...
apps/users/templates/users/user_detail.html
View file @
5418d0b4
...
...
@@ -89,6 +89,10 @@
<td>
{% trans 'Role' %}:
</td>
<td><b>
{{ user_object.get_role_display }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Enable OTP' %}:
</td>
<td><b>
{{ user_object.enable_otp|yesno:"Yes,No,Unknown"}}
</b></td>
</tr>
<tr>
<td>
{% trans 'Date expired' %}:
</td>
<td><b>
{{ user_object.date_expired|date:"Y-m-j H:i:s" }}
</b></td>
...
...
apps/users/templates/users/user_pubkey_update.html
View file @
5418d0b4
...
...
@@ -61,6 +61,7 @@
<label>
{{ user.public_key_obj.hash_md5 }}
</label>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Update public key' %}
</h3>
{% bootstrap_field form.public_key layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
...
...
apps/users/views/group.py
View file @
5418d0b4
...
...
@@ -103,7 +103,7 @@ class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
users
=
User
.
objects
.
exclude
(
id__in
=
self
.
object
.
users
.
all
())
context
=
{
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User
Group D
etail'
),
'action'
:
_
(
'User
group d
etail'
),
'users'
:
users
,
}
kwargs
.
update
(
context
)
...
...
apps/users/views/user.py
View file @
5418d0b4
...
...
@@ -4,10 +4,9 @@ from __future__ import unicode_literals
import
json
import
uuid
from
openpyxl
import
load_workbook
from
openpyxl
import
Workbook
from
openpyxl.writer.excel
import
save_virtual_workbook
import
csv
import
codecs
from
io
import
StringIO
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
...
...
@@ -31,7 +30,7 @@ from .. import forms
from
..models
import
User
,
UserGroup
from
..utils
import
AdminUserRequiredMixin
,
user_add_success_next
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_logger
from
common.utils
import
get_logger
,
get_object_or_none
from
perms.models
import
AssetPermission
__all__
=
[
'UserListView'
,
'UserCreateView'
,
'UserDetailView'
,
...
...
@@ -123,34 +122,44 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
return
super
(
UserDetailView
,
self
)
.
get_context_data
(
**
kwargs
)
USER_ATTR_MAPPING
=
(
(
'name'
,
'Name'
),
(
'username'
,
'Username'
),
(
'email'
,
'Email'
),
(
'groups'
,
'User groups'
),
(
'role'
,
'Role'
),
(
'phone'
,
'Phone'
),
(
'wechat'
,
'Wechat'
),
(
'comment'
,
'Comment'
),
)
@method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
UserExportView
(
View
):
def
get
(
self
,
request
):
mapping
=
[
(
k
,
_
(
v
))
for
k
,
v
in
USER_ATTR_MAPPING
]
spm
=
request
.
GET
.
get
(
'spm'
,
''
)
users_id
=
cache
.
get
(
spm
)
if
not
users_id
and
not
isinstance
(
users_id
,
list
):
return
HttpResponse
(
'May be expired'
,
status
=
404
)
users_id
=
cache
.
get
(
spm
,
[
'1'
])
filename
=
'users-{}.csv'
.
format
(
timezone
.
localtime
(
timezone
.
now
())
.
strftime
(
'
%
Y-
%
m-
%
d_
%
H-
%
M-
%
S'
))
response
=
HttpResponse
(
content_type
=
'text/csv'
)
response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
response
.
write
(
codecs
.
BOM_UTF8
)
users
=
User
.
objects
.
filter
(
id__in
=
users_id
)
print
(
users
)
wb
=
Workbook
()
ws
=
wb
.
active
ws
.
title
=
'User'
header
=
[
"name"
,
'username'
,
'email'
,
'groups'
,
"role"
,
"phone"
,
"wechat"
,
"comment"
]
ws
.
append
(
header
)
writer
=
csv
.
writer
(
response
,
dialect
=
'excel'
,
quoting
=
csv
.
QUOTE_MINIMAL
)
header
=
[
v
for
k
,
v
in
mapping
]
writer
.
writerow
(
header
)
for
user
in
users
:
ws
.
append
([
user
.
name
,
user
.
username
,
user
.
email
,
','
.
join
([
group
.
name
for
group
in
user
.
groups
.
all
()]),
user
.
role
,
user
.
phone
,
user
.
wechat
,
user
.
comment
])
groups
=
','
.
join
([
group
.
name
for
group
in
user
.
groups
.
all
()])
writer
.
writerow
([
user
.
name
,
user
.
username
,
user
.
email
,
groups
,
user
.
role
,
user
.
phone
,
user
.
wechat
,
user
.
comment
])
filename
=
'users-{}.xlsx'
.
format
(
timezone
.
localtime
(
timezone
.
now
())
.
strftime
(
'
%
Y-
%
m-
%
d_
%
H-
%
M-
%
S'
))
response
=
HttpResponse
(
save_virtual_workbook
(
wb
),
content_type
=
'applications/vnd.ms-excel'
)
response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
return
response
def
post
(
self
,
request
):
...
...
@@ -158,7 +167,7 @@ class UserExportView(View):
users_id
=
json
.
loads
(
request
.
body
)
.
get
(
'users_id'
,
[])
except
ValueError
:
return
HttpResponse
(
'Json object not valid'
,
status
=
400
)
spm
=
uuid
.
uuid4
()
.
get_hex
()
spm
=
uuid
.
uuid4
()
.
hex
cache
.
set
(
spm
,
users_id
,
300
)
url
=
reverse
(
'users:user-export'
)
+
'?spm=
%
s'
%
spm
return
JsonResponse
({
'redirect'
:
url
})
...
...
@@ -179,54 +188,51 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
return
self
.
render_json_response
(
data
)
def
form_valid
(
self
,
form
):
try
:
wb
=
load_workbook
(
form
.
cleaned_data
[
'file'
])
ws
=
wb
.
get_active_sheet
()
except
Exception
as
e
:
print
(
e
)
data
=
{
'valid'
:
False
,
'msg'
:
'Not a valid Excel file'
}
return
self
.
render_json_response
(
data
)
rows
=
ws
.
rows
header_need
=
[
"name"
,
'username'
,
'email'
,
'groups'
,
"role"
,
"phone"
,
"wechat"
,
"comment"
]
header
=
[
col
.
value
for
col
in
next
(
rows
)]
print
(
header
)
if
header
!=
header_need
:
data
=
{
'valid'
:
False
,
'msg'
:
'Must be same format as '
'template or export file'
}
file
=
form
.
cleaned_data
[
'file'
]
data
=
file
.
read
()
.
decode
(
'utf-8'
)
.
strip
(
codecs
.
BOM_UTF8
.
decode
(
'utf-8'
))
csv_file
=
StringIO
(
data
)
reader
=
csv
.
reader
(
csv_file
)
csv_data
=
[
row
for
row
in
reader
]
header_
=
csv_data
[
0
]
mapping_reverse
=
{
_
(
v
):
k
for
k
,
v
in
USER_ATTR_MAPPING
}
user_attr
=
[
mapping_reverse
.
get
(
n
,
None
)
for
n
in
header_
]
if
None
in
user_attr
:
data
=
{
'valid'
:
False
,
'msg'
:
'Must be same format as '
'template or export file'
}
return
self
.
render_json_response
(
data
)
created
=
[]
updated
=
[]
failed
=
[]
for
row
in
rows
:
user_dict
=
dict
(
zip
(
header
,
[
col
.
value
for
col
in
row
]
))
created
,
updated
,
failed
=
[],
[],
[]
for
row
in
csv_data
[
1
:]:
if
set
(
row
)
==
{
''
}:
continue
user_dict
=
dict
(
zip
(
user_attr
,
row
))
groups_name
=
user_dict
.
pop
(
'groups'
)
if
groups_name
:
groups_name
=
groups_name
.
split
(
','
)
groups
=
UserGroup
.
objects
.
filter
(
name__in
=
groups_name
)
else
:
groups
=
None
try
:
user
=
User
.
objects
.
create
(
**
user_dict
)
user_add_success_next
(
user
)
created
.
append
(
user_dict
[
'username'
])
except
User
.
IntegrityError
as
e
:
user
=
User
.
objects
.
filter
(
username
=
user_dict
[
'username'
])
if
not
user
:
failed
.
append
(
user_dict
[
'username'
])
continue
user
.
update
(
**
user_dict
)
user
=
user
[
0
]
updated
.
append
(
user_dict
[
'username'
])
except
TypeError
as
e
:
print
(
e
)
failed
.
append
(
user_dict
[
'username'
])
user
=
None
username
=
user_dict
[
'username'
]
user
=
get_object_or_none
(
User
,
username
=
username
)
if
not
user
:
try
:
user
=
User
.
objects
.
create
(
**
user_dict
)
created
.
append
(
user_dict
[
'username'
])
user_add_success_next
(
user
)
except
Exception
as
e
:
failed
.
append
(
'
%
s:
%
s'
%
(
user_dict
[
'username'
],
str
(
e
)))
else
:
for
k
,
v
in
user_dict
.
items
():
if
v
:
setattr
(
user
,
k
,
v
)
try
:
user
.
save
()
updated
.
append
(
user_dict
[
'username'
])
except
Exception
as
e
:
failed
.
append
(
'
%
s:
%
s'
%
(
user_dict
[
'username'
],
str
(
e
)))
if
user
and
groups
:
user
.
groups
.
add
(
*
tuple
(
groups
))
user
.
groups
=
groups
user
.
save
()
data
=
{
...
...
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