mirror of https://github.com/jumpserver/jumpserver
				
				
				
			Tmp org (#1579)
* [Update] 添加org api, 升级到django 2.0 * [Update] fix some bug * [Update] 修改一些bugpull/1580/head^2
							parent
							
								
									c816875f28
								
							
						
					
					
						commit
						b156f4ad16
					
				| 
						 | 
				
			
			@ -2,8 +2,9 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
import random
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from rest_framework import generics
 | 
			
		||||
from rest_framework import generics, permissions
 | 
			
		||||
from rest_framework.response import Response
 | 
			
		||||
from rest_framework_bulk import BulkModelViewSet
 | 
			
		||||
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView
 | 
			
		||||
| 
						 | 
				
			
			@ -39,9 +40,10 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
 | 
			
		|||
    queryset = Asset.objects.all()
 | 
			
		||||
    serializer_class = serializers.AssetSerializer
 | 
			
		||||
    pagination_class = LimitOffsetPagination
 | 
			
		||||
    permission_classes = (IsOrgAdminOrAppUser,)
 | 
			
		||||
    permission_classes = (permissions.AllowAny,)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        time.sleep(3)
 | 
			
		||||
        queryset = super().get_queryset()\
 | 
			
		||||
            .prefetch_related('labels', 'nodes')\
 | 
			
		||||
            .select_related('admin_user')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,11 @@
 | 
			
		|||
 | 
			
		||||
from rest_framework_bulk import BulkModelViewSet
 | 
			
		||||
from rest_framework.views import APIView, Response
 | 
			
		||||
from rest_condition import Or
 | 
			
		||||
 | 
			
		||||
from django.views.generic.detail import SingleObjectMixin
 | 
			
		||||
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
from common.permissions import IsOrgAdmin, IsAppUser
 | 
			
		||||
from common.permissions import IsOrgAdmin, IsAppUser, IsOrgAdminOrAppUser
 | 
			
		||||
from ..models import Domain, Gateway
 | 
			
		||||
from ..utils import test_gateway_connectability
 | 
			
		||||
from .. import serializers
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ class Gateway(AssetUser):
 | 
			
		|||
    ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
 | 
			
		||||
    port = models.IntegerField(default=22, verbose_name=_('Port'))
 | 
			
		||||
    protocol = models.CharField(choices=PROTOCOL_CHOICES, max_length=16, default=SSH_PROTOCOL, verbose_name=_("Protocol"))
 | 
			
		||||
    domain = models.ForeignKey(Domain, verbose_name=_("Domain"))
 | 
			
		||||
    domain = models.ForeignKey(Domain, on_delete=models.CASCADE, verbose_name=_("Domain"))
 | 
			
		||||
    comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Comment"))
 | 
			
		||||
    is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,20 @@
 | 
			
		|||
        .dropdown a:hover {
 | 
			
		||||
            background-color: #f1f1f1
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .dataTables_wrapper .dataTables_processing {
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            top: 30%;
 | 
			
		||||
            left: 50%;
 | 
			
		||||
            width: 30%;
 | 
			
		||||
            height: 40px;
 | 
			
		||||
            margin-left: -20%;
 | 
			
		||||
            margin-top: -25px;
 | 
			
		||||
            padding-top: 20px;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            font-size: 1.2em;
 | 
			
		||||
            background: none;
 | 
			
		||||
        }
 | 
			
		||||
	</style>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
 | 
			
		|||
    template_name = 'assets/asset_list.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        print(Node.root().name)
 | 
			
		||||
        Node.root()
 | 
			
		||||
        context = {
 | 
			
		||||
            'app': _('Assets'),
 | 
			
		||||
            'action': _('Asset list'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,7 +86,18 @@ class LDAPTestingAPI(APIView):
 | 
			
		|||
 | 
			
		||||
class DjangoSettingsAPI(APIView):
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
        return Response('Danger, Close now')
 | 
			
		||||
        if not settings.DEBUG:
 | 
			
		||||
            return Response("Not in debug mode")
 | 
			
		||||
 | 
			
		||||
        data = {}
 | 
			
		||||
        for k, v in settings.__dict__.items():
 | 
			
		||||
            if k and k.isupper():
 | 
			
		||||
                try:
 | 
			
		||||
                    json.dumps(v)
 | 
			
		||||
                    data[k] = v
 | 
			
		||||
                except (json.JSONDecodeError, TypeError):
 | 
			
		||||
                    data[k] = str(v)
 | 
			
		||||
        return Response(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@
 | 
			
		|||
 | 
			
		||||
from rest_framework import permissions
 | 
			
		||||
from django.contrib.auth.mixins import UserPassesTestMixin
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
from django.http.response import HttpResponseForbidden
 | 
			
		||||
 | 
			
		||||
from orgs.utils import current_org
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +25,18 @@ class IsAppUser(IsValidUser):
 | 
			
		|||
            and request.user.is_app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IsSuperUser(IsValidUser):
 | 
			
		||||
    def has_permission(self, request, view):
 | 
			
		||||
        return super(IsSuperUser, self).has_permission(request, view) \
 | 
			
		||||
               and request.user.is_superuser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IsSuperUserOrAppUser(IsSuperUser):
 | 
			
		||||
    def has_permission(self, request, view):
 | 
			
		||||
        return super(IsSuperUserOrAppUser, self).has_permission(request, view) \
 | 
			
		||||
            and (request.user.is_superuser or request.user.is_app)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IsOrgAdmin(IsValidUser):
 | 
			
		||||
    """Allows access only to superuser"""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,3 +77,18 @@ class AdminUserRequiredMixin(UserPassesTestMixin):
 | 
			
		|||
            self.raise_exception = True
 | 
			
		||||
            return False
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        print("Current org: {}".format(current_org))
 | 
			
		||||
        if not current_org:
 | 
			
		||||
            return redirect('orgs:switch-a-org')
 | 
			
		||||
 | 
			
		||||
        if not current_org.can_admin_by(request.user):
 | 
			
		||||
            print("{} cannot admin {}".format(request.user, current_org))
 | 
			
		||||
            if request.user.is_org_admin:
 | 
			
		||||
                print("Is org admin")
 | 
			
		||||
                return redirect('orgs:switch-a-org')
 | 
			
		||||
            return HttpResponseForbidden()
 | 
			
		||||
        else:
 | 
			
		||||
            print(current_org.can_admin_by(request.user))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,5 +9,5 @@ app_name = 'common'
 | 
			
		|||
urlpatterns = [
 | 
			
		||||
    url(r'^mail/testing/$', api.MailTestingAPI.as_view(), name='mail-testing'),
 | 
			
		||||
    url(r'^ldap/testing/$', api.LDAPTestingAPI.as_view(), name='ldap-testing'),
 | 
			
		||||
    url(r'^django-settings/$', api.DjangoSettingsAPI.as_view(), name='django-settings'),
 | 
			
		||||
    # url(r'^django-settings/$', api.DjangoSettingsAPI.as_view(), name='django-settings'),
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,6 +66,7 @@ INSTALLED_APPS = [
 | 
			
		|||
    'audits.apps.AuditsConfig',
 | 
			
		||||
    'rest_framework',
 | 
			
		||||
    'rest_framework_swagger',
 | 
			
		||||
    'drf_yasg',
 | 
			
		||||
    'django_filters',
 | 
			
		||||
    'bootstrap3',
 | 
			
		||||
    'captcha',
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +231,7 @@ LOGGING = {
 | 
			
		|||
            'level': LOG_LEVEL,
 | 
			
		||||
        },
 | 
			
		||||
        'django_auth_ldap': {
 | 
			
		||||
            'handlers': ['console', 'ansible_logs'],
 | 
			
		||||
            'handlers': ['console', 'file'],
 | 
			
		||||
            'level': "INFO",
 | 
			
		||||
        },
 | 
			
		||||
        # 'django.db': {
 | 
			
		||||
| 
						 | 
				
			
			@ -294,6 +295,7 @@ REST_FRAMEWORK = {
 | 
			
		|||
        'common.permissions.IsOrgAdmin',
 | 
			
		||||
    ),
 | 
			
		||||
    'DEFAULT_AUTHENTICATION_CLASSES': (
 | 
			
		||||
        'rest_framework.authentication.BasicAuthentication',
 | 
			
		||||
        'users.authentication.AccessKeyAuthentication',
 | 
			
		||||
        'users.authentication.AccessTokenAuthentication',
 | 
			
		||||
        'users.authentication.PrivateTokenAuthentication',
 | 
			
		||||
| 
						 | 
				
			
			@ -375,7 +377,7 @@ CACHES = {
 | 
			
		|||
            'password': CONFIG.REDIS_PASSWORD if CONFIG.REDIS_PASSWORD else '',
 | 
			
		||||
            'host': CONFIG.REDIS_HOST or '127.0.0.1',
 | 
			
		||||
            'port': CONFIG.REDIS_PORT or 6379,
 | 
			
		||||
            'db':CONFIG.REDIS_DB_CACHE or 4,
 | 
			
		||||
            'db': CONFIG.REDIS_DB_CACHE or 4,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -425,3 +427,12 @@ TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION or 3600
 | 
			
		|||
DISPLAY_PER_PAGE = CONFIG.DISPLAY_PER_PAGE or 25
 | 
			
		||||
DEFAULT_EXPIRED_YEARS = 70
 | 
			
		||||
USER_GUIDE_URL = ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SWAGGER_SETTINGS = {
 | 
			
		||||
    'SECURITY_DEFINITIONS': {
 | 
			
		||||
        'basic': {
 | 
			
		||||
            'type': 'basic'
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,13 +9,28 @@ from rest_framework.response import Response
 | 
			
		|||
from django.views.decorators.csrf import csrf_exempt
 | 
			
		||||
from django.http import HttpResponse
 | 
			
		||||
from django.utils.encoding import iri_to_uri
 | 
			
		||||
from rest_framework import permissions
 | 
			
		||||
 | 
			
		||||
from rest_framework.schemas import get_schema_view
 | 
			
		||||
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
 | 
			
		||||
# from rest_framework.schemas import get_schema_view
 | 
			
		||||
# from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
 | 
			
		||||
from drf_yasg.views import get_schema_view
 | 
			
		||||
from drf_yasg import openapi
 | 
			
		||||
 | 
			
		||||
from .views import IndexView, LunaView
 | 
			
		||||
 | 
			
		||||
schema_view = get_schema_view(title='Users API', renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer])
 | 
			
		||||
# schema_view = get_schema_view(title='Users API', renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer])
 | 
			
		||||
schema_view = get_schema_view(
 | 
			
		||||
   openapi.Info(
 | 
			
		||||
      title="Snippets API",
 | 
			
		||||
      default_version='v1',
 | 
			
		||||
      description="Test description",
 | 
			
		||||
      terms_of_service="https://www.google.com/policies/terms/",
 | 
			
		||||
      contact=openapi.Contact(email="contact@snippets.local"),
 | 
			
		||||
      license=openapi.License(name="BSD License"),
 | 
			
		||||
   ),
 | 
			
		||||
   public=True,
 | 
			
		||||
   permission_classes=(permissions.AllowAny,),
 | 
			
		||||
)
 | 
			
		||||
api_url_pattern = re.compile(r'^/api/(?P<app>\w+)/(?P<version>\w+)/(?P<extra>.*)$')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,5 +100,7 @@ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
 | 
			
		|||
 | 
			
		||||
if settings.DEBUG:
 | 
			
		||||
    urlpatterns += [
 | 
			
		||||
        url(r'^docs/', schema_view, name="docs"),
 | 
			
		||||
        url(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=None), name='schema-json'),
 | 
			
		||||
        url(r'^docs/', schema_view.with_ui('swagger', cache_timeout=None), name="docs"),
 | 
			
		||||
        url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=None), name='redoc'),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,16 +4,15 @@ from django.http import HttpResponse
 | 
			
		|||
from django.views.generic import TemplateView, View
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.db.models import Count
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
 | 
			
		||||
from users.models import User
 | 
			
		||||
from assets.models import Asset
 | 
			
		||||
from terminal.models import Session
 | 
			
		||||
from orgs.mixins import OrgViewGenericMixin
 | 
			
		||||
from common.permissions import AdminUserRequiredMixin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IndexView(LoginRequiredMixin, OrgViewGenericMixin, TemplateView):
 | 
			
		||||
class IndexView(AdminUserRequiredMixin, TemplateView):
 | 
			
		||||
    template_name = 'index.html'
 | 
			
		||||
 | 
			
		||||
    session_week = None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,8 @@ class TaskViewSet(viewsets.ModelViewSet):
 | 
			
		|||
    queryset = Task.objects.all()
 | 
			
		||||
    serializer_class = TaskSerializer
 | 
			
		||||
    permission_classes = (IsOrgAdmin,)
 | 
			
		||||
    label = None
 | 
			
		||||
    help_text = ''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TaskRun(generics.RetrieveAPIView):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
from rest_framework import viewsets
 | 
			
		||||
 | 
			
		||||
from common.permissions import IsOrgAdminOrAppUser
 | 
			
		||||
from .models import Organization
 | 
			
		||||
from .serializers import OrgSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrgViewSet(viewsets.ModelViewSet):
 | 
			
		||||
    queryset = Organization.objects.all()
 | 
			
		||||
    serializer_class = OrgSerializer
 | 
			
		||||
    permission_classes = (IsOrgAdminOrAppUser,)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
from threading import local
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
import warnings
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +13,6 @@ from .utils import current_org, set_current_org
 | 
			
		|||
from .models import Organization
 | 
			
		||||
 | 
			
		||||
logger = get_logger(__file__)
 | 
			
		||||
 | 
			
		||||
from threading import local
 | 
			
		||||
 | 
			
		||||
tl = local()
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +72,7 @@ class OrgModelMixin(models.Model):
 | 
			
		|||
 | 
			
		||||
class OrgViewGenericMixin:
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        print("Crrent org: {}".format(current_org))
 | 
			
		||||
        print("Current org: {}".format(current_org))
 | 
			
		||||
        if not current_org:
 | 
			
		||||
            return redirect('orgs:switch-a-org')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +82,8 @@ class OrgViewGenericMixin:
 | 
			
		|||
                print("Is org admin")
 | 
			
		||||
                return redirect('orgs:switch-a-org')
 | 
			
		||||
            return HttpResponseForbidden()
 | 
			
		||||
        else:
 | 
			
		||||
            print(current_org.can_admin_by(request.user))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
 | 
			
		||||
from rest_framework.serializers import ModelSerializer
 | 
			
		||||
from .models import Organization
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrgSerializer(ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Organization
 | 
			
		||||
        fields = '__all__'
 | 
			
		||||
        read_only_fields = ['id', 'created_by', 'date_created']
 | 
			
		||||
| 
						 | 
				
			
			@ -2,10 +2,17 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
from django.conf.urls import url
 | 
			
		||||
from .. import views
 | 
			
		||||
 | 
			
		||||
from rest_framework.routers import DefaultRouter
 | 
			
		||||
from .. import api
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app_name = 'orgs'
 | 
			
		||||
router = DefaultRouter()
 | 
			
		||||
router.register(r'orgs', api.OrgViewSet, 'org')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    # url(r'^(?P<pk>[0-9a-zA-Z\-]{36})/$', views.OrgDetailView.as_view(), name='asset-index')
 | 
			
		||||
]
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
urlpatterns += router.urls
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,8 @@ _thread_locals = local()
 | 
			
		|||
 | 
			
		||||
def get_org_from_request(request):
 | 
			
		||||
    oid = request.session.get("oid")
 | 
			
		||||
    if not oid:
 | 
			
		||||
        oid = request.META.get("HTTP_X_JMS_ORG")
 | 
			
		||||
    org = Organization.get_instance(oid)
 | 
			
		||||
    return org
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,6 +250,8 @@ function initTree() {
 | 
			
		|||
        {#$.fn.zTree.init($("#assetTree"), setting);#}
 | 
			
		||||
        $.fn.zTree.init($("#assetTree"), setting, zNodes);
 | 
			
		||||
        zTree = $.fn.zTree.getZTreeObj("assetTree");
 | 
			
		||||
        var root = zTree.getNodes()[0];
 | 
			
		||||
        zTree.expandNode(root);
 | 
			
		||||
        {#selectQueryNode();#}
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,6 +250,22 @@ function makeLabel(data) {
 | 
			
		|||
var jumpserver = {};
 | 
			
		||||
jumpserver.checked = false;
 | 
			
		||||
jumpserver.selected = {};
 | 
			
		||||
jumpserver.language = {
 | 
			
		||||
    processing: "加载中",
 | 
			
		||||
    search: "搜索",
 | 
			
		||||
    lengthMenu: "每页  _MENU_",
 | 
			
		||||
    info: "显示第 _START_ 至 _END_ 项结果; 总共 _TOTAL_ 项",
 | 
			
		||||
    infoFiltered: "",
 | 
			
		||||
    infoEmpty: "",
 | 
			
		||||
    zeroRecords: "没有匹配项",
 | 
			
		||||
    emptyTable: "没有记录",
 | 
			
		||||
    paginate: {
 | 
			
		||||
        first: "«",
 | 
			
		||||
        previous: "‹",
 | 
			
		||||
        next: "›",
 | 
			
		||||
        last: "»"
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
jumpserver.initDataTable = function (options) {
 | 
			
		||||
  // options = {
 | 
			
		||||
  //    ele *: $('#dataTable_id'),
 | 
			
		||||
| 
						 | 
				
			
			@ -293,21 +309,7 @@ jumpserver.initDataTable = function (options) {
 | 
			
		|||
        },
 | 
			
		||||
        columns: options.columns || [],
 | 
			
		||||
        select: options.select || select,
 | 
			
		||||
        language: {
 | 
			
		||||
            search: "搜索",
 | 
			
		||||
            lengthMenu: "每页  _MENU_",
 | 
			
		||||
            info: "显示第 _START_ 至 _END_ 项结果; 总共 _TOTAL_ 项",
 | 
			
		||||
            infoFiltered:   "",
 | 
			
		||||
            infoEmpty:      "",
 | 
			
		||||
            zeroRecords:    "没有匹配项",
 | 
			
		||||
            emptyTable:     "没有记录",
 | 
			
		||||
            paginate: {
 | 
			
		||||
                first:      "«",
 | 
			
		||||
                previous:   "‹",
 | 
			
		||||
                next:       "›",
 | 
			
		||||
                last:       "»"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        language: jumpserver.language,
 | 
			
		||||
        lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
 | 
			
		||||
    });
 | 
			
		||||
    table.on('select', function(e, dt, type, indexes) {
 | 
			
		||||
| 
						 | 
				
			
			@ -343,6 +345,16 @@ jumpserver.initDataTable = function (options) {
 | 
			
		|||
    return table;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
jumpserver.initStaticTable = function (selector) {
 | 
			
		||||
    $(selector).DataTable({
 | 
			
		||||
        "searching": false,
 | 
			
		||||
        "bInfo": false,
 | 
			
		||||
        "paging": false,
 | 
			
		||||
        "order": [],
 | 
			
		||||
        "language": jumpserver.language
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
jumpserver.initServerSideDataTable = function (options) {
 | 
			
		||||
  // options = {
 | 
			
		||||
  //    ele *: $('#dataTable_id'),
 | 
			
		||||
| 
						 | 
				
			
			@ -374,11 +386,11 @@ jumpserver.initServerSideDataTable = function (options) {
 | 
			
		|||
            selector: 'td:first-child'
 | 
			
		||||
      };
 | 
			
		||||
  var table = ele.DataTable({
 | 
			
		||||
        pageLength: options.pageLength || 15,
 | 
			
		||||
        dom: options.dom || '<"#uc.pull-left">flt<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
 | 
			
		||||
        order: options.order || [],
 | 
			
		||||
        // pageLength: options.pageLength || 15,
 | 
			
		||||
        // dom: options.dom || '<"#uc.pull-left">flt<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
 | 
			
		||||
        // order: options.order || [],
 | 
			
		||||
        // select: options.select || 'multi',
 | 
			
		||||
        buttons: [],
 | 
			
		||||
        // buttons: [],
 | 
			
		||||
        columnDefs: columnDefs,
 | 
			
		||||
        serverSide: true,
 | 
			
		||||
        processing: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -432,21 +444,7 @@ jumpserver.initServerSideDataTable = function (options) {
 | 
			
		|||
        },
 | 
			
		||||
        columns: options.columns || [],
 | 
			
		||||
        select: options.select || select,
 | 
			
		||||
        language: {
 | 
			
		||||
            search: "搜索",
 | 
			
		||||
            lengthMenu: "每页  _MENU_",
 | 
			
		||||
            info: "显示第 _START_ 至 _END_ 项结果; 总共 _TOTAL_ 项",
 | 
			
		||||
            infoFiltered:   "",
 | 
			
		||||
            infoEmpty:      "",
 | 
			
		||||
            zeroRecords:    "没有匹配项",
 | 
			
		||||
            emptyTable:     "没有记录",
 | 
			
		||||
            paginate: {
 | 
			
		||||
                first:      "«",
 | 
			
		||||
                previous:   "‹",
 | 
			
		||||
                next:       "›",
 | 
			
		||||
                last:       "»"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        language: jumpserver.language,
 | 
			
		||||
        lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]]
 | 
			
		||||
    });
 | 
			
		||||
    table.selected = [];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,9 +64,12 @@
 | 
			
		|||
            <span class="nav-label">{% trans 'Web terminal' %}</span>
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
        {% if request.user.is_superuser %}
 | 
			
		||||
        <li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </ul>
 | 
			
		||||
</li>
 | 
			
		||||
{% if request.user.is_superuser %}
 | 
			
		||||
<li id="ops">
 | 
			
		||||
    <a>
 | 
			
		||||
        <i class="fa fa-coffee" style="width: 14px"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +78,7 @@
 | 
			
		|||
        <li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task list' %}</a></li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</li>
 | 
			
		||||
{% endif %}
 | 
			
		||||
<li id="audits">
 | 
			
		||||
    <a>
 | 
			
		||||
        <i class="fa fa-history" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span>
 | 
			
		||||
| 
						 | 
				
			
			@ -92,11 +96,13 @@
 | 
			
		|||
{#        <li id="download"><a href="">{% trans 'File download' %}</a></li>#}
 | 
			
		||||
{#    </ul>#}
 | 
			
		||||
{#</li>#}
 | 
			
		||||
{% if request.user.is_superuser %}
 | 
			
		||||
<li id="settings">
 | 
			
		||||
    <a href="{% url 'settings:basic-setting' %}">
 | 
			
		||||
        <i class="fa fa-gears"></i> <span class="nav-label">{% trans 'Settings' %}</span><span class="label label-info pull-right"></span>
 | 
			
		||||
    </a>
 | 
			
		||||
</li>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -150,12 +150,7 @@
 | 
			
		|||
            });
 | 
			
		||||
        }
 | 
			
		||||
        $(document).ready(function() {
 | 
			
		||||
            $('table').DataTable({
 | 
			
		||||
                "searching": false,
 | 
			
		||||
                "paging": false,
 | 
			
		||||
                "bInfo" : false,
 | 
			
		||||
                "order": []
 | 
			
		||||
            });
 | 
			
		||||
            jumpserver.initStaticTable('table');
 | 
			
		||||
            $('.select2').select2({
 | 
			
		||||
                dropdownAutoWidth: true,
 | 
			
		||||
                width: "auto"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,10 @@ from .. import api
 | 
			
		|||
app_name = 'terminal'
 | 
			
		||||
 | 
			
		||||
router = routers.DefaultRouter()
 | 
			
		||||
router.register(r'terminal', api.TerminalViewSet, 'terminal2')
 | 
			
		||||
router.register(r'terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?status', api.StatusViewSet, 'terminal-status')
 | 
			
		||||
router.register(r'terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions')
 | 
			
		||||
router.register(r'tasks', api.TaskViewSet, 'tasks')
 | 
			
		||||
router.register(r'terminal', api.TerminalViewSet, 'terminal')
 | 
			
		||||
router.register(r'command', api.CommandViewSet, 'command')
 | 
			
		||||
router.register(r'sessions', api.SessionViewSet, 'session')
 | 
			
		||||
router.register(r'status', api.StatusViewSet, 'session')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -195,7 +195,7 @@ class User(AbstractUser):
 | 
			
		|||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_org_admin(self):
 | 
			
		||||
        if self.is_superuser or self.admin_orgs:
 | 
			
		||||
        if self.is_superuser or self.admin_orgs.exists():
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            return False
 | 
			
		||||
| 
						 | 
				
			
			@ -223,7 +223,7 @@ class User(AbstractUser):
 | 
			
		|||
            self.is_active = True
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
        if current_org and current_org.is_real():
 | 
			
		||||
            self.orgs.add(current_org)
 | 
			
		||||
            self.orgs.add(current_org.id)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def private_token(self):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,12 +80,7 @@
 | 
			
		|||
    <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
 | 
			
		||||
    <script>
 | 
			
		||||
        $(document).ready(function() {
 | 
			
		||||
            $('table').DataTable({
 | 
			
		||||
                "searching": false,
 | 
			
		||||
                "bInfo" : false,
 | 
			
		||||
                "paging": false,
 | 
			
		||||
                "order": []
 | 
			
		||||
            });
 | 
			
		||||
            jumpserver.initStaticTable('table');
 | 
			
		||||
            $('#date .input-daterange').datepicker({
 | 
			
		||||
                format: "yyyy-mm-dd",
 | 
			
		||||
                todayBtn: "linked",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
# ~*~ coding: utf-8 ~*~
 | 
			
		||||
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
from django.urls import reverse_lazy
 | 
			
		||||
from django.views.generic.base import TemplateView
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +10,8 @@ from django.contrib.messages.views import SuccessMessageMixin
 | 
			
		|||
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
from common.const import create_success_msg, update_success_msg
 | 
			
		||||
from orgs.mixins import OrgViewGenericMixin
 | 
			
		||||
from ..models import User, UserGroup
 | 
			
		||||
from common.permissions import AdminUserRequiredMixin
 | 
			
		||||
from ..models import User, UserGroup
 | 
			
		||||
from .. import forms
 | 
			
		||||
 | 
			
		||||
__all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +19,7 @@ __all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
 | 
			
		|||
logger = get_logger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupListView(AdminUserRequiredMixin, OrgViewGenericMixin, TemplateView):
 | 
			
		||||
class UserGroupListView(AdminUserRequiredMixin, TemplateView):
 | 
			
		||||
    template_name = 'users/user_group_list.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -33,8 +31,7 @@ class UserGroupListView(AdminUserRequiredMixin, OrgViewGenericMixin, TemplateVie
 | 
			
		|||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupCreateView(AdminUserRequiredMixin, OrgViewGenericMixin,
 | 
			
		||||
                          SuccessMessageMixin, CreateView):
 | 
			
		||||
class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
 | 
			
		||||
    model = UserGroup
 | 
			
		||||
    form_class = forms.UserGroupForm
 | 
			
		||||
    template_name = 'users/user_group_create_update.html'
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +47,7 @@ class UserGroupCreateView(AdminUserRequiredMixin, OrgViewGenericMixin,
 | 
			
		|||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin,
 | 
			
		||||
                          OrgViewGenericMixin, UpdateView):
 | 
			
		||||
class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
 | 
			
		||||
    model = UserGroup
 | 
			
		||||
    form_class = forms.UserGroupForm
 | 
			
		||||
    template_name = 'users/user_group_create_update.html'
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +67,7 @@ class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin,
 | 
			
		|||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupDetailView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailView):
 | 
			
		||||
class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
 | 
			
		||||
    model = UserGroup
 | 
			
		||||
    context_object_name = 'user_group'
 | 
			
		||||
    template_name = 'users/user_group_detail.html'
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +83,7 @@ class UserGroupDetailView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailVie
 | 
			
		|||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupGrantedAssetView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailView):
 | 
			
		||||
class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
 | 
			
		||||
    model = UserGroup
 | 
			
		||||
    template_name = 'users/user_group_granted_asset.html'
 | 
			
		||||
    context_object_name = 'user_group'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -308,7 +308,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
 | 
			
		|||
    file_storage = default_storage
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        if request.user.is_authenticated() and not request.user.is_first_login:
 | 
			
		||||
        if request.user.is_authenticated and not request.user.is_first_login:
 | 
			
		||||
            return redirect(reverse('index'))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ __all__ = [
 | 
			
		|||
logger = get_logger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserListView(TemplateView):
 | 
			
		||||
class UserListView(AdminUserRequiredMixin, TemplateView):
 | 
			
		||||
    template_name = 'users/user_list.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,8 @@ coreapi==2.3.3
 | 
			
		|||
coreschema==0.0.4
 | 
			
		||||
cryptography==2.1.4
 | 
			
		||||
decorator==4.1.2
 | 
			
		||||
Django==1.11
 | 
			
		||||
#Django==1.11
 | 
			
		||||
#Django==2.0.7
 | 
			
		||||
django-auth-ldap==1.3.0
 | 
			
		||||
django-bootstrap3==9.1.0
 | 
			
		||||
django-celery-beat==1.1.1
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +25,8 @@ django-ranged-response==0.2.0
 | 
			
		|||
django-redis-cache==1.7.1
 | 
			
		||||
django-rest-swagger==2.1.2
 | 
			
		||||
django-simple-captcha==0.5.6
 | 
			
		||||
djangorestframework==3.7.3
 | 
			
		||||
#djangorestframework==3.7.3
 | 
			
		||||
djangorestframework==3.8.2
 | 
			
		||||
djangorestframework-bulk==0.2.1
 | 
			
		||||
docutils==0.14
 | 
			
		||||
ecdsa==0.13
 | 
			
		||||
| 
						 | 
				
			
			@ -69,3 +71,4 @@ sshpubkeys==2.2.0
 | 
			
		|||
uritemplate==3.0.0
 | 
			
		||||
urllib3==1.22
 | 
			
		||||
vine==1.1.4
 | 
			
		||||
drf-yasg==1.9.1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue