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
9aae1069
Commit
9aae1069
authored
Mar 22, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of github.com:jumpserver/jumpserver into dev
parents
c82044f6
e4e6f595
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
142 additions
and
7 deletions
+142
-7
models.py
apps/audits/models.py
+18
-0
login_log_list.html
apps/audits/templates/audits/login_log_list.html
+49
-7
view_urls.py
apps/audits/urls/view_urls.py
+1
-0
utils.py
apps/audits/utils.py
+23
-0
views.py
apps/audits/views.py
+51
-0
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
No files found.
apps/audits/models.py
View file @
9aae1069
import
uuid
from
django.db
import
models
from
django.db.models
import
Q
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
timezone
...
...
@@ -100,5 +101,22 @@ class UserLoginLog(models.Model):
status
=
models
.
BooleanField
(
max_length
=
2
,
default
=
True
,
choices
=
STATUS_CHOICE
,
verbose_name
=
_
(
'Status'
))
datetime
=
models
.
DateTimeField
(
default
=
timezone
.
now
,
verbose_name
=
_
(
'Date login'
))
@classmethod
def
get_login_logs
(
cls
,
date_form
=
None
,
date_to
=
None
,
user
=
None
,
keyword
=
None
):
login_logs
=
cls
.
objects
.
all
()
if
date_form
and
date_to
:
login_logs
=
login_logs
.
filter
(
datetime__gt
=
date_form
,
datetime__lt
=
date_to
)
if
user
:
login_logs
=
login_logs
.
filter
(
username
=
user
)
if
keyword
:
login_logs
=
login_logs
.
filter
(
Q
(
ip__contains
=
keyword
)
|
Q
(
city__contains
=
keyword
)
|
Q
(
username__contains
=
keyword
)
)
return
login_logs
class
Meta
:
ordering
=
[
'-datetime'
,
'username'
]
apps/audits/templates/audits/login_log_list.html
View file @
9aae1069
...
...
@@ -17,10 +17,10 @@
<div
class=
"form-group"
id=
"date"
>
<div
class=
"input-daterange input-group"
id=
"datepicker"
>
<span
class=
"input-group-addon"
><i
class=
"fa fa-calendar"
></i></span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_from"
value=
"{{ date_from|date:'Y-m-d'}}"
>
<input
type=
"text"
id=
"id_date_from"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_from"
value=
"{{ date_from|date:'Y-m-d'}}"
>
{#
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_from"
>
#}
<span
class=
"input-group-addon"
>
to
</span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_to"
value=
"{{ date_to|date:'Y-m-d'}}"
>
<input
type=
"text"
id=
"id_date_to"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_to"
value=
"{{ date_to|date:'Y-m-d'}}"
>
</div>
</div>
<div
class=
"input-group"
>
...
...
@@ -32,7 +32,7 @@
</select>
</div>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"keyword"
placeholder=
"{% trans 'Search' %}"
value=
"{{ keyword }}"
>
<input
type=
"text"
id=
"search"
class=
"form-control input-sm"
name=
"keyword"
placeholder=
"{% trans 'Search' %}"
value=
"{{ keyword }}"
>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group-btn"
>
...
...
@@ -43,8 +43,10 @@
</div>
</form>
{% endblock %}
{% block table_head %}
{% block table_container %}
<table
class=
"table table-striped table-bordered table-hover "
id=
"login_log_table"
>
<thead>
<tr>
<th
class=
"text-center"
>
{% trans 'ID' %}
</th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</th>
<th
class=
"text-center"
>
{% trans 'Type' %}
</th>
...
...
@@ -55,9 +57,10 @@
<th
class=
"text-center"
>
{% trans 'Reason' %}
</th>
<th
class=
"text-center"
>
{% trans 'Status' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date' %}
</th>
{% endblock %}
</tr>
<thead>
{% block table_body %}
<tbody>
{% for login_log in object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ forloop.counter }}
</td>
...
...
@@ -74,8 +77,24 @@
<td
class=
"text-center"
>
{{ login_log.datetime }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div
id=
"actions"
class=
""
style=
"margin-top: -20px"
>
<div
class=
"input-group"
>
<select
class=
"form-control m-b"
style=
"width: auto"
id=
"slct_bulk_update"
>
<option
value=
"export"
>
{% trans 'Export login log' %}
</option>
</select>
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<button
id=
'btn_bulk_update'
style=
"height: 32px;"
class=
"btn btn-sm btn-primary btn_export"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
<script>
...
...
@@ -95,6 +114,29 @@
width
:
'auto'
});
})
.
on
(
'click'
,
'.btn_export'
,
function
()
{
var
date_form
=
$
(
'#id_date_from'
).
val
();
var
date_to
=
$
(
'#id_date_to'
).
val
();
var
user
=
$
(
'.select2 option:selected'
).
val
();
var
keyword
=
$
(
'#search'
).
val
();
$
.
ajax
({
url
:
"{% url "
audits
:
login
-
log
-
export
" %}"
,
method
:
'POST'
,
data
:
JSON
.
stringify
({
'date_form'
:
date_form
,
'date_to'
:
date_to
,
'user'
:
user
,
'keyword'
:
keyword
}),
dataType
:
"json"
,
success
:
function
(
data
,
textStatus
)
{
window
.
open
(
data
.
redirect
)
},
error
:
function
()
{
toastr
.
error
(
'Export failed'
);
}
})
})
</script>
{% endblock %}
apps/audits/urls/view_urls.py
View file @
9aae1069
...
...
@@ -14,4 +14,5 @@ urlpatterns = [
path
(
'operate-log/'
,
views
.
OperateLogListView
.
as_view
(),
name
=
'operate-log-list'
),
path
(
'password-change-log/'
,
views
.
PasswordChangeLogList
.
as_view
(),
name
=
'password-change-log-list'
),
path
(
'command-execution-log/'
,
views
.
CommandExecutionListView
.
as_view
(),
name
=
'command-execution-log-list'
),
path
(
'login-log/export/'
,
views
.
LoginLogExportView
.
as_view
(),
name
=
'login-log-export'
),
]
apps/audits/utils.py
0 → 100644
View file @
9aae1069
import
csv
import
codecs
from
django.http
import
HttpResponse
def
get_excel_response
(
filename
):
excel_response
=
HttpResponse
(
content_type
=
'text/csv'
)
excel_response
[
'Content-Disposition'
]
=
'attachment; filename="
%
s"'
%
filename
excel_response
.
write
(
codecs
.
BOM_UTF8
)
return
excel_response
def
write_content_to_excel
(
response
,
header
=
None
,
login_logs
=
None
,
fields
=
None
):
writer
=
csv
.
writer
(
response
,
dialect
=
'excel'
,
quoting
=
csv
.
QUOTE_MINIMAL
)
if
header
:
writer
.
writerow
(
header
)
if
login_logs
:
for
log
in
login_logs
:
data
=
[
getattr
(
log
,
field
.
name
)
for
field
in
fields
]
writer
.
writerow
(
data
)
return
response
\ No newline at end of file
apps/audits/views.py
View file @
9aae1069
import
csv
import
json
import
uuid
import
codecs
from
django.conf
import
settings
from
django.urls
import
reverse
from
django.utils
import
timezone
from
django.core.cache
import
cache
from
django.http
import
HttpResponse
,
JsonResponse
from
django.utils.decorators
import
method_decorator
from
django.views
import
View
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.generic
import
ListView
from
django.utils.translation
import
ugettext
as
_
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.db.models
import
Q
from
audits.utils
import
get_excel_response
,
write_content_to_excel
from
common.mixins
import
DatetimeSearchMixin
from
common.permissions
import
AdminUserRequiredMixin
...
...
@@ -232,3 +247,38 @@ class CommandExecutionListView(UserCommandExecutionListView):
}
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
@method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
LoginLogExportView
(
LoginRequiredMixin
,
View
):
def
get
(
self
,
request
):
fields
=
[
field
for
field
in
UserLoginLog
.
_meta
.
fields
]
filename
=
'login-logs-{}.csv'
.
format
(
timezone
.
localtime
(
timezone
.
now
())
.
strftime
(
'
%
Y-
%
m-
%
d_
%
H-
%
M-
%
S'
)
)
excel_response
=
get_excel_response
(
filename
)
header
=
[
field
.
verbose_name
for
field
in
fields
]
login_logs
=
cache
.
get
(
request
.
GET
.
get
(
'spm'
,
''
),
[])
response
=
write_content_to_excel
(
excel_response
,
login_logs
=
login_logs
,
header
=
header
,
fields
=
fields
)
return
response
def
post
(
self
,
request
):
try
:
date_form
=
json
.
loads
(
request
.
body
)
.
get
(
'date_form'
,
[])
date_to
=
json
.
loads
(
request
.
body
)
.
get
(
'date_to'
,
[])
user
=
json
.
loads
(
request
.
body
)
.
get
(
'user'
,
[])
keyword
=
json
.
loads
(
request
.
body
)
.
get
(
'keyword'
,
[])
login_logs
=
UserLoginLog
.
get_login_logs
(
date_form
=
date_form
,
date_to
=
date_to
,
user
=
user
,
keyword
=
keyword
)
except
ValueError
:
return
HttpResponse
(
'Json object not valid'
,
status
=
400
)
spm
=
uuid
.
uuid4
()
.
hex
cache
.
set
(
spm
,
login_logs
,
300
)
url
=
reverse
(
'audits:login-log-export'
)
+
'?spm=
%
s'
%
spm
return
JsonResponse
({
'redirect'
:
url
})
\ No newline at end of file
apps/locale/zh/LC_MESSAGES/django.mo
View file @
9aae1069
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
9aae1069
This diff is collapsed.
Click to expand it.
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