diff --git a/apps/applications/api.py b/apps/applications/api.py
index 3a58ed8e2..4933246b0 100644
--- a/apps/applications/api.py
+++ b/apps/applications/api.py
@@ -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 TerminalRegisterView(ListCreateAPIView):
+class TerminalViewSet(viewsets.ModelViewSet):
queryset = Terminal.objects.all()
serializer_class = TerminalSerializer
- permission_classes = (AllowAny,)
+ permission_classes = (IsSuperUserOrAppUserOrUserReadonly,)
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
- if get_object_or_none(Terminal, name=name):
- return Response({'msg': 'Already register, Need '
- 'administrator active it'}, status=200)
+ terminal = get_object_or_none(Terminal, name=name)
+ if terminal:
+ msg = 'Terminal name %s already used' % name
+ return Response({'msg': msg}, status=409)
+
+ 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)
+ def get_permissions(self):
+ if self.action == "create":
+ self.permission_classes = (AllowAny,)
+ return super().get_permissions()
-class TerminalViewSet(viewsets.ModelViewSet):
- queryset = Terminal.objects.all()
- serializer_class = TerminalSerializer
- permission_classes = (IsSuperUserOrAppUserOrUserReadonly,)
-
- def create(self, request, *args, **kwargs):
- return Response({'msg': 'Use register view except that'}, status=404)
-
- # 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}]}
diff --git a/apps/applications/forms.py b/apps/applications/forms.py
index b6a20eafa..6ef787594 100644
--- a/apps/applications/forms.py
+++ b/apps/applications/forms.py
@@ -2,6 +2,7 @@
#
from django import forms
+from django.utils.translation import ugettext_lazy as _
from .models import Terminal
@@ -9,10 +10,12 @@ 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'})
- }
\ No newline at end of file
+ }
diff --git a/apps/applications/models.py b/apps/applications/models.py
index 29adecdae..0d1cb1bc9 100644
--- a/apps/applications/models.py
+++ b/apps/applications/models.py
@@ -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',)
diff --git a/apps/applications/serializers.py b/apps/applications/serializers.py
index 56f05e67c..fcb43adb9 100644
--- a/apps/applications/serializers.py
+++ b/apps/applications/serializers.py
@@ -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', 'comment',
- 'is_accepted', 'is_active', 'get_type_display',
- 'proxy_online', 'is_alive']
+ fields = ['id', 'name', 'remote_addr', 'http_port', 'ssh_port',
+ '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
+
+
diff --git a/apps/applications/templates/applications/terminal_list.html b/apps/applications/templates/applications/terminal_list.html
index fa0f32396..bd3f72c0c 100644
--- a/apps/applications/templates/applications/terminal_list.html
+++ b/apps/applications/templates/applications/terminal_list.html
@@ -27,9 +27,10 @@
{% trans 'Name' %} |
- {% trans 'IP' %} |
- {% trans 'Type' %} |
- {% trans 'Session online' %} |
+ {% trans 'Addr' %} |
+ {% trans 'SSH Port' %} |
+ {% trans 'Http Port' %} |
+ {% trans 'Connected' %} |
{% trans 'Active' %} |
{% trans 'Alive' %} |
{% trans 'Action' %} |
@@ -53,21 +54,21 @@ $(document).ready(function(){
var detail_btn = '' + cellData + '';
$(td).html(detail_btn.replace('99991937', rowData.id));
}},
- {targets: 5, createdCell: function (td, cellData) {
+ {targets: 6, createdCell: function (td, cellData) {
if (!cellData) {
$(td).html('')
} else {
$(td).html('')
}
}},
- {targets: 6, createdCell: function (td, cellData) {
+ {targets: 7, createdCell: function (td, cellData) {
if (!cellData) {
$(td).html('')
} else {
$(td).html('')
}
}},
- {targets: 7, createdCell: function (td, cellData, rowData) {
+ {targets: 8, createdCell: function (td, cellData, rowData) {
var update_btn = '{% trans "Update" %}'
.replace('99991937', cellData);
var delete_btn = '{% trans "Delete" %}'
@@ -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_active'}, {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_alive'}, {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)
diff --git a/apps/applications/templates/applications/terminal_modal_accept.html b/apps/applications/templates/applications/terminal_modal_accept.html
index 7e9c7fac7..50789a3a0 100644
--- a/apps/applications/templates/applications/terminal_modal_accept.html
+++ b/apps/applications/templates/applications/terminal_modal_accept.html
@@ -10,8 +10,8 @@
{% 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" %}
diff --git a/apps/applications/urls/api_urls.py b/apps/applications/urls/api_urls.py
index ed0e42c32..7eb6e8b43 100644
--- a/apps/applications/urls/api_urls.py
+++ b/apps/applications/urls/api_urls.py
@@ -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
diff --git a/apps/applications/views.py b/apps/applications/views.py
index 90874d382..7cac6f575 100644
--- a/apps/applications/views.py
+++ b/apps/applications/views.py
@@ -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),
diff --git a/apps/common/utils.py b/apps/common/utils.py
index de8e995bd..fb9bc6937 100644
--- a/apps/common/utils.py
+++ b/apps/common/utils.py
@@ -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'
diff --git a/apps/static/css/plugins/inputTags.css b/apps/static/css/plugins/inputTags.css
index 085ea19fa..365454272 100644
--- a/apps/static/css/plugins/inputTags.css
+++ b/apps/static/css/plugins/inputTags.css
@@ -1,5 +1,5 @@
-@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;*/
/*}*/
diff --git a/apps/static/css/style.css b/apps/static/css/style.css
index 637517e34..a4c62fe97 100644
--- a/apps/static/css/style.css
+++ b/apps/static/css/style.css
@@ -1,5 +1,5 @@
-@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
diff --git a/apps/users/authentication.py b/apps/users/authentication.py
index b8e2601e6..09321953e 100644
--- a/apps/users/authentication.py
+++ b/apps/users/authentication.py
@@ -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):
diff --git a/apps/users/models/authentication.py b/apps/users/models/authentication.py
index 917bc1114..954c7e5bc 100644
--- a/apps/users/models/authentication.py
+++ b/apps/users/models/authentication.py
@@ -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"""
diff --git a/apps/users/models/user.py b/apps/users/models/user.py
index e6f5724c4..cf9a51034 100644
--- a/apps/users/models/user.py
+++ b/apps/users/models/user.py
@@ -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'))
diff --git a/apps/users/serializers.py b/apps/users/serializers.py
index 880d3b21e..fd52d99c7 100644
--- a/apps/users/serializers.py
+++ b/apps/users/serializers.py
@@ -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