Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
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
coco
Commits
cb232113
Commit
cb232113
authored
Nov 10, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改搜索查询的逻辑
parent
cc3b4d7b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
67 additions
and
36 deletions
+67
-36
char.py
coco/char.py
+1
-0
forward.py
coco/forward.py
+1
-3
interactive.py
coco/interactive.py
+61
-33
models.py
coco/models.py
+4
-0
No files found.
coco/char.py
View file @
cb232113
...
@@ -5,3 +5,4 @@ ENTER_CHAR = [b'\r', b'\n', b'\r\n']
...
@@ -5,3 +5,4 @@ ENTER_CHAR = [b'\r', b'\n', b'\r\n']
UNSUPPORTED_CHAR
=
{
b
'
\x15
'
:
'Ctrl-U'
,
b
'
\x0c
'
:
'Ctrl-L'
,
b
'
\x05
'
:
'Ctrl-E'
}
UNSUPPORTED_CHAR
=
{
b
'
\x15
'
:
'Ctrl-U'
,
b
'
\x0c
'
:
'Ctrl-L'
,
b
'
\x05
'
:
'Ctrl-E'
}
CLEAR_CHAR
=
b
'
\x1b
[H
\x1b
[2J'
CLEAR_CHAR
=
b
'
\x1b
[H
\x1b
[2J'
BELL_CHAR
=
b
'
\x07
'
BELL_CHAR
=
b
'
\x07
'
NEW_LINE
=
b
'
\r\n
'
coco/forward.py
View file @
cb232113
...
@@ -67,7 +67,6 @@ class ProxyServer:
...
@@ -67,7 +67,6 @@ class ProxyServer:
except
paramiko
.
AuthenticationException
as
e
:
except
paramiko
.
AuthenticationException
as
e
:
self
.
client
.
send
(
"[Errno 66] Authentication failed: {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
self
.
client
.
send
(
"[Errno 66] Authentication failed: {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
return
None
return
None
except
socket
.
error
as
e
:
except
socket
.
error
as
e
:
self
.
client
.
send
(
" {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
self
.
client
.
send
(
" {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
return
None
return
None
...
@@ -97,12 +96,11 @@ class ProxyServer:
...
@@ -97,12 +96,11 @@ class ProxyServer:
def
send_connecting_message
(
self
):
def
send_connecting_message
(
self
):
def
func
():
def
func
():
delay
=
0.0
delay
=
0.0
self
.
client
.
send
(
'Connecting to {} {:.1f}'
.
format
(
'abc.com'
,
delay
)
.
encode
(
'utf-8'
))
self
.
client
.
send
(
'Connecting to {} {:.1f}'
.
format
(
self
.
server
,
delay
)
.
encode
(
'utf-8'
))
while
self
.
connecting
and
delay
<
TIMEOUT
:
while
self
.
connecting
and
delay
<
TIMEOUT
:
self
.
client
.
send
(
'
\x08\x08\x08
{:.1f}'
.
format
(
delay
)
.
encode
(
'utf-8'
))
self
.
client
.
send
(
'
\x08\x08\x08
{:.1f}'
.
format
(
delay
)
.
encode
(
'utf-8'
))
time
.
sleep
(
0.1
)
time
.
sleep
(
0.1
)
delay
+=
0.1
delay
+=
0.1
thread
=
threading
.
Thread
(
target
=
func
)
thread
=
threading
.
Thread
(
target
=
func
)
thread
.
daemon
=
True
thread
.
start
()
thread
.
start
()
coco/interactive.py
View file @
cb232113
...
@@ -4,7 +4,7 @@ import socket
...
@@ -4,7 +4,7 @@ import socket
import
threading
import
threading
# Todo remove
# Todo remove
from
jms.models
import
Asset
,
SystemUser
from
jms.models
import
Asset
,
SystemUser
,
AssetGroup
from
.
import
char
from
.
import
char
from
.utils
import
wrap_with_line_feed
as
wr
,
wrap_with_title
as
title
,
\
from
.utils
import
wrap_with_line_feed
as
wr
,
wrap_with_title
as
title
,
\
...
@@ -26,23 +26,26 @@ class InteractiveServer:
...
@@ -26,23 +26,26 @@ class InteractiveServer:
self
.
search_result
=
None
self
.
search_result
=
None
self
.
asset_groups
=
None
self
.
asset_groups
=
None
self
.
get_user_assets_async
()
self
.
get_user_assets_async
()
self
.
get_user_asset_groups_async
()
def
display_banner
(
self
):
def
display_banner
(
self
):
self
.
client
.
send
(
char
.
CLEAR_CHAR
)
self
.
client
.
send
(
char
.
CLEAR_CHAR
)
banner
=
u
"""
\n
{title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}
\r\n\r
banner
=
"""
\n
{title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}
\r\n\r
1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进行搜索登录(如果唯一).
\r
1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进行搜索登录(如果唯一).
\r
2) 输入 {green}/{end} + {green}IP, 主机名 or 备注 {end}搜索. 如: /ip
\r
2) 输入 {green}/{end} + {green}IP, 主机名 or 备注 {end}搜索. 如: /ip
\r
3) 输入 {green}P/p{end} 显示您有权限的主机.
\r
3) 输入 {green}P/p{end} 显示您有权限的主机.
\r
4) 输入 {green}G/g{end} 显示您有权限的主机组.
\r
4) 输入 {green}G/g{end} 显示您有权限的主机组.
\r
5) 输入 {green}G/g{end}
{end}
+ {green}组ID{end} 显示该组下主机. 如: g1
\r
5) 输入 {green}G/g{end} + {green}组ID{end} 显示该组下主机. 如: g1
\r
6) 输入 {green}E/e{end} 批量执行命令.(未完成)
\r
6) 输入 {green}E/e{end} 批量执行命令.(未完成)
\r
7) 输入 {green}U/u{end} 批量上传文件.(未完成)
\r
7) 输入 {green}U/u{end} 批量上传文件.(未完成)
\r
8) 输入 {green}D/d{end} 批量下载文件.(未完成)
\r
8) 输入 {green}D/d{end} 批量下载文件.(未完成)
\r
9) 输入 {green}H/h{end} 帮助.
\r
9) 输入 {green}H/h{end} 帮助.
\r
0) 输入 {green}Q/q{end} 退出.
\r\n
"""
.
format
(
0) 输入 {green}Q/q{end} 退出.
\r\n
"""
.
format
(
title
=
"
\033
[1;32m"
,
green
=
"
\033
[32m"
,
end
=
"
\033
[0m"
,
user
=
self
.
client
.
user
)
title
=
"
\033
[1;32m"
,
green
=
"
\033
[32m"
,
self
.
client
.
send
(
banner
.
encode
(
'utf-8'
))
end
=
"
\033
[0m"
,
user
=
self
.
client
.
user
)
self
.
client
.
send
(
banner
)
def
get_choice
(
self
,
prompt
=
b
'Opt> '
):
def
get_choice
(
self
,
prompt
=
b
'Opt> '
):
"""实现了一个ssh input, 提示用户输入, 获取并返回
"""实现了一个ssh input, 提示用户输入, 获取并返回
...
@@ -92,42 +95,48 @@ class InteractiveServer:
...
@@ -92,42 +95,48 @@ class InteractiveServer:
input_data
.
append
(
data
)
input_data
.
append
(
data
)
def
dispatch
(
self
,
opt
):
def
dispatch
(
self
,
opt
):
if
opt
i
n
[
'q'
,
'Q'
,
'0'
]
:
if
opt
i
s
None
:
self
.
app
.
remove_client
(
self
.
client
)
return
elif
opt
in
[
'h'
,
'H'
,
'9'
]
:
elif
opt
.
startswith
(
"/"
)
:
self
.
display_banner
(
)
self
.
search_and_display
(
opt
.
lstrip
(
"/"
)
)
elif
opt
in
[
'p'
,
'P'
,
'3'
]:
elif
opt
in
[
'p'
,
'P'
,
'3'
]:
self
.
display_assets
()
self
.
display_assets
()
elif
opt
in
[
'g'
,
'G'
,
'
5
'
]:
elif
opt
in
[
'g'
,
'G'
,
'
4
'
]:
self
.
display_asset_groups
()
self
.
display_asset_groups
()
elif
opt
.
startswith
(
"g"
)
and
opt
.
lstrip
(
"g"
)
.
isdigit
():
self
.
display_group_assets
(
int
(
opt
.
lstrip
(
"g"
)))
elif
opt
in
[
'q'
,
'Q'
,
'0'
]:
self
.
app
.
remove_client
(
self
.
client
)
elif
opt
in
[
'h'
,
'H'
,
'9'
]:
self
.
display_banner
()
else
:
else
:
self
.
search_and_proxy
(
opt
)
self
.
search_and_proxy
(
opt
)
def
search_assets
(
self
,
q
,
from_result
=
False
):
def
search_assets
(
self
,
q
):
if
self
.
assets
is
None
:
if
self
.
assets
is
None
:
self
.
get_user_assets
()
self
.
get_user_assets
()
if
from_result
:
source
=
self
.
search_result
else
:
source
=
self
.
assets
result
=
[]
result
=
[]
# 所有的
if
q
==
''
:
result
=
self
.
assets
# 用户输入的是数字,可能想使用id唯一键搜索
# 用户输入的是数字,可能想使用id唯一键搜索
if
q
.
isdigit
():
el
if
q
.
isdigit
():
if
len
(
s
ource
)
>
int
(
q
):
if
len
(
s
elf
.
search_result
)
>=
int
(
q
):
result
=
[
s
ource
[
q
-
1
]]
result
=
[
s
elf
.
search_result
[
int
(
q
)
-
1
]]
# 全匹配
则直接返回
# 全匹配
到则直接返回全匹配的
if
len
(
result
)
==
0
:
if
len
(
result
)
==
0
:
_result
=
[
asset
for
asset
in
s
ource
if
is_obj_attr_eq
(
asset
,
q
)]
_result
=
[
asset
for
asset
in
s
elf
.
assets
if
is_obj_attr_eq
(
asset
,
q
)]
if
len
(
_result
)
==
1
:
if
len
(
_result
)
==
1
:
result
=
_result
result
=
_result
# 最后模糊匹配
# 最后模糊匹配
if
len
(
result
)
==
0
:
if
len
(
result
)
==
0
:
result
=
[
asset
for
asset
in
s
ource
if
is_obj_attr_has
(
asset
,
q
)]
result
=
[
asset
for
asset
in
s
elf
.
assets
if
is_obj_attr_has
(
asset
,
q
)]
self
.
search_result
=
sort_assets
(
result
,
self
.
app
.
config
[
"ASSET_LIST_SORT_BY"
])
self
.
search_result
=
result
def
display_assets
(
self
):
def
display_assets
(
self
):
"""
"""
...
@@ -136,35 +145,57 @@ class InteractiveServer:
...
@@ -136,35 +145,57 @@ class InteractiveServer:
"""
"""
self
.
search_and_display
(
''
)
self
.
search_and_display
(
''
)
def
display_group_assets
(
self
):
def
display_asset_groups
(
self
):
pass
if
self
.
asset_groups
is
None
:
self
.
get_user_asset_groups
()
if
len
(
self
.
asset_groups
)
==
0
:
self
.
client
.
send
(
warning
(
"Nothing"
))
return
fake_group
=
AssetGroup
(
name
=
"Name"
,
assets_amount
=
"Assets"
,
comment
=
"Comment"
)
id_max_length
=
max
(
len
(
str
(
len
(
self
.
asset_groups
))),
5
)
name_max_length
=
max
(
max
([
len
(
group
.
name
)
for
group
in
self
.
asset_groups
]),
15
)
amount_max_length
=
max
(
len
(
str
(
max
([
group
.
assets_amount
for
group
in
self
.
asset_groups
]))),
10
)
header
=
'{1:>
%
d} {0.name:
%
d} {0.assets_amount:<
%
s} '
%
(
id_max_length
,
name_max_length
,
amount_max_length
)
comment_length
=
self
.
request
.
meta
[
"width"
]
-
len
(
header
.
format
(
fake_group
,
id_max_length
))
line
=
header
+
'{0.comment:
%
s}'
%
(
comment_length
/
2
)
# comment中可能有中文
header
+=
"{0.comment:
%
s}"
%
comment_length
self
.
client
.
send
(
title
(
header
.
format
(
fake_group
,
"ID"
)))
for
index
,
group
in
enumerate
(
self
.
asset_groups
):
self
.
client
.
send
(
wr
(
line
.
format
(
group
,
index
)))
self
.
client
.
send
(
wr
(
"Total: {}"
.
format
(
len
(
self
.
asset_groups
)),
before
=
1
))
def
display_group_assets
(
self
,
_id
):
self
.
search_result
=
self
.
asset_groups
[
_id
]
.
assets_granted
self
.
display_search_result
()
def
display_search_result
(
self
):
def
display_search_result
(
self
):
if
len
(
self
.
search_result
)
==
0
:
if
len
(
self
.
search_result
)
==
0
:
self
.
client
.
send
(
warning
(
"Nothing match"
))
self
.
client
.
send
(
warning
(
"Nothing match"
))
return
return
self
.
search_result
=
sort_assets
(
self
.
search_result
,
self
.
app
.
config
[
"ASSET_LIST_SORT_BY"
])
fake_asset
=
Asset
(
hostname
=
"Hostname"
,
ip
=
"IP"
,
system_users_join
=
"LoginAs"
,
comment
=
"Comment"
)
fake_asset
=
Asset
(
hostname
=
"Hostname"
,
ip
=
"IP"
,
system_users_join
=
"LoginAs"
,
comment
=
"Comment"
)
id_max_length
=
max
(
len
(
str
(
len
(
self
.
search_result
))),
3
)
id_max_length
=
max
(
len
(
str
(
len
(
self
.
search_result
))),
3
)
hostname_max_length
=
max
(
max
([
len
(
asset
.
hostname
)
for
asset
in
self
.
search_result
+
[
fake_asset
]]),
15
)
hostname_max_length
=
max
(
max
([
len
(
asset
.
hostname
)
for
asset
in
self
.
search_result
+
[
fake_asset
]]),
15
)
sysuser_max_length
=
max
([
len
(
asset
.
system_users_join
)
for
asset
in
self
.
search_result
+
[
fake_asset
]])
sysuser_max_length
=
max
([
len
(
asset
.
system_users_join
)
for
asset
in
self
.
search_result
+
[
fake_asset
]])
header
=
'{1:
%
d} {0.hostname:
%
d} {0.ip:15} {0.system_users_join:
%
d} '
%
\
header
=
'{1:
>
%
d} {0.hostname:
%
d} {0.ip:15} {0.system_users_join:
%
d} '
%
\
(
id_max_length
,
hostname_max_length
,
sysuser_max_length
)
(
id_max_length
,
hostname_max_length
,
sysuser_max_length
)
comment_length
=
self
.
request
.
meta
[
"width"
]
-
len
(
header
.
format
(
fake_asset
,
id_max_length
))
comment_length
=
self
.
request
.
meta
[
"width"
]
-
len
(
header
.
format
(
fake_asset
,
id_max_length
))
line
=
header
+
'{0.comment:.
%
d}'
%
(
comment_length
/
2
)
# comment中可能有中文
line
=
header
+
'{0.comment:.
%
d}'
%
(
comment_length
/
2
)
# comment中可能有中文
header
+=
'{0.comment:
%
s}'
%
comment_length
header
+=
'{0.comment:
%
s}'
%
comment_length
self
.
client
.
send
(
wr
(
title
(
header
.
format
(
fake_asset
,
"ID"
)
.
encode
(
"utf-8"
))))
self
.
client
.
send
(
wr
(
title
(
header
.
format
(
fake_asset
,
"ID"
))))
self
.
client
.
send
(
b
'
\r\n
'
)
for
index
,
asset
in
enumerate
(
self
.
search_result
,
1
):
for
index
,
asset
in
enumerate
(
self
.
search_result
,
1
):
self
.
client
.
send
(
line
.
format
(
asset
,
index
)
.
encode
(
'utf-8'
))
self
.
client
.
send
(
wr
(
line
.
format
(
asset
,
index
)
))
self
.
client
.
send
(
b
'
\r\n
'
)
self
.
client
.
send
(
wr
(
"Total: {}"
.
format
(
len
(
self
.
search_result
)),
before
=
1
)
)
def
search_and_display
(
self
,
q
):
def
search_and_display
(
self
,
q
):
self
.
search_assets
(
q
)
self
.
search_assets
(
q
)
self
.
display_search_result
()
self
.
display_search_result
()
def
get_user_asset_groups
(
self
):
def
get_user_asset_groups
(
self
):
pass
self
.
asset_groups
=
self
.
app
.
service
.
get_user_asset_groups
(
self
.
client
.
user
)
def
get_user_asset_groups_async
(
self
):
def
get_user_asset_groups_async
(
self
):
thread
=
threading
.
Thread
(
target
=
self
.
get_user_asset_groups
)
thread
=
threading
.
Thread
(
target
=
self
.
get_user_asset_groups
)
...
@@ -177,9 +208,6 @@ class InteractiveServer:
...
@@ -177,9 +208,6 @@ class InteractiveServer:
thread
=
threading
.
Thread
(
target
=
self
.
get_user_assets
)
thread
=
threading
.
Thread
(
target
=
self
.
get_user_assets
)
thread
.
start
()
thread
.
start
()
def
display_asset_groups
(
self
):
pass
def
choose_system_user
(
self
,
system_users
):
def
choose_system_user
(
self
,
system_users
):
pass
pass
...
...
coco/models.py
View file @
cb232113
...
@@ -38,6 +38,8 @@ class Client:
...
@@ -38,6 +38,8 @@ class Client:
return
self
.
chan
.
fileno
()
return
self
.
chan
.
fileno
()
def
send
(
self
,
b
):
def
send
(
self
,
b
):
if
isinstance
(
b
,
str
):
b
=
b
.
encode
(
"utf-8"
)
return
self
.
chan
.
send
(
b
)
return
self
.
chan
.
send
(
b
)
def
recv
(
self
,
size
):
def
recv
(
self
,
size
):
...
@@ -77,6 +79,8 @@ class Server:
...
@@ -77,6 +79,8 @@ class Server:
return
self
.
chan
.
fileno
()
return
self
.
chan
.
fileno
()
def
send
(
self
,
b
):
def
send
(
self
,
b
):
if
isinstance
(
b
,
str
):
b
=
b
.
encode
(
"utf-8"
)
if
not
self
.
_input_initial
:
if
not
self
.
_input_initial
:
self
.
_input_initial
=
True
self
.
_input_initial
=
True
...
...
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