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
034f0a02
Commit
034f0a02
authored
Oct 31, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update terminal api
parent
30c4fc95
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
66 additions
and
86 deletions
+66
-86
api.py
apps/applications/api.py
+21
-30
forms.py
apps/applications/forms.py
+5
-2
models.py
apps/applications/models.py
+6
-13
serializers.py
apps/applications/serializers.py
+8
-7
terminal_list.html
apps/applications/templates/applications/terminal_list.html
+9
-9
terminal_modal_accept.html
...cations/templates/applications/terminal_modal_accept.html
+2
-2
api_urls.py
apps/applications/urls/api_urls.py
+0
-3
views.py
apps/applications/views.py
+1
-2
utils.py
apps/common/utils.py
+4
-4
inputTags.css
apps/static/css/plugins/inputTags.css
+2
-2
style.css
apps/static/css/style.css
+2
-2
authentication.py
apps/users/authentication.py
+2
-2
authentication.py
apps/users/models/authentication.py
+1
-3
user.py
apps/users/models/user.py
+3
-3
serializers.py
apps/users/serializers.py
+0
-2
No files found.
apps/applications/api.py
View file @
034f0a02
...
...
@@ -3,12 +3,10 @@
from
collections
import
OrderedDict
import
copy
from
rest_framework.generics
import
ListCreateAPIView
from
rest_framework
import
viewsets
from
rest_framework.views
import
APIView
,
Response
from
rest_framework.permissions
import
AllowAny
from
django.shortcuts
import
get_object_or_404
from
rest_framework.decorators
import
api_view
from
.models
import
Terminal
,
TerminalHeatbeat
from
.serializers
import
TerminalSerializer
,
TerminalHeatbeatSerializer
...
...
@@ -17,21 +15,25 @@ from .hands import IsSuperUserOrAppUser, IsAppUser, ProxyLog, \
from
common.utils
import
get_object_or_none
class
Terminal
RegisterView
(
ListCreateAPIView
):
class
Terminal
ViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
Terminal
.
objects
.
all
()
serializer_class
=
TerminalSerializer
permission_classes
=
(
AllowAn
y
,)
permission_classes
=
(
IsSuperUserOrAppUserOrUserReadonl
y
,)
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
name
=
request
.
data
.
get
(
'name'
,
''
)
remote_addr
=
request
.
META
.
get
(
'X-Real-IP'
)
or
\
request
.
META
.
get
(
'REMOTE_ADDR'
)
serializer
=
self
.
serializer_class
(
data
=
{
'name'
:
name
,
'remote_addr'
:
remote_addr
})
name
=
request
.
data
.
get
(
'name'
)
remote_ip
=
request
.
META
.
get
(
'REMOTE_ADDR'
)
x_real_ip
=
request
.
META
.
get
(
'X-Real-IP'
)
remote_addr
=
x_real_ip
or
remote_ip
terminal
=
get_object_or_none
(
Terminal
,
name
=
name
)
if
terminal
:
msg
=
'Terminal name
%
s already used'
%
name
return
Response
({
'msg'
:
msg
},
status
=
409
)
if
get_object_or_none
(
Terminal
,
name
=
name
):
return
Response
({
'msg'
:
'Already register, Need '
'administrator active it'
},
status
=
200
)
serializer
=
self
.
serializer_class
(
data
=
{
'name'
:
name
,
'remote_addr'
:
remote_addr
}
)
if
serializer
.
is_valid
():
terminal
=
serializer
.
save
()
...
...
@@ -39,30 +41,19 @@ class TerminalRegisterView(ListCreateAPIView):
data
=
OrderedDict
()
data
[
'terminal'
]
=
copy
.
deepcopy
(
serializer
.
data
)
data
[
'user'
]
=
app_user
.
to_json
()
data
[
'access_key
_id'
]
=
access_key
.
id
data
[
'access_key_secret'
]
=
access_key
.
secret
data
[
'access_key
'
]
=
{
'id'
:
access_key
.
id
,
'secret'
:
access_key
.
secret
}
return
Response
(
data
,
status
=
201
)
else
:
data
=
{
'msg'
:
'Not valid'
,
'detail'
:
';'
.
join
(
serializer
.
errors
)}
data
=
serializer
.
errors
return
Response
(
data
,
status
=
400
)
def
list
(
self
,
request
,
*
args
,
**
kwargs
):
return
Response
(
''
,
status
=
404
)
class
TerminalViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
Terminal
.
objects
.
all
()
serializer_class
=
TerminalSerializer
permission_classes
=
(
IsSuperUserOrAppUserOrUserReadonly
,)
def
get_permissions
(
self
):
if
self
.
action
==
"create"
:
self
.
permission_classes
=
(
AllowAny
,)
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
return
Response
({
'msg'
:
'Use register view except that'
},
status
=
404
)
return
super
()
.
get_permissions
()
# def destroy(self, request, *args, **kwargs):
# instance = self.get_object()
# if instance.user is not None:
# instance.user.delete()
# return super(TerminalViewSet, self).destroy(request, *args, **kwargs)
tasks
=
OrderedDict
()
# tasks = {1: [{'name': 'kill_proxy', 'proxy_log_id': 23}]}
...
...
apps/applications/forms.py
View file @
034f0a02
...
...
@@ -2,6 +2,7 @@
#
from
django
import
forms
from
django.utils.translation
import
ugettext_lazy
as
_
from
.models
import
Terminal
...
...
@@ -9,9 +10,11 @@ from .models import Terminal
class
TerminalForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Terminal
fields
=
[
'name'
,
'remote_addr'
,
'
type'
,
'url
'
,
'comment'
]
fields
=
[
'name'
,
'remote_addr'
,
'
ssh_port'
,
'http_port
'
,
'comment'
]
help_texts
=
{
'url'
:
'Example: ssh://192.168.1.1:22 or http://jms.jumpserver.org, that user login'
'remote_addr'
:
_
(
'A unique addr of every terminal, user browser can arrive it'
),
'ssh_port'
:
_
(
"Coco ssh listen port"
),
'http_port'
:
_
(
"Coco http/ws listen port"
),
}
widgets
=
{
'name'
:
forms
.
TextInput
(
attrs
=
{
'readonly'
:
'readonly'
})
...
...
apps/applications/models.py
View file @
034f0a02
...
...
@@ -7,16 +7,11 @@ from users.models import User
class
Terminal
(
models
.
Model
):
TYPE_CHOICES
=
(
(
'SSH'
,
'SSH Terminal'
),
(
'Web'
,
'Web Terminal'
)
)
name
=
models
.
CharField
(
max_length
=
30
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
remote_addr
=
models
.
GenericIPAddressField
(
verbose_name
=
_
(
'Remote address'
),
blank
=
True
,
null
=
True
)
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
3
,
blank
=
True
,
verbose_name
=
_
(
'Terminal type'
))
user
=
models
.
OneToOneField
(
User
,
related_name
=
'terminal'
,
verbose_name
=
'Application user'
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
url
=
models
.
CharField
(
max_length
=
100
,
blank
=
True
,
verbose_name
=
_
(
'URL to login'
))
name
=
models
.
CharField
(
max_length
=
32
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
remote_addr
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Remote Address'
))
ssh_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'SSH Port'
),
default
=
2222
)
http_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'HTTP Port'
),
default
=
5000
)
user
=
models
.
OneToOneField
(
User
,
related_name
=
'terminal'
,
verbose_name
=
'Application User'
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
is_accepted
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'Is Accepted'
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
...
...
@@ -44,12 +39,10 @@ class Terminal(models.Model):
self
.
user
.
delete
()
return
super
(
Terminal
,
self
)
.
delete
(
using
=
using
,
keep_parents
=
keep_parents
)
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
active
=
'Active'
if
self
.
user
and
self
.
user
.
is_active
else
'Disabled'
return
'
%
s:
%
s'
%
(
self
.
name
,
active
)
__str__
=
__unicode__
class
Meta
:
ordering
=
(
'is_accepted'
,)
...
...
apps/applications/serializers.py
View file @
034f0a02
...
...
@@ -9,17 +9,17 @@ from .hands import ProxyLog
class
TerminalSerializer
(
serializers
.
ModelSerializer
):
proxy_online
=
serializers
.
SerializerMethodField
()
session_connected
=
serializers
.
SerializerMethodField
()
is_alive
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
Terminal
fields
=
[
'id'
,
'name'
,
'remote_addr'
,
'
type'
,
'url'
,
'commen
t'
,
'
is_accepted'
,
'is_active'
,
'get_type_display
'
,
'
proxy_online
'
,
'is_alive'
]
fields
=
[
'id'
,
'name'
,
'remote_addr'
,
'
http_port'
,
'ssh_por
t'
,
'
comment'
,
'is_accepted
'
,
'
session_connected
'
,
'is_alive'
]
@staticmethod
def
get_
proxy_online
(
obj
):
def
get_
session_connected
(
obj
):
return
ProxyLog
.
objects
.
filter
(
terminal
=
obj
.
name
,
is_finished
=
False
)
.
count
()
@staticmethod
...
...
@@ -33,9 +33,10 @@ class TerminalSerializer(serializers.ModelSerializer):
class
TerminalHeatbeatSerializer
(
serializers
.
ModelSerializer
):
date_start
=
serializers
.
DateTimeField
class
Meta
:
model
=
TerminalHeatbeat
if
__name__
==
'__main__'
:
pass
apps/applications/templates/applications/terminal_list.html
View file @
034f0a02
...
...
@@ -27,9 +27,10 @@
</div>
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</th>
<th
class=
"text-center"
>
{% trans 'IP' %}
</th>
<th
class=
"text-center"
>
{% trans 'Type' %}
</th>
<th
class=
"text-center"
>
{% trans 'Session online' %}
</th>
<th
class=
"text-center"
>
{% trans 'Addr' %}
</th>
<th
class=
"text-center"
>
{% trans 'SSH Port' %}
</th>
<th
class=
"text-center"
>
{% trans 'Http Port' %}
</th>
<th
class=
"text-center"
>
{% trans 'Connected' %}
</th>
<th
class=
"text-center"
>
{% trans 'Active' %}
</th>
<th
class=
"text-center"
>
{% trans 'Alive' %}
</th>
<th
class=
"text-center"
>
{% trans 'Action' %}
</th>
...
...
@@ -53,21 +54,21 @@ $(document).ready(function(){
var
detail_btn
=
'<a href="{% url "applications:terminal-detail" pk=99991937 %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'99991937'
,
rowData
.
id
));
}},
{
targets
:
5
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-times text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-circle text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-circle text-navy"></i>'
)
}
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "applications:terminal-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'99991937'
,
cellData
);
var
delete_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="99991937" data-name="99991938">{% trans "Delete" %}</a>'
...
...
@@ -94,8 +95,8 @@ $(document).ready(function(){
}}
],
ajax_url
:
'{% url "api-applications:terminal-list" %}'
,
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"name"
},
{
data
:
"remote_addr"
},
{
data
:
"
get_type_display"
},
{
data
:
"
proxy_online"
},
{
data
:
"is_active"
},
{
data
:
'is_act
ive'
},
{
data
:
"id"
}],
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"name"
},
{
data
:
"remote_addr"
},
{
data
:
"
ssh_port"
},
{
data
:
"http_port"
},
{
data
:
"
session_connected"
},
{
data
:
"is_alive"
},
{
data
:
'is_al
ive'
},
{
data
:
"id"
}],
op_html
:
$
(
'#actions'
).
html
()
};
jumpserver
.
initDataTable
(
options
);
...
...
@@ -131,7 +132,6 @@ $(document).ready(function(){
success
:
function
(
data
)
{
$
(
'#id_name'
).
val
(
data
.
name
);
$
(
'#id_remote_addr'
).
val
(
data
.
remote_addr
);
$
(
'#id_type'
).
val
(
data
.
type
);
$
(
'#id_url'
).
val
(
data
.
url
);
$
(
'#id_comment'
).
val
(
data
.
comment
);
$
(
'#form_terminal_accept'
).
attr
(
'action'
,
post_url
)
...
...
apps/applications/templates/applications/terminal_modal_accept.html
View file @
034f0a02
...
...
@@ -10,8 +10,8 @@
<p
class=
"alert alert-danger"
id=
"modal-error"
style=
"display: none"
></p>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.
type
layout="horizontal" %}
{% bootstrap_field form.
url
layout="horizontal" %}
{% bootstrap_field form.
ssh_port
layout="horizontal" %}
{% bootstrap_field form.
http_port
layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
</form>
...
...
apps/applications/urls/api_urls.py
View file @
034f0a02
...
...
@@ -14,11 +14,8 @@ router.register(r'v1/terminal/heatbeat', api.TerminalHeatbeatViewSet, 'terminal-
router
.
register
(
r'v1/terminal'
,
api
.
TerminalViewSet
,
'terminal'
)
urlpatterns
=
[
url
(
r'^v1/terminal/register/$'
,
api
.
TerminalRegisterView
.
as_view
(),
name
=
'terminal-register'
),
url
(
r'^v1/terminate/connection/$'
,
api
.
TerminateConnectionView
.
as_view
(),
name
=
'terminate-connection'
)
# url(r'^v1/terminal/heatbeat/$', api.TestHeatbeat.as_view())
]
urlpatterns
+=
router
.
urls
apps/applications/views.py
View file @
034f0a02
...
...
@@ -66,7 +66,6 @@ class TerminalModelAccept(AdminUserRequiredMixin, JSONResponseMixin, UpdateView)
template_name
=
'applications/terminal_modal_test.html'
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
print
(
request
.
POST
)
return
super
(
TerminalModelAccept
,
self
)
.
post
(
request
,
*
args
,
**
kwargs
)
def
form_valid
(
self
,
form
):
...
...
@@ -81,7 +80,7 @@ class TerminalModelAccept(AdminUserRequiredMixin, JSONResponseMixin, UpdateView)
return
self
.
render_json_response
(
data
)
def
form_invalid
(
self
,
form
):
print
(
'form.data'
)
print
(
form
.
data
)
data
=
{
'success'
:
False
,
'msg'
:
str
(
form
.
errors
),
...
...
apps/common/utils.py
View file @
034f0a02
...
...
@@ -274,8 +274,10 @@ def content_md5(data):
返回值可以直接作为HTTP Content-Type头部的值
"""
m
=
hashlib
.
md5
(
to_bytes
(
data
))
return
to_string
(
base64
.
b64encode
(
m
.
digest
()))
if
isinstance
(
data
,
str
):
data
=
hashlib
.
md5
(
data
.
encode
(
'utf-8'
))
value
=
base64
.
b64encode
(
data
.
digest
())
return
value
.
decode
(
'utf-8'
)
_STRPTIME_LOCK
=
threading
.
Lock
()
...
...
@@ -330,8 +332,6 @@ def encrypt_password(password):
return
None
def
capacity_convert
(
size
,
expect
=
'auto'
,
rate
=
1000
):
"""
:param size: '100MB', '1G'
...
...
apps/static/css/plugins/inputTags.css
View file @
034f0a02
@import
url("https://fonts.css.network/css?family=Open+Sans:300,400,600,700")
;
@import
url("https://fonts.css.network/css?family=Roboto:400,300,500,700")
;
/*@import url("https://fonts.css.network/css?family=Open+Sans:300,400,600,700");*/
/*@import url("https://fonts.css.network/css?family=Roboto:400,300,500,700");*/
/** {*/
/*box-sizing: border-box;*/
/*}*/
...
...
apps/static/css/style.css
View file @
034f0a02
@import
url("https://fonts.css.network/css?family=Open+Sans:300,400,600,700")
;
@import
url("https://fonts.css.network/css?family=Roboto:400,300,500,700")
;
/*@import url("https://fonts.css.network/css?family=Open+Sans:300,400,600,700");*/
/*@import url("https://fonts.css.network/css?family=Roboto:400,300,500,700");*/
/*
*
* INSPINIA - Responsive Admin Theme
...
...
apps/users/authentication.py
View file @
034f0a02
...
...
@@ -49,7 +49,6 @@ class AccessKeyAuthentication(authentication.BaseAuthentication):
def
authenticate
(
self
,
request
):
auth
=
authentication
.
get_authorization_header
(
request
)
.
split
()
if
not
auth
or
auth
[
0
]
.
lower
()
!=
self
.
keyword
.
lower
()
.
encode
():
return
None
...
...
@@ -80,7 +79,8 @@ class AccessKeyAuthentication(authentication.BaseAuthentication):
request_signature
=
sign
[
1
]
return
self
.
authenticate_credentials
(
request
,
access_key_id
,
request_signature
)
request
,
access_key_id
,
request_signature
)
@staticmethod
def
authenticate_credentials
(
request
,
access_key_id
,
request_signature
):
...
...
apps/users/models/authentication.py
View file @
034f0a02
...
...
@@ -25,11 +25,9 @@ class AccessKey(models.Model):
def
get_secret
(
self
):
return
str
(
self
.
secret
)
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
str
(
self
.
id
)
__str__
=
__unicode__
class
PrivateToken
(
Token
):
"""Inherit from auth token, otherwise migration is boring"""
...
...
apps/users/models/user.py
View file @
034f0a02
...
...
@@ -23,9 +23,9 @@ __all__ = ['User']
class
User
(
AbstractUser
):
ROLE_CHOICES
=
(
(
'Admin'
,
_
(
'Administrator'
)
),
(
'User'
,
_
(
'User'
)
),
(
'App'
,
_
(
'Application'
)
)
(
'Admin'
,
'Administrator'
),
(
'User'
,
'User'
),
(
'App'
,
'Application'
)
)
username
=
models
.
CharField
(
max_length
=
20
,
unique
=
True
,
verbose_name
=
_
(
'Username'
))
...
...
apps/users/serializers.py
View file @
034f0a02
...
...
@@ -36,8 +36,6 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
@staticmethod
def
validate__public_key
(
value
):
if
not
validate_ssh_public_key
(
value
):
print
(
'Not a valid key'
)
print
(
value
)
raise
serializers
.
ValidationError
(
_
(
'Not a valid ssh public key'
))
return
value
...
...
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