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
6db76423
Commit
6db76423
authored
Nov 09, 2015
by
liuzheng712
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://git.coding.net/jumpserver/jumpserver
into NormalUserPageLZ
parents
cab34668
91b5d039
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
220 additions
and
131 deletions
+220
-131
connect.py
connect.py
+0
-0
views.py
jlog/views.py
+7
-2
jumpserver.conf
jumpserver.conf
+2
-2
models.py
jumpserver/models.py
+1
-0
settings.py
jumpserver/settings.py
+3
-3
views.py
jumpserver/views.py
+30
-18
user_api.py
juser/user_api.py
+1
-1
views.py
juser/views.py
+2
-1
run_websocket.py
run_websocket.py
+109
-39
log_online.html
templates/jlog/log_online.html
+27
-19
paginator.html
templates/paginator.html
+27
-43
setting.html
templates/setting.html
+11
-3
No files found.
connect.py
View file @
6db76423
This diff is collapsed.
Click to expand it.
jlog/views.py
View file @
6db76423
...
...
@@ -48,7 +48,8 @@ def log_list(request, offset):
contact_list
,
p
,
contacts
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
posts
,
request
)
web_monitor_uri
=
'
%
s/monitor'
%
web_socket_host
web_monitor_uri
=
'ws://
%
s/monitor'
%
web_socket_host
web_kill_uri
=
'http://
%
s/kill'
%
web_socket_host
return
render_to_response
(
'jlog/log_
%
s.html'
%
offset
,
locals
(),
context_instance
=
RequestContext
(
request
))
...
...
@@ -103,6 +104,10 @@ def log_record(request):
def
web_terminal
(
request
):
web_terminal_uri
=
'
%
s/terminal'
%
web_socket_host
#username = get_session.get('username', '')
token
=
request
.
COOKIES
.
get
(
'sessionid'
)
username
=
request
.
user
.
username
asset_name
=
'127.0.0.1'
web_terminal_uri
=
'ws://
%
s/terminal?username=
%
s&asset_name=
%
s&token=
%
s'
%
(
web_socket_host
,
username
,
asset_name
,
token
)
return
render_to_response
(
'jlog/web_terminal.html'
,
locals
())
jumpserver.conf
View file @
6db76423
...
...
@@ -23,7 +23,7 @@ root_pw = secret234
[
websocket
]
web_socket_host
=
ws
://
192
.
168
.
244
.
129
:
3000
web_socket_host
=
192
.
168
.
244
.
129
:
3000
[
mail
]
...
...
@@ -32,4 +32,4 @@ email_host = smtp.exmail.qq.com
email_port
=
25
email_host_user
=
noreply
@
jumpserver
.
org
email_host_password
=
jumpserver1234
email_use_tls
=
Fals
e
email_use_tls
=
Tru
e
jumpserver/models.py
View file @
6db76423
...
...
@@ -7,6 +7,7 @@ class Setting(models.Model):
name
=
models
.
CharField
(
max_length
=
100
)
default_user
=
models
.
CharField
(
max_length
=
100
,
null
=
True
,
blank
=
True
)
default_port
=
models
.
IntegerField
(
max_length
=
10
,
null
=
True
,
blank
=
True
)
default_password
=
models
.
CharField
(
max_length
=
100
,
null
=
True
,
blank
=
True
)
default_pri_key_path
=
models
.
CharField
(
max_length
=
100
,
null
=
True
,
blank
=
True
)
class
Meta
:
...
...
jumpserver/settings.py
View file @
6db76423
...
...
@@ -15,7 +15,7 @@ import getpass
config
=
ConfigParser
.
ConfigParser
()
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
))
BASE_DIR
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
)
))
config
.
read
(
os
.
path
.
join
(
BASE_DIR
,
'jumpserver.conf'
))
DB_HOST
=
config
.
get
(
'db'
,
'host'
)
...
...
@@ -25,11 +25,13 @@ DB_PASSWORD = config.get('db', 'password')
DB_DATABASE
=
config
.
get
(
'db'
,
'database'
)
AUTH_USER_MODEL
=
'juser.User'
# mail config
MAIL_ENABLE
=
config
.
get
(
'mail'
,
'mail_enable'
)
EMAIL_HOST
=
config
.
get
(
'mail'
,
'email_host'
)
EMAIL_PORT
=
config
.
get
(
'mail'
,
'email_port'
)
EMAIL_HOST_USER
=
config
.
get
(
'mail'
,
'email_host_user'
)
EMAIL_HOST_PASSWORD
=
config
.
get
(
'mail'
,
'email_host_password'
)
EMAIL_USE_TLS
=
config
.
getboolean
(
'mail'
,
'email_use_tls'
)
EMAIL_TIMEOUT
=
5
# ======== Log ==========
LOG
=
False
...
...
@@ -41,8 +43,6 @@ KEY = config.get('base', 'key')
LOGIN_NAME
=
getpass
.
getuser
()
# LDAP_ENABLE = CONF.getint('ldap', 'ldap_enable')
URL
=
config
.
get
(
'base'
,
'url'
)
MAIL_ENABLE
=
config
.
get
(
'mail'
,
'mail_enable'
)
MAIL_FROM
=
config
.
get
(
'mail'
,
'email_host_user'
)
log_dir
=
os
.
path
.
join
(
BASE_DIR
,
'logs'
)
log_level
=
config
.
get
(
'base'
,
'log'
)
web_socket_host
=
config
.
get
(
'websocket'
,
'web_socket_host'
)
...
...
jumpserver/views.py
View file @
6db76423
...
...
@@ -246,27 +246,39 @@ def Logout(request):
def
setting
(
request
):
header_title
,
path1
=
'项目设置'
,
'设置'
setting_
r
=
get_object
(
Setting
,
name
=
'default'
)
setting_
default
=
get_object
(
Setting
,
name
=
'default'
)
if
request
.
method
==
"POST"
:
username
=
request
.
POST
.
get
(
'username'
,
''
)
port
=
request
.
POST
.
get
(
'port'
,
''
)
private_key
=
request
.
POST
.
get
(
'key'
,
''
)
if
''
in
[
username
,
port
,
private_key
]:
return
HttpResponse
(
'所填内容不能为空'
)
else
:
settings
=
get_object
(
Setting
,
id
=
1
)
private_key_path
=
os
.
path
.
join
(
BASE_DIR
,
'keys'
,
'default'
,
'default_private_key.pem'
)
with
open
(
private_key_path
,
'w'
)
as
f
:
f
.
write
(
private_key
)
os
.
chmod
(
private_key_path
,
0600
)
if
settings
:
Setting
.
objects
.
filter
(
name
=
'default'
)
.
update
(
default_user
=
username
,
default_port
=
port
,
default_pri_key_path
=
private_key_path
)
setting_raw
=
request
.
POST
.
get
(
'setting'
,
''
)
if
setting_raw
==
'default'
:
username
=
request
.
POST
.
get
(
'username'
,
''
)
port
=
request
.
POST
.
get
(
'port'
,
''
)
password
=
request
.
POST
.
get
(
'password'
,
''
)
private_key
=
request
.
POST
.
get
(
'key'
,
''
)
if
''
in
[
username
,
port
]
and
(
''
in
password
or
''
in
private_key
):
return
HttpResponse
(
'所填内容不能为空, 且密码和私钥填一个'
)
else
:
setting_r
=
Setting
(
name
=
'default'
,
default_user
=
username
,
default_port
=
port
,
default_pri_key_path
=
private_key_path
)
.
save
()
private_key_path
=
os
.
path
.
join
(
BASE_DIR
,
'keys'
,
'default'
,
'default_private_key.pem'
)
if
private_key
:
with
open
(
private_key_path
,
'w'
)
as
f
:
f
.
write
(
private_key
)
os
.
chmod
(
private_key_path
,
0600
)
if
setting_default
:
if
password
!=
setting_default
.
default_password
:
password_encode
=
CRYPTOR
.
encrypt
(
password
)
else
:
password_encode
=
password
Setting
.
objects
.
filter
(
name
=
'default'
)
.
update
(
default_user
=
username
,
default_port
=
port
,
default_password
=
password_encode
,
default_pri_key_path
=
private_key_path
)
else
:
password_encode
=
CRYPTOR
.
encrypt
(
password
)
setting_r
=
Setting
(
name
=
'default'
,
default_user
=
username
,
default_port
=
port
,
default_password
=
password_encode
,
default_pri_key_path
=
private_key_path
)
.
save
()
msg
=
"设置成功"
return
my_render
(
'setting.html'
,
locals
(),
request
)
...
...
juser/user_api.py
View file @
6db76423
...
...
@@ -5,7 +5,7 @@ from subprocess import call
from
juser.models
import
AdminGroup
from
jumpserver.api
import
*
from
jumpserver.settings
import
BASE_DIR
from
jumpserver.settings
import
BASE_DIR
,
EMAIL_HOST_USER
as
MAIL_FROM
def
group_add_user
(
group
,
user_id
=
None
,
username
=
None
):
...
...
juser/views.py
View file @
6db76423
...
...
@@ -10,10 +10,11 @@ from django.contrib.auth.decorators import login_required
from
django.db.models
import
Q
from
django.template
import
RequestContext
from
django.db.models
import
ObjectDoesNotExist
from
jumpserver.settings
import
MAIL_FROM
,
MAIL_ENABLE
from
jumpserver.settings
import
EMAIL_HOST_USER
from
juser.user_api
import
*
from
jperm.perm_api
import
_public_perm_api
,
perm_user_api
,
user_permed
MAIL_FROM
=
EMAIL_HOST_USER
def
chg_role
(
request
):
role
=
{
'SU'
:
2
,
'GA'
:
1
,
'CU'
:
0
}
...
...
run_websocket.py
View file @
6db76423
# coding: utf-8
import
time
import
datetime
import
json
import
os
import
sys
import
os.path
import
threading
import
urllib
import
tornado.ioloop
import
tornado.options
...
...
@@ -13,6 +15,7 @@ import tornado.web
import
tornado.websocket
import
tornado.httpserver
import
tornado.gen
import
tornado.httpclient
from
tornado.websocket
import
WebSocketClosedError
from
tornado.options
import
define
,
options
...
...
@@ -21,9 +24,12 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE
# from gevent import monkey
# monkey.patch_all()
# import gevent
from
gevent.socket
import
wait_read
,
wait_write
# from gevent.socket import wait_read, wait_write
import
struct
,
fcntl
,
signal
,
socket
,
select
,
fnmatch
import
paramiko
from
connect
import
Tty
from
connect
import
TtyLog
,
Log
try
:
import
simplejson
as
json
...
...
@@ -35,6 +41,20 @@ define("port", default=3000, help="run on the given port", type=int)
define
(
"host"
,
default
=
'0.0.0.0'
,
help
=
"run port on"
,
type
=
str
)
def
require_auth
(
func
):
def
_deco
(
request
,
*
args
,
**
kwargs
):
username
=
request
.
get_argument
(
'username'
,
''
)
asset_name
=
request
.
get_argument
(
'asset_name'
,
''
)
token
=
request
.
get_argument
(
'token'
,
''
)
print
username
,
asset_name
,
token
client
=
tornado
.
httpclient
.
HTTPClient
()
# response = client.fetch('http://some/url') + urllib.urlencode({'username': username,
# 'asset_name': asset_name, 'token': token})
# return request.close()
return
func
(
request
,
*
args
,
**
kwargs
)
return
_deco
class
MyThread
(
threading
.
Thread
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
MyThread
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -92,6 +112,7 @@ class Application(tornado.web.Application):
handlers
=
[
(
r'/monitor'
,
MonitorHandler
),
(
r'/terminal'
,
WebTerminalHandler
),
(
r'/kill'
,
WebTerminalKillHandler
),
]
setting
=
{
...
...
@@ -115,6 +136,7 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
def
check_origin
(
self
,
origin
):
return
True
@require_auth
def
open
(
self
):
# 获取监控的path
self
.
file_path
=
self
.
get_argument
(
'file_path'
,
''
)
...
...
@@ -123,12 +145,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
threads
.
append
(
thread
)
self
.
stream
.
set_nodelay
(
True
)
print
len
(
MonitorHandler
.
threads
),
len
(
MonitorHandler
.
clients
)
def
on_message
(
self
,
message
):
self
.
write_message
(
'Connect WebSocket Success. <br/>'
)
# 监控日志,发生变动发向客户端
try
:
for
t
in
MonitorHandler
.
threads
:
if
t
.
is_alive
():
...
...
@@ -142,6 +158,12 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
print
len
(
MonitorHandler
.
threads
),
len
(
MonitorHandler
.
clients
)
def
on_message
(
self
,
message
):
# 监控日志,发生变动发向客户端
pass
def
on_close
(
self
):
# 客户端主动关闭
# self.close()
...
...
@@ -152,28 +174,55 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
class
WebTty
(
Tty
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
WebTty
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
login_type
=
'web'
self
.
ws
=
None
self
.
input_r
=
''
self
.
input_mode
=
False
class
WebTerminalKillHandler
(
tornado
.
web
.
RequestHandler
):
def
get
(
self
):
ws_id
=
self
.
get_argument
(
'id'
)
Log
.
objects
.
filter
(
id
=
ws_id
)
.
update
(
is_finished
=
True
)
for
ws
in
WebTerminalHandler
.
clients
:
print
ws
.
id
if
ws
.
id
==
int
(
ws_id
):
print
"killed"
ws
.
log
.
save
()
ws
.
close
()
print
len
(
WebTerminalHandler
.
clients
)
class
WebTerminalHandler
(
tornado
.
websocket
.
WebSocketHandler
):
tasks
=
[]
clients
=
[]
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
chan
=
None
self
.
ssh
=
None
self
.
term
=
None
self
.
channel
=
None
self
.
log_file_f
=
None
self
.
log_time_f
=
None
self
.
log
=
None
self
.
id
=
0
super
(
WebTerminalHandler
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
check_origin
(
self
,
origin
):
return
True
@require_auth
def
open
(
self
):
self
.
ssh
=
paramiko
.
SSHClient
()
self
.
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
try
:
self
.
ssh
.
connect
(
'127.0.0.1'
,
22
,
'root'
,
'redhat'
)
except
:
self
.
write_message
(
json
.
loads
({
'data'
:
'Connect server Error'
}))
self
.
close
()
self
.
chan
=
self
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
WebTerminalHandler
.
tasks
.
append
(
threading
.
Thread
(
target
=
self
.
_forward_outbound
))
asset_name
=
self
.
get_argument
(
'asset_name'
,
''
)
username
=
self
.
get_argument
(
'username'
,
''
)
token
=
self
.
get_argument
(
'token'
,
''
)
print
asset_name
,
username
,
token
self
.
term
=
WebTty
(
'a'
,
'b'
)
self
.
term
.
get_connection
()
self
.
channel
=
self
.
term
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
WebTerminalHandler
.
tasks
.
append
(
MyThread
(
target
=
self
.
forward_outbound
))
WebTerminalHandler
.
clients
.
append
(
self
)
for
t
in
WebTerminalHandler
.
tasks
:
if
t
.
is_alive
():
...
...
@@ -185,35 +234,56 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
data
=
json
.
loads
(
message
)
if
not
data
:
return
if
'resize'
in
data
:
self
.
chan
.
resize_pty
(
data
[
'resize'
]
.
get
(
'width'
,
80
),
data
[
'resize'
]
.
get
(
'height'
,
24
))
if
'data'
in
data
:
self
.
chan
.
send
(
data
[
'data'
])
if
data
.
get
(
'data'
):
self
.
term
.
input_mode
=
True
if
str
(
data
[
'data'
])
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
TtyLog
(
log
=
self
.
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
self
.
term
.
remove_control_char
(
self
.
term
.
input_r
))
.
save
()
self
.
term
.
input_r
=
''
self
.
term
.
input_mode
=
False
self
.
channel
.
send
(
data
[
'data'
])
def
on_close
(
self
):
self
.
write_message
(
json
.
dumps
({
'data'
:
'close websocket'
}))
print
'On_close'
if
self
in
WebTerminalHandler
.
clients
:
WebTerminalHandler
.
clients
.
remove
(
self
)
try
:
self
.
log_file_f
.
write
(
'End time is
%
s'
%
datetime
.
datetime
.
now
())
self
.
log
.
is_finished
=
True
self
.
log
.
end_time
=
datetime
.
datetime
.
now
()
self
.
log
.
save
()
self
.
close
()
except
AttributeError
:
pass
def
_forward_outbound
(
self
):
""" Forward outbound traffic (ssh -> websockets) """
def
forward_outbound
(
self
):
self
.
log_file_f
,
self
.
log_time_f
,
self
.
log
=
self
.
term
.
get_log_file
()
self
.
id
=
self
.
log
.
id
try
:
data
=
''
pre_timestamp
=
time
.
time
()
while
True
:
wait_read
(
self
.
chan
.
fileno
())
recv
=
self
.
chan
.
recv
(
1024
)
if
not
len
(
recv
):
return
data
+=
recv
try
:
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
data
=
''
except
UnicodeDecodeError
:
pass
r
,
w
,
e
=
select
.
select
([
self
.
channel
,
sys
.
stdin
],
[],
[])
if
self
.
channel
in
r
:
recv
=
self
.
channel
.
recv
(
1024
)
if
not
len
(
recv
):
return
data
+=
recv
try
:
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
now_timestamp
=
time
.
time
()
self
.
log_time_f
.
write
(
'
%
s
%
s
\n
'
%
(
round
(
now_timestamp
-
pre_timestamp
,
4
),
len
(
data
)))
self
.
log_file_f
.
write
(
data
)
pre_timestamp
=
now_timestamp
self
.
log_file_f
.
flush
()
self
.
log_time_f
.
flush
()
if
self
.
term
.
input_mode
and
not
self
.
term
.
is_output
(
data
):
self
.
term
.
input_r
+=
data
data
=
''
except
UnicodeDecodeError
:
pass
finally
:
self
.
close
()
if
__name__
==
'__main__'
:
tornado
.
options
.
parse_command_line
()
app
=
Application
()
...
...
templates/jlog/log_online.html
View file @
6db76423
...
...
@@ -50,7 +50,7 @@
<div
class=
"col-lg-12"
>
<div
class=
"ibox float-e-margins"
>
<div
id=
"ibox-content"
class=
"ibox-title"
>
<h5>
用户日志详细信息列表
</h5>
<h5>
用户日志详细信息列表
<
input
type=
"button"
id=
"test_connect"
class=
"btn btn-primary"
value=
"测试连接 web terminal"
/>
<
/h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
...
...
@@ -97,7 +97,7 @@
{% ifnotequal session_role_id 0 %}
<td
class=
"text-center"
><a
href=
"/jlog/history/?id={{ post.id }}"
class=
"log_command"
>
命令统计
</a></td>
<td
class=
"text-center"
><a
class=
"monitor"
file_path=
"{{ post.log_path }}"
>
监控
</a></td>
<td
class=
"text-center"
><input
type=
"button"
id=
"cut"
class=
"btn btn-danger btn-xs"
name=
"cut"
value=
"阻断"
onclick=
'cut("{{ post.pid }}")'
/></td>
<td
class=
"text-center"
><input
type=
"button"
id=
"cut"
class=
"btn btn-danger btn-xs"
name=
"cut"
value=
"阻断"
onclick=
'cut("{{ post.pid }}"
, "{{ post.remote_ip }}"
)'
/></td>
{% endifnotequal %}
<td
class=
"text-center"
id=
"start_time"
>
{{ post.start_time|date:"Y-m-d H:i:s" }}
</td>
</tr>
...
...
@@ -127,8 +127,20 @@
var
file_path
=
obj
.
attr
(
'file_path'
);
var
wsUri
=
'{{ web_monitor_uri }}'
;
var
socket
=
new
WebSocket
(
wsUri
+
'?file_path='
+
file_path
);
var
term
=
new
Terminal
({
cols
:
80
,
rows
:
24
,
screenKeys
:
false
});
var
tag
=
$
(
'<div id="term" style="height:500px; overflow: auto;background-color: rgba(0, 0, 0, 0);border: none"></div>'
);
term
.
open
();
term
.
resize
(
80
,
24
);
socket
.
onopen
=
function
(
evt
){
socket
.
send
(
file_path
)
socket
.
send
(
'hello'
);
term
.
write
(
'~.~ Connect WebSocket Success.~.~
\
r
\
n'
);
};
window
.
onbeforeunload
=
function
(){
...
...
@@ -138,29 +150,15 @@
var
username
=
obj
.
closest
(
'tr'
).
find
(
'#username'
).
text
();
var
ip
=
obj
.
closest
(
'tr'
).
find
(
'#ip'
).
text
();
BootstrapDialog
.
show
({
message
:
function
(){
//服务器端认证
{
#
socket
.
send
(
'login'
,
{
userid
:
message
.
id
,
filename
:
message
.
filename
,
username
:
username
,
seed
:
seed
});
#
}
var
term
=
new
Terminal
({
cols
:
80
,
rows
:
24
,
screenKeys
:
false
});
var
tag
=
$
(
'<div id="term" style="height:500px; overflow: auto;background-color: rgba(0, 0, 0, 0);border: none"></div>'
);
term
.
open
();
term
.
resize
(
80
,
24
);
window
.
setTimeout
(
function
(){
$
(
'.terminal'
).
detach
().
appendTo
(
'#term'
);
socket
.
onmessage
=
function
(
evt
){
term
.
write
(
evt
.
data
);
}},
1000
);
tag
[
0
].
style
.
color
=
"#00FF00"
;
return
tag
[
0
];
}
,
title
:
'Jumpserver实时监控 '
+
' 登录用户名: '
+
'<span class="text-info">'
+
username
+
'</span>'
+
' 登录主机: '
+
'<span class="text-info">'
+
ip
,
...
...
@@ -190,6 +188,10 @@
}});
return
false
;
});
$
(
'#test_connect'
).
click
(
function
(){
window
.
open
(
'/jlog/web_terminal/?asset_name="hello'
,
'播放'
,
'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'
);
});
});
{
#
function
log_search
(){
#
}
...
...
@@ -204,8 +206,14 @@
{
#
}
#
}
function
cut
(
num
){
var
g_url
=
"/jlog/log_kill/?id="
+
num
;
function
cut
(
num
,
host
){
console
.
log
(
host
);
if
(
host
==
'Web'
){
var
g_url
=
'{{ web_kill_uri }}'
+
'?id='
+
num
;
}
else
{
g_url
=
"/jlog/log_kill/?id="
+
num
;
}
$
.
ajax
({
type
:
"GET"
,
url
:
g_url
,
...
...
templates/paginator.html
View file @
6db76423
<div
class=
"col-sm-6"
>
<div
class=
"dataTables_paginate paging_simple_numbers"
id=
"editable_paginate"
>
<ul
class=
"pagination"
style=
"margin-top: 0; float: right"
>
{% if keyword %}
{% if contacts.has_previous %}
<li
class=
"paginate_button previous"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"?keyword={{ keyword }}&
page={{ contacts.previous_page_number }}"
>
Previous
</a>
<a
class=
"page"
href=
"?
page={{ contacts.previous_page_number }}"
>
Previous
</a>
</li>
{% else %}
<li
class=
"paginate_button previous disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"#"
>
Previous
</a>
<a
class=
"page"
href=
"#"
>
Previous
</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?keyword={{ keyword }}&
page=1"
title=
"第1页"
>
1...
</a></li>
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
class=
"page"
href=
"?
page=1"
title=
"第1页"
>
1...
</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li
class=
"paginate_button active"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?keyword={{ keyword }}&
page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
<li
class=
"paginate_button active"
aria-controls=
"editable"
tabindex=
"0"
><a
class=
"page"
href=
"?
page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% else %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?keyword={{ keyword }}&
page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
class=
"page"
href=
"?
page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?keyword={{ keyword }}&
page={{ p.num_pages }}"
title=
"第{{ page }}页"
>
...{{ p.num_pages }}
</a></li>
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
class=
"page"
href=
"?
page={{ p.num_pages }}"
title=
"第{{ page }}页"
>
...{{ p.num_pages }}
</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li
class=
"paginate_button next"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"?keyword={{ keyword }}&
page={{ contacts.next_page_number }}"
>
Next
</a>
<a
class=
"page"
href=
"?
page={{ contacts.next_page_number }}"
>
Next
</a>
</li>
{% else %}
<li
class=
"paginate_button next disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"#"
>
Next
</a>
<a
class=
"page"
href=
"#"
>
Next
</a>
</li>
{% endif %}
{% else %}
{% if contacts.has_previous %}
<li
class=
"paginate_button previous"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"?page={{ contacts.previous_page_number }}"
>
Previous
</a>
</li>
{% else %}
<li
class=
"paginate_button previous disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"#"
>
Previous
</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page=1"
title=
"第1页"
>
1...
</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li
class=
"paginate_button active"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% else %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ p.num_pages }}"
title=
"第{{ page }}页"
>
...{{ p.num_pages }}
</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li
class=
"paginate_button next"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"?page={{ contacts.next_page_number }}"
>
Next
</a>
</li>
{% else %}
<li
class=
"paginate_button next disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"#"
>
Next
</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>
</div>
<script>
$
(
document
).
ready
(
function
(){
$
(
'.page'
).
click
(
function
(){
var
searchStr
=
location
.
search
;
var
old_href
=
$
(
this
).
attr
(
'href'
).
replace
(
'?'
,
''
);
var
searchArray
=
searchStr
.
split
(
'&'
);
if
(
searchStr
.
indexOf
(
'page'
)){
searchArray
.
pop
();
}
searchArray
.
push
(
old_href
);
if
(
searchArray
.
length
>
2
){
$
(
this
).
attr
(
'href'
,
searchArray
.
join
(
'&'
));
}
})
});
</script>
templates/setting.html
View file @
6db76423
...
...
@@ -46,20 +46,28 @@
{% endif %}
<div
class=
"form-group"
>
<label
for=
"username"
class=
"col-sm-2 control-label"
>
默认用户名
<span
class=
"red-fonts"
>
*
</span></label>
<input
name=
"setting"
value=
"default"
style=
"display: none"
>
<div
class=
"col-sm-8"
>
<input
id=
"username"
name=
"username"
placeholder=
"Username"
type=
"text"
value=
"{{ setting_
r
.default_user }}"
class=
"form-control"
>
<input
id=
"username"
name=
"username"
placeholder=
"Username"
type=
"text"
value=
"{{ setting_
default
.default_user }}"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"port"
class=
"col-sm-2 control-label"
>
默认ssh端口
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<input
id=
"port"
name=
"port"
placeholder=
"Port"
type=
"text"
value=
"{{ setting_
r
.default_port }}"
class=
"form-control"
>
<input
id=
"port"
name=
"port"
placeholder=
"Port"
type=
"text"
value=
"{{ setting_
default
.default_port }}"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"key"
class=
"col-sm-2 control-label"
>
默认密钥
<span
class=
"red-fonts"
>
*
</span></label>
<label
for=
"key"
class=
"col-sm-2 control-label"
>
默认密码
</label>
<div
class=
"col-sm-8"
>
<input
id=
"password"
name=
"password"
placeholder=
"Password"
type=
"password"
value=
"{{ setting_default.default_password }}"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"key"
class=
"col-sm-2 control-label"
>
默认密钥
</label>
<div
class=
"col-sm-8"
>
<textarea
class=
"form-control"
name=
"key"
placeholder=
"请复制粘贴私钥(原来的因为安全原因不被显示)"
rows=
"10"
style=
"font-size: 9px;"
></textarea>
</div>
...
...
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