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
b0551449
Commit
b0551449
authored
Mar 01, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge with audits
parents
7825c107
dd5dd9d7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
356 additions
and
215 deletions
+356
-215
.gitignore
.gitignore
+2
-0
forms.py
apps/assets/forms.py
+7
-7
_asset_bulk_update_modal.html
apps/assets/templates/assets/_asset_bulk_update_modal.html
+0
-5
admin_user_detail.html
apps/assets/templates/assets/admin_user_detail.html
+1
-4
admin_user_list.html
apps/assets/templates/assets/admin_user_list.html
+6
-3
asset_detail.html
apps/assets/templates/assets/asset_detail.html
+0
-1
asset_group_detail.html
apps/assets/templates/assets/asset_group_detail.html
+1
-4
asset_group_list.html
apps/assets/templates/assets/asset_group_list.html
+3
-1
asset_list.html
apps/assets/templates/assets/asset_list.html
+40
-6
asset_tag_detail.html
apps/assets/templates/assets/asset_tag_detail.html
+1
-4
asset_tags_list.html
apps/assets/templates/assets/asset_tags_list.html
+1
-3
idc_assets.html
apps/assets/templates/assets/idc_assets.html
+1
-4
idc_create_update.html
apps/assets/templates/assets/idc_create_update.html
+1
-0
idc_detail.html
apps/assets/templates/assets/idc_detail.html
+1
-4
system_user_asset.html
apps/assets/templates/assets/system_user_asset.html
+1
-4
system_user_asset_group.html
apps/assets/templates/assets/system_user_asset_group.html
+1
-4
system_user_detail.html
apps/assets/templates/assets/system_user_detail.html
+1
-4
system_user_list.html
apps/assets/templates/assets/system_user_list.html
+3
-2
views.py
apps/assets/views.py
+9
-9
command_log_list.html
apps/audits/templates/audits/command_log_list.html
+0
-1
proxy_log_detail.html
apps/audits/templates/audits/proxy_log_detail.html
+0
-1
proxy_log_list.html
apps/audits/templates/audits/proxy_log_list.html
+0
-1
fake.json
apps/fixtures/fake.json
+0
-0
settings.py
apps/jumpserver/settings.py
+6
-6
task.py
apps/ops/models/task.py
+3
-4
detail.html
apps/ops/templates/cron/detail.html
+0
-2
detail.html
apps/ops/templates/sudo/detail.html
+0
-2
detail.html
apps/ops/templates/task/detail.html
+0
-2
asset_permission_asset.html
apps/perms/templates/perms/asset_permission_asset.html
+1
-4
asset_permission_detail.html
apps/perms/templates/perms/asset_permission_detail.html
+1
-4
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+0
-1
asset_permission_user.html
apps/perms/templates/perms/asset_permission_user.html
+1
-4
jumpserver.css
apps/static/css/jumpserver.css
+14
-2
_base_list.html
apps/templates/_base_list.html
+0
-1
base.html
apps/templates/base.html
+4
-3
api.py
apps/users/api.py
+9
-11
user.py
apps/users/models/user.py
+24
-3
permissions.py
apps/users/permissions.py
+11
-18
user_asset_permission.html
apps/users/templates/users/user_asset_permission.html
+1
-4
user_detail.html
apps/users/templates/users/user_detail.html
+0
-0
user_granted_asset.html
apps/users/templates/users/user_granted_asset.html
+1
-4
user_group_asset_permission.html
apps/users/templates/users/user_group_asset_permission.html
+1
-4
user_group_granted_asset.html
apps/users/templates/users/user_group_granted_asset.html
+1
-4
user_profile.html
apps/users/templates/users/user_profile.html
+148
-0
__init__.py
apps/users/templatetags/__init__.py
+0
-0
users_tags.py
apps/users/templatetags/users_tags.py
+0
-38
views_urls.py
apps/users/urls/views_urls.py
+6
-0
user.py
apps/users/views/user.py
+42
-21
config_example.py
config_example.py
+2
-1
No files found.
.gitignore
View file @
b0551449
...
...
@@ -19,3 +19,5 @@ config.py
migrations/
*.log
host_rsa_key
*.bat
tags
apps/assets/forms.py
View file @
b0551449
...
...
@@ -20,13 +20,13 @@ class AssetCreateForm(forms.ModelForm):
self
.
instance
.
tags
.
clear
()
self
.
instance
.
tags
.
add
(
*
tuple
(
tags
))
def
clean
(
self
):
clean_data
=
super
(
AssetCreateForm
,
self
)
.
clean
()
ip
=
clean_data
.
get
(
'ip'
)
port
=
clean_data
.
get
(
'port'
)
query
=
Asset
.
objects
.
filter
(
ip
=
ip
,
port
=
port
)
if
query
:
raise
forms
.
ValidationError
(
'this asset has exists.'
)
#
def clean(self):
#
clean_data = super(AssetCreateForm, self).clean()
#
ip = clean_data.get('ip')
#
port = clean_data.get('port')
#
query = Asset.objects.filter(ip=ip, port=port)
#
if query:
#
raise forms.ValidationError('this asset has exists.')
class
Meta
:
model
=
Asset
...
...
apps/assets/templates/assets/_asset_bulk_update_modal.html
View file @
b0551449
...
...
@@ -77,10 +77,6 @@
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_asset_bulk_update{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/admin_user_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -439,4 +437,4 @@ $(document).ready(function () {
objectDelete
(
$this
,
name
,
the_url
,
redirect_url
);
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/admin_user_list.html
View file @
b0551449
...
...
@@ -52,10 +52,11 @@ $(document).ready(function(){
$
(
td
).
html
(
'<a href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</a>'
);
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
script_btn
=
'<a href="{% url "assets:admin-user-update" pk=99991937 %}" class="btn btn-xs btn-primary">{% trans "Script" %}</a>'
.
replace
(
'99991937'
,
cellData
);
{
#
var
script_btn
=
'<a href="{% url "assets:admin-user-update" pk=99991937 %}" class="btn btn-xs btn-primary">{% trans "Script" %}</a>'
.
replace
(
'99991937'
,
cellData
);
#
}
var
update_btn
=
'<a href="{% url "assets:admin-user-update" pk=99991937 %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'99991937'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'
.
replace
(
'99991937'
,
cellData
);
$
(
td
).
html
(
script_btn
+
update_btn
+
del_btn
)
{
#
$
(
td
).
html
(
script_btn
+
update_btn
+
del_btn
)
#
}
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
ajax_url
:
'{% url "api-assets:admin-user-list" %}'
,
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"name"
},
{
data
:
"username"
},
{
data
:
"assets_amount"
},
{
data
:
function
()
{
return
'lost'
}
},
...
...
@@ -72,7 +73,9 @@ $(document).ready(function(){
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-assets:admin-user-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
$data_table
.
ajax
.
reload
();
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
...
...
apps/assets/templates/assets/asset_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load static %}
{% load i18n %}
...
...
apps/assets/templates/assets/asset_group_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -394,4 +392,4 @@ $(document).ready(function () {
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/asset_group_list.html
View file @
b0551449
...
...
@@ -70,7 +70,9 @@ $(document).ready(function(){
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-assets:asset-group-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
$data_table
.
ajax
.
reload
();
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
...
...
apps/assets/templates/assets/asset_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n %}
{% load static %}
{% load common_tags %}
{% 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>
...
...
@@ -33,7 +32,7 @@
<div
class=
"tagBtnList"
>
{% for tag in tag_list %}
<a
href=
"{% url 'assets:asset-tags' tag_id=tag.0 %}"
{%
if
tag
.
0
|
int_to_str
=
=
tag_id
%}
{%
if
tag
.
0 =
=
tag_id
%}
class=
"tagBtn2 label label-warning"
name=
"tag_on"
>
{% else %}
class="tagBtn2 label label-default">
...
...
@@ -105,6 +104,38 @@ function tagShow() {
}
}
//onload;
function
objDelete
(
obj
,
name
,
url
)
{
function
doDelete
()
{
var
body
=
{};
var
success
=
function
()
{
swal
(
'Deleted!'
,
"[ "
+
name
+
"]"
+
" has been deleted "
,
"success"
);
$
(
obj
).
parent
().
parent
().
remove
();
};
var
fail
=
function
()
{
swal
(
"Failed"
,
"Delete"
+
"[ "
+
name
+
" ]"
+
"failed"
,
"error"
);
};
APIUpdateAttr
({
url
:
url
,
body
:
JSON
.
stringify
(
body
),
method
:
'DELETE'
,
success
:
success
,
error
:
fail
});
}
swal
({
title
:
'Are you sure delete ?'
,
text
:
" ["
+
name
+
"] "
,
type
:
"warning"
,
showCancelButton
:
true
,
cancelButtonText
:
'Cancel'
,
confirmButtonColor
:
"#DD6B55"
,
confirmButtonText
:
'Confirm'
,
closeOnConfirm
:
false
},
function
()
{
doDelete
()
});
}
$
(
document
).
ready
(
function
(){
var
options
=
{
ele
:
$
(
'#asset_list_table'
),
...
...
@@ -187,8 +218,11 @@ $(document).ready(function(){
var
name
=
$
(
this
).
closest
(
"tr"
).
find
(
":nth-child(2)"
).
children
(
'a'
).
html
();
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-assets:asset-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
$data_table
.
ajax
.
reload
();
console
.
log
(
the_url
);
objDelete
(
$this
,
name
,
the_url
);
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
...
...
@@ -324,5 +358,6 @@ $(document).ready(function(){
{
#
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
post_list
),
success
:
success
});
#
}
$
(
'#asset_bulk_update_modal'
).
modal
(
'hide'
);
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/asset_tag_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -276,4 +274,4 @@ $(document).ready(function () {
deleteTagAssets
(
$this
,
name
,
the_url
,
data
);
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/asset_tags_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n static %}
{#{% load common_tags %}#}
{% 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>
...
...
@@ -123,4 +122,4 @@ $(document).ready(function () {
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/idc_assets.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -365,4 +363,4 @@ $(document).ready(function () {
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/idc_create_update.html
View file @
b0551449
...
...
@@ -41,6 +41,7 @@
<div
class=
"hr-line-dashed"
></div>
<h3
class=
"widget-head-color-box"
>
IP段
</h3>
{{ form.operator|bootstrap_horizontal }}
{{ form.intranet|bootstrap_horizontal }}
{{ form.extranet|bootstrap_horizontal }}
...
...
apps/assets/templates/assets/idc_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -155,4 +153,4 @@ $(document).ready(function () {
idcDelete
(
name
,
the_url
);
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/system_user_asset.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -370,4 +368,4 @@ $(document).ready(function () {
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/system_user_asset_group.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -133,4 +131,4 @@
$
(
'.select2'
).
select2
();
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/system_user_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -184,4 +182,4 @@
$
(
'.select2'
).
select2
();
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/assets/templates/assets/system_user_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block table_search %}
{% endblock %}
...
...
@@ -75,7 +74,9 @@ $(document).ready(function(){
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "api-assets:system-user-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
objectDelete
(
$this
,
name
,
the_url
);
$data_table
.
ajax
.
reload
();
setTimeout
(
function
()
{
$data_table
.
ajax
.
reload
();
},
3000
);
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
...
...
apps/assets/views.py
View file @
b0551449
...
...
@@ -139,15 +139,15 @@ class AssetUpdateView(AdminUserRequiredMixin, UpdateAssetTagsMiXin, UpdateView):
print
(
form
.
errors
)
return
super
(
AssetUpdateView
,
self
)
.
form_invalid
(
form
)
def
form_valid
(
self
,
form
):
asset
=
form
.
save
(
commit
=
False
)
def
prn_obj_key
(
obj_form
):
return
obj_form
.
clean
()
.
keys
()
for
i
in
prn_obj_key
(
form
):
if
i
not
in
self
.
new_form
.
keys
():
print
i
#
def form_valid(self, form):
#
asset = form.save(commit=False)
#
#
def prn_obj_key(obj_form):
#
return obj_form.clean().keys()
#
#
for i in prn_obj_key(form):
#
if i not in self.new_form.keys():
#
print i
#delattr(asset, '"%s" % i')
#del asset.i
...
...
apps/audits/templates/audits/command_log_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n %}
{% load static %}
{% load common_tags %}
{% block content_left_head %}
<link
href=
"{% static "
css
/
plugins
/
footable
/
footable
.
core
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static 'css/plugins/datepicker/datepicker3.css' %}"
rel=
"stylesheet"
>
...
...
apps/audits/templates/audits/proxy_log_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load static %}
{% load i18n %}
...
...
apps/audits/templates/audits/proxy_log_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n %}
{% load static %}
{% load common_tags %}
{% block content_left_head %}
<link
href=
"{% static 'css/plugins/datepicker/datepicker3.css' %}"
rel=
"stylesheet"
>
<style>
...
...
apps/fixtures/fake.json
View file @
b0551449
This diff is collapsed.
Click to expand it.
apps/jumpserver/settings.py
View file @
b0551449
...
...
@@ -14,7 +14,6 @@ import os
import
sys
from
django.urls
import
reverse_lazy
from
datetime
import
timedelta
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)))
...
...
@@ -300,11 +299,11 @@ CELERY_RESULT_BACKEND = BROKER_URL
# crontab job
# CELERYBEAT_SCHEDULE = {
# Check applications is alive every 10m
# 'check_terminal_alive': {
# 'task': 'applications.tasks.check_terminal_alive',
# 'schedule': timedelta(seconds=TERMINAL_HEATBEAT_INTERVAL),
# 'args': (),
# },
# 'check_terminal_alive': {
# 'task': 'applications.tasks.check_terminal_alive',
# 'schedule': timedelta(seconds=TERMINAL_HEATBEAT_INTERVAL),
# 'args': (),
# },
# }
...
...
@@ -326,3 +325,4 @@ CAPTCHA_FOREGROUND_COLOR = '#001100'
COMMAND_STORE_BACKEND
=
'audits.backends.command.db'
RECORD_STORE_BACKEND
=
'audits.backends.record.db'
CAPTCHA_TEST_MODE
=
CONFIG
.
CAPTCHA_TEST_MODE
apps/ops/models/task.py
View file @
b0551449
...
...
@@ -6,7 +6,6 @@ import logging
from
uuid
import
uuid4
from
assets.models
import
Asset
from
ops.models
import
TaskRecord
from
ops.utils.ansible_api
import
ADHocRunner
,
Config
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
...
...
@@ -20,7 +19,7 @@ logger = logging.getLogger(__name__)
class
Task
(
models
.
Model
):
record
=
models
.
OneToOneField
(
TaskRecord
)
name
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Name'
))
is_gather_facts
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is Gather Ansible Facts'
))
is_gather_facts
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is Gather Ansible Facts'
))
assets
=
models
.
ManyToManyField
(
Asset
,
related_name
=
'tasks'
)
def
__unicode__
(
self
):
...
...
@@ -31,6 +30,7 @@ class Task(models.Model):
return
[]
def
run
(
self
):
from
ops.utils.ansible_api
import
ADHocRunner
,
Config
conf
=
Config
()
gather_facts
=
"yes"
if
self
.
is_gather_facts
else
"no"
play_source
=
{
...
...
@@ -55,4 +55,4 @@ class SubTask(models.Model):
register
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Ansible Task Register'
))
def
__unicode__
(
self
):
return
"
%
s
%
s"
%
(
self
.
module_name
,
self
.
module_args
)
\ No newline at end of file
return
"
%
s
%
s"
%
(
self
.
module_name
,
self
.
module_args
)
apps/ops/templates/cron/detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
apps/ops/templates/sudo/detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
apps/ops/templates/task/detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
apps/perms/templates/perms/asset_permission_asset.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -193,4 +191,4 @@
$
(
'.select2'
).
select2
();
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/perms/templates/perms/asset_permission_detail.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -268,4 +266,4 @@
removeSystemUser
(
$uid
,
$tr
)
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/perms/templates/perms/asset_permission_list.html
View file @
b0551449
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a
href=
"{% url 'perms:asset-permission-create' %}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create permission" %}
...
...
apps/perms/templates/perms/asset_permission_user.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
...
...
@@ -197,4 +195,4 @@
console
.
log
(
jumpserver
.
users_selected
)
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/static/css/jumpserver.css
View file @
b0551449
...
...
@@ -225,6 +225,7 @@ table.dataTable tbody td.selected td i.text-navy
background
:
#f1f1f1
;
margin-right
:
2px
;
}
.form-asset-on
{
border
:
1px
solid
#e5e6e7
;
padding-top
:
5px
;
...
...
@@ -263,4 +264,16 @@ div.dataTables_wrapper div.dataTables_filter,
div
.dataTables_wrapper
div
.dataTables_filter
{
margin-left
:
15px
;
}
\ No newline at end of file
}
.simple-tag
{
background-color
:
#f3f3f4
;
border
:
1px
solid
#e7eaec
;
border-radius
:
2px
;
color
:
inherit
;
display
:
inline-block
;
font-size
:
10px
;
margin-right
:
5px
;
margin-top
:
5px
;
padding
:
5px
12px
;
}
apps/templates/_base_list.html
View file @
b0551449
{% extends 'base.html' %}
{% load static %}
{% load common_tags %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
dataTables
/
dataTables
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
awesome-bootstrap-checkbox
/
awesome-bootstrap-checkbox
.
css
"
%}"
rel=
"stylesheet"
>
...
...
apps/templates/base.html
View file @
b0551449
...
...
@@ -24,9 +24,9 @@
{% block first_login_message %}
{% if user.is_authenticated and user.is_first_login %}
<div
class=
"alert alert-danger"
style=
"margin: 20px auto 0px"
>
{% url 'users:user-first-login' as
the
_url %}
{% url 'users:user-first-login' as
first_login
_url %}
{% blocktrans %}
Your information was incomplete. Please click
<a
href=
"{{
the
_url }}"
>
this link
</a>
to complete your information.
Your information was incomplete. Please click
<a
href=
"{{
first_login
_url }}"
>
this link
</a>
to complete your information.
{% endblocktrans %}
</div>
{% endif %}
...
...
@@ -34,8 +34,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-profile' as profile_url %}
{% blocktrans %}
Your ssh-public-key has been expired. Please click
<a
href=
"
#"
>
this link
</a>
to
update your ssh-public-key.
Your ssh-public-key has been expired. Please click
<a
href=
"
{{ profile_url }}"
>
this link
</a>
to
update your ssh-public-key.
{% endblocktrans %}
</div>
{% endif %}
...
...
apps/users/api.py
View file @
b0551449
# ~*~ coding: utf-8 ~*~
#
from
rest_framework
import
generics
,
viewsets
from
rest_framework
import
generics
from
rest_framework.permissions
import
AllowAny
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
rest_framework.permissions
import
AllowAny
from
rest_framework_bulk
import
BulkModelViewSet
# from django_filters.rest_framework import DjangoFilterBackend
from
.
import
serializers
from
.hands
import
write_login_log_async
from
.models
import
User
,
UserGroup
from
.permissions
import
IsSuperUser
,
IsValidUser
,
IsCurrentUserOrReadOnly
from
.utils
import
check_user_valid
,
generate_token
from
common.mixins
import
IDInFilterMixin
from
common.utils
import
get_logger
from
.utils
import
check_user_valid
,
generate_token
from
.models
import
User
,
UserGroup
from
.hands
import
write_login_log_async
from
.permissions
import
(
IsSuperUser
,
IsAppUser
,
IsValidUser
)
from
.
import
serializers
logger
=
get_logger
(
__name__
)
...
...
@@ -41,7 +38,7 @@ class UserResetPasswordApi(generics.UpdateAPIView):
def
perform_update
(
self
,
serializer
):
# Note: we are not updating the user object here.
# We just do the reset-password st
a
ff.
# We just do the reset-password st
u
ff.
import
uuid
from
.utils
import
send_reset_password_mail
user
=
self
.
get_object
()
...
...
@@ -65,6 +62,7 @@ class UserResetPKApi(generics.UpdateAPIView):
class
UserUpdatePKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
serializers
.
UserPKUpdateSerializer
permission_classes
=
(
IsCurrentUserOrReadOnly
,)
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
...
...
apps/users/models/user.py
View file @
b0551449
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import
os
from
collections
import
OrderedDict
from
django.conf
import
settings
from
django.contrib.auth.hashers
import
make_password
from
django.contrib.auth.models
import
AbstractUser
from
django.core
import
signing
from
django.conf
import
settings
from
django.db
import
models
,
IntegrityError
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
timezone
from
django.shortcuts
import
reverse
from
common.utils
import
signer
,
date_expired_default
from
.
import
UserGroup
from
common.utils
import
signer
,
date_expired_default
__all__
=
[
'User'
]
...
...
@@ -61,6 +62,15 @@ class User(AbstractUser):
def
get_absolute_url
(
self
):
return
reverse
(
'users:user-detail'
,
args
=
(
self
.
id
,))
def
is_public_key_valid
(
self
):
"""
Check if the user's ssh public key is valid.
This function is used in base.html.
"""
if
self
.
_public_key
:
return
True
return
False
@property
def
is_expired
(
self
):
if
self
.
date_expired
<
timezone
.
now
():
...
...
@@ -156,6 +166,17 @@ class User(AbstractUser):
return
True
return
False
def
avatar_url
(
self
):
if
self
.
avatar
:
return
self
.
avatar
.
url
else
:
default_dir
=
os
.
path
.
join
(
settings
.
MEDIA_ROOT
,
'avatar'
,
'default'
)
if
os
.
path
.
isdir
(
default_dir
):
default_avatar_list
=
os
.
listdir
(
default_dir
)
default_avatar
=
default_avatar_list
[
len
(
self
.
username
)
%
len
(
default_avatar_list
)]
return
os
.
path
.
join
(
settings
.
MEDIA_URL
,
'avatar'
,
'default'
,
default_avatar
)
return
'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
def
generate_reset_token
(
self
):
return
signer
.
sign_t
({
'reset'
:
self
.
id
,
'email'
:
self
.
email
},
expires_in
=
3600
)
...
...
apps/users/permissions.py
View file @
b0551449
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import
base64
from
django.core.cache
import
cache
from
django.conf
import
settings
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
authentication
,
exceptions
,
permissions
from
rest_framework.compat
import
is_authenticated
from
common.utils
import
signer
,
get_object_or_none
from
.hands
import
Terminal
from
.models
import
User
from
rest_framework
import
permissions
class
IsValidUser
(
permissions
.
IsAuthenticated
,
permissions
.
BasePermission
):
...
...
@@ -20,7 +9,7 @@ class IsValidUser(permissions.IsAuthenticated, permissions.BasePermission):
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsValidUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_valid
and
request
.
user
.
is_valid
class
IsAppUser
(
IsValidUser
,
permissions
.
BasePermission
):
...
...
@@ -28,7 +17,7 @@ class IsAppUser(IsValidUser, permissions.BasePermission):
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsAppUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_app
and
request
.
user
.
is_app
class
IsSuperUser
(
IsValidUser
,
permissions
.
BasePermission
):
...
...
@@ -36,7 +25,7 @@ class IsSuperUser(IsValidUser, permissions.BasePermission):
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsSuperUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_superuser
and
request
.
user
.
is_superuser
class
IsSuperUserOrAppUser
(
IsValidUser
,
permissions
.
BasePermission
):
...
...
@@ -44,8 +33,12 @@ class IsSuperUserOrAppUser(IsValidUser, permissions.BasePermission):
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsSuperUserOrAppUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
(
request
.
user
.
is_superuser
or
request
.
user
.
is_app
)
and
(
request
.
user
.
is_superuser
or
request
.
user
.
is_app
)
class
IsCurrentUserOrReadOnly
(
permissions
.
BasePermission
):
if
__name__
==
'__main__'
:
pass
def
has_object_permission
(
self
,
request
,
view
,
obj
):
if
request
.
method
in
permissions
.
SAFE_METHODS
:
return
True
return
obj
==
request
.
user
apps/users/templates/users/user_asset_permission.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load bootstrap %}
{% load static %}
{% load i18n %}
...
...
@@ -182,4 +180,4 @@
});
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/users/templates/users/user_detail.html
View file @
b0551449
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_granted_asset.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load bootstrap %}
{% load static %}
{% load i18n %}
...
...
@@ -155,4 +153,4 @@
jumpserver
.
initDataTable
(
options2
);
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/users/templates/users/user_group_asset_permission.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load bootstrap %}
{% load static %}
{% load i18n %}
...
...
@@ -180,4 +178,4 @@
console
.
log
(
'click excel'
)
})
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/users/templates/users/user_group_granted_asset.html
View file @
b0551449
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load bootstrap %}
{% load static %}
{% load i18n %}
...
...
@@ -155,4 +153,4 @@
jumpserver
.
initDataTable
(
options2
);
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
apps/users/templates/users/user_profile.html
0 → 100644
View file @
b0551449
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-6"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
class=
"label label-primary"
><b>
{{ user.name }}
</b></span>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<div
class=
"text-left"
>
<table
class=
"table"
>
<tr>
<td
class=
"text-navy"
>
用户名
</td>
<td>
{{ user.username }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
姓名
</td>
<td>
{{ user.name }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
权限
</td>
<td>
{{ user.get_role_display }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
Email
</td>
<td>
{{ user.email }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
激活
</td>
<td>
{{ user.is_active }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
添加日期
</td>
<td>
{{ user.date_joined|date:"Y-m-d H:i:s" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
最后登录
</td>
<td>
{{ user.last_login|date:"Y-m-d H:i:s" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
所在用户组
</td>
<td>
{% for group in user.groups.all %}
<span
class=
"simple-tag with-link"
>
<a
href=
"{% url 'users:user-group-detail' group.id %}"
>
{{ group.name }}
</a>
</span>
{% endfor %}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
授权主机数量
</td>
<td>
{{ assets | length }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
授权主机组
</td>
<td>
{% for group in asset_groups %}
<span
class=
"simple-tag with-link"
>
<a
href=
"{% url 'assets:asset-group-detail' group.id %}"
>
{{ group.name }}
</a>
</span>
{% endfor %}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
授权规则
</td>
<td>
{% for perm in permissions %}
<span
class=
"simple-tag with-link"
>
<a
href=
"{% url 'perms:asset-permission-detail' perm.id %}"
>
{{ perm.name }}
</a>
</span>
{% endfor %}
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div
class=
"col-sm-6"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
class=
"label label-primary"
><b>
{% trans "Update Public Key" %}
</b></span>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<p>
{% trans "Paste your SSH Public Key here" %}
</p>
<textarea
id=
"txt_pk"
class=
"form-control"
cols=
"30"
rows=
"10"
placeholder=
"ssh-rsa AAAAB3NzaC1yc2EAA....."
></textarea>
<button
id=
"btn_update_pk"
class=
"btn btn-primary m-t-15"
>
{% trans 'Update' %}
</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
on
(
'click'
,
'#btn_update_pk'
,
function
()
{
var
$this
=
$
(
this
);
var
pk
=
$
(
'#txt_pk'
).
val
();
var
the_url
=
'{% url "api-users:user-public-key-update" pk=user.id %}'
;
var
body
=
{
'_public_key'
:
pk
};
var
success
=
function
()
{
$
(
'#txt_pk'
).
val
(
''
);
var
msg
=
"{% trans 'Successfully updated the SSH public key.' %}"
;
swal
(
"{% trans 'User SSH Public Key Update' %}"
,
msg
,
"success"
);
};
var
fail
=
function
()
{
var
msg
=
"{% trans 'Failed to update SSH public key.' %}"
;
swal
({
title
:
"{% trans 'User SSH Public Key Update' %}"
,
text
:
msg
,
type
:
"error"
,
showCancelButton
:
false
,
confirmButtonColor
:
"#DD6B55"
,
confirmButtonText
:
"{% trans 'Confirm' %}"
,
closeOnConfirm
:
true
},
function
()
{
$
(
'#txt_pk'
).
focus
();
}
);
}
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
,
error
:
fail
});
})
</script>
{% endblock %}
apps/users/templatetags/__init__.py
deleted
100644 → 0
View file @
7825c107
apps/users/templatetags/users_tags.py
deleted
100644 → 0
View file @
7825c107
# ~*~ coding: utf-8 ~*~
import
os
import
urllib
import
hashlib
from
django
import
template
from
django.utils
import
timezone
from
django.conf
import
settings
register
=
template
.
Library
()
@register.filter
def
join_queryset_attr
(
queryset
,
attr
,
delimiter
=
', '
):
return
delimiter
.
join
([
getattr
(
obj
,
attr
,
''
)
for
obj
in
queryset
])
@register.filter
def
is_expired
(
datetime
):
if
datetime
>
timezone
.
now
():
return
False
else
:
return
True
@register.filter
def
user_avatar_url
(
user
):
if
user
.
avatar
:
return
user
.
avatar
.
url
else
:
default_dir
=
os
.
path
.
join
(
settings
.
MEDIA_ROOT
,
'avatar'
,
'default'
)
if
os
.
path
.
isdir
(
default_dir
):
default_avatar_list
=
os
.
listdir
(
default_dir
)
default_avatar
=
default_avatar_list
[
len
(
user
.
username
)
%
len
(
default_avatar_list
)]
return
os
.
path
.
join
(
settings
.
MEDIA_URL
,
'avatar'
,
'default'
,
default_avatar
)
return
'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
apps/users/urls/views_urls.py
View file @
b0551449
from
__future__
import
absolute_import
from
django.conf.urls
import
url
from
..
import
views
app_name
=
'users'
...
...
@@ -20,6 +21,11 @@ urlpatterns = [
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
# Profile
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
# User view
url
(
r'^user$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user/(?P<pk>[0-9]+)$'
,
views
.
UserDetailView
.
as_view
(),
...
...
apps/users/views/user.py
View file @
b0551449
# ~*~ coding: utf-8 ~*~
from
__future__
import
unicode_literals
import
uuid
import
json
import
uuid
from
django.shortcuts
import
redirect
from
openpyxl
import
load_workbook
from
openpyxl
import
Workbook
from
openpyxl.writer.excel
import
save_virtual_workbook
from
openpyxl
import
load_workbook
from
django
import
forms
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.core.cache
import
cache
from
django.http
import
HttpResponse
,
JsonResponse
from
django.
contrib.messages.views
import
SuccessMessageMixin
from
django.
shortcuts
import
redirect
from
django.urls
import
reverse_lazy
,
reverse
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext
as
_
...
...
@@ -19,22 +21,23 @@ from django.utils.decorators import method_decorator
from
django.views
import
View
from
django.views.generic
import
ListView
from
django.views.generic.base
import
TemplateView
from
django.views.generic.edit
import
CreateView
,
UpdateView
,
FormMixin
,
\
FormView
from
django.views.generic.edit
import
(
CreateView
,
UpdateView
,
FormMixin
,
FormView
)
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.views.decorators.csrf
import
csrf_exempt
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
perms.models
import
AssetPermission
from
..models
import
User
,
UserGroup
from
..utils
import
AdminUserRequiredMixin
,
user_add_success_next
from
..
import
forms
__all__
=
[
'UserListView'
,
'UserCreateView'
,
'UserDetailView'
,
'UserUpdateView'
,
'UserAssetPermissionCreateView'
,
'UserAssetPermissionView'
,
'UserGrantedAssetView'
,
'UserExportView'
,
'UserBulkImportView'
]
'UserExportView'
,
'UserBulkImportView'
,
'UserProfileView'
]
logger
=
get_logger
(
__name__
)
...
...
@@ -103,7 +106,7 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
class
UserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
User
template_name
=
'users/user_detail.html'
context_object_name
=
"user"
context_object_name
=
"user
_object
"
def
get_context_data
(
self
,
**
kwargs
):
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
...
...
@@ -134,18 +137,16 @@ class UserExportView(View):
ws
.
append
(
header
)
for
user
in
users
:
print
(
user
.
name
)
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
,
])
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
])
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
response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
return
response
def
post
(
self
,
request
):
...
...
@@ -303,4 +304,25 @@ class UserGrantedAssetView(AdminUserRequiredMixin, DetailView):
'action'
:
'User granted asset'
,
}
kwargs
.
update
(
context
)
return
super
(
UserGrantedAssetView
,
self
)
.
get_context_data
(
**
kwargs
)
\ No newline at end of file
return
super
(
UserGrantedAssetView
,
self
)
.
get_context_data
(
**
kwargs
)
class
UserProfileView
(
LoginRequiredMixin
,
TemplateView
):
template_name
=
'users/user_profile.html'
def
get_context_data
(
self
,
**
kwargs
):
from
perms.utils
import
(
get_user_granted_assets
,
get_user_granted_asset_groups
,
get_user_asset_permissions
)
assets
=
get_user_granted_assets
(
self
.
request
.
user
)
asset_groups
=
get_user_granted_asset_groups
(
self
.
request
.
user
)
permissions
=
get_user_asset_permissions
(
self
.
request
.
user
)
context
=
{
'app'
:
'User'
,
'action'
:
'User Profile'
,
'assets'
:
assets
,
'asset_groups'
:
asset_groups
,
'permissions'
:
permissions
}
kwargs
.
update
(
context
)
return
super
(
UserProfileView
,
self
)
.
get_context_data
(
**
kwargs
)
config_example.py
View file @
b0551449
...
...
@@ -81,6 +81,8 @@ class Config:
# EMAIL_USE_TLS = False # If port is 587, set True
# EMAIL_SUBJECT_PREFIX = '[Jumpserver] '
CAPTCHA_TEST_MODE
=
False
def
__init__
(
self
):
pass
...
...
@@ -121,4 +123,3 @@ config = {
}
env
=
'development'
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