* [Update] 添加org api, 升级到django 2.0

* [Update] fix some bug

* [Update] 修改一些bug
pull/1580/head^2
老广 2018-07-24 22:21:12 -05:00 committed by GitHub
parent c816875f28
commit b156f4ad16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 200 additions and 87 deletions

View File

@ -2,8 +2,9 @@
# #
import random import random
import time
from rest_framework import generics from rest_framework import generics, permissions
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView
@ -39,9 +40,10 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
queryset = Asset.objects.all() queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer serializer_class = serializers.AssetSerializer
pagination_class = LimitOffsetPagination pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (permissions.AllowAny,)
def get_queryset(self): def get_queryset(self):
time.sleep(3)
queryset = super().get_queryset()\ queryset = super().get_queryset()\
.prefetch_related('labels', 'nodes')\ .prefetch_related('labels', 'nodes')\
.select_related('admin_user') .select_related('admin_user')

View File

@ -2,12 +2,11 @@
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from rest_framework.views import APIView, Response from rest_framework.views import APIView, Response
from rest_condition import Or
from django.views.generic.detail import SingleObjectMixin from django.views.generic.detail import SingleObjectMixin
from common.utils import get_logger 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 ..models import Domain, Gateway
from ..utils import test_gateway_connectability from ..utils import test_gateway_connectability
from .. import serializers from .. import serializers

View File

@ -44,7 +44,7 @@ class Gateway(AssetUser):
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
port = models.IntegerField(default=22, verbose_name=_('Port')) port = models.IntegerField(default=22, verbose_name=_('Port'))
protocol = models.CharField(choices=PROTOCOL_CHOICES, max_length=16, default=SSH_PROTOCOL, verbose_name=_("Protocol")) 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")) comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Comment"))
is_active = models.BooleanField(default=True, verbose_name=_("Is active")) is_active = models.BooleanField(default=True, verbose_name=_("Is active"))

View File

@ -35,6 +35,20 @@
.dropdown a:hover { .dropdown a:hover {
background-color: #f1f1f1 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> </style>
{% endblock %} {% endblock %}

View File

@ -44,7 +44,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
template_name = 'assets/asset_list.html' template_name = 'assets/asset_list.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
print(Node.root().name) Node.root()
context = { context = {
'app': _('Assets'), 'app': _('Assets'),
'action': _('Asset list'), 'action': _('Asset list'),

View File

@ -86,7 +86,18 @@ class LDAPTestingAPI(APIView):
class DjangoSettingsAPI(APIView): class DjangoSettingsAPI(APIView):
def get(self, request): 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)

View File

@ -3,6 +3,8 @@
from rest_framework import permissions from rest_framework import permissions
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import redirect
from django.http.response import HttpResponseForbidden
from orgs.utils import current_org from orgs.utils import current_org
@ -23,6 +25,18 @@ class IsAppUser(IsValidUser):
and request.user.is_app 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): class IsOrgAdmin(IsValidUser):
"""Allows access only to superuser""" """Allows access only to superuser"""
@ -63,3 +77,18 @@ class AdminUserRequiredMixin(UserPassesTestMixin):
self.raise_exception = True self.raise_exception = True
return False return False
return True 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)

View File

@ -9,5 +9,5 @@ app_name = 'common'
urlpatterns = [ urlpatterns = [
url(r'^mail/testing/$', api.MailTestingAPI.as_view(), name='mail-testing'), url(r'^mail/testing/$', api.MailTestingAPI.as_view(), name='mail-testing'),
url(r'^ldap/testing/$', api.LDAPTestingAPI.as_view(), name='ldap-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'),
] ]

View File

@ -66,6 +66,7 @@ INSTALLED_APPS = [
'audits.apps.AuditsConfig', 'audits.apps.AuditsConfig',
'rest_framework', 'rest_framework',
'rest_framework_swagger', 'rest_framework_swagger',
'drf_yasg',
'django_filters', 'django_filters',
'bootstrap3', 'bootstrap3',
'captcha', 'captcha',
@ -230,7 +231,7 @@ LOGGING = {
'level': LOG_LEVEL, 'level': LOG_LEVEL,
}, },
'django_auth_ldap': { 'django_auth_ldap': {
'handlers': ['console', 'ansible_logs'], 'handlers': ['console', 'file'],
'level': "INFO", 'level': "INFO",
}, },
# 'django.db': { # 'django.db': {
@ -294,6 +295,7 @@ REST_FRAMEWORK = {
'common.permissions.IsOrgAdmin', 'common.permissions.IsOrgAdmin',
), ),
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'users.authentication.AccessKeyAuthentication', 'users.authentication.AccessKeyAuthentication',
'users.authentication.AccessTokenAuthentication', 'users.authentication.AccessTokenAuthentication',
'users.authentication.PrivateTokenAuthentication', 'users.authentication.PrivateTokenAuthentication',
@ -375,7 +377,7 @@ CACHES = {
'password': CONFIG.REDIS_PASSWORD if CONFIG.REDIS_PASSWORD else '', 'password': CONFIG.REDIS_PASSWORD if CONFIG.REDIS_PASSWORD else '',
'host': CONFIG.REDIS_HOST or '127.0.0.1', 'host': CONFIG.REDIS_HOST or '127.0.0.1',
'port': CONFIG.REDIS_PORT or 6379, '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 DISPLAY_PER_PAGE = CONFIG.DISPLAY_PER_PAGE or 25
DEFAULT_EXPIRED_YEARS = 70 DEFAULT_EXPIRED_YEARS = 70
USER_GUIDE_URL = "" USER_GUIDE_URL = ""
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'basic': {
'type': 'basic'
}
},
}

View File

@ -9,13 +9,28 @@ from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse from django.http import HttpResponse
from django.utils.encoding import iri_to_uri from django.utils.encoding import iri_to_uri
from rest_framework import permissions
from rest_framework.schemas import get_schema_view # from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer # 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 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>.*)$') 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: if settings.DEBUG:
urlpatterns += [ 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'),
] ]

View File

@ -4,16 +4,15 @@ from django.http import HttpResponse
from django.views.generic import TemplateView, View from django.views.generic import TemplateView, View
from django.utils import timezone from django.utils import timezone
from django.db.models import Count from django.db.models import Count
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect from django.shortcuts import redirect
from users.models import User from users.models import User
from assets.models import Asset from assets.models import Asset
from terminal.models import Session 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' template_name = 'index.html'
session_week = None session_week = None

View File

@ -19,6 +19,8 @@ class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all() queryset = Task.objects.all()
serializer_class = TaskSerializer serializer_class = TaskSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
label = None
help_text = ''
class TaskRun(generics.RetrieveAPIView): class TaskRun(generics.RetrieveAPIView):

14
apps/orgs/api.py Normal file
View File

@ -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,)

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from threading import local
from django.db import models from django.db import models
from django.shortcuts import redirect from django.shortcuts import redirect
import warnings import warnings
@ -11,9 +13,6 @@ from .utils import current_org, set_current_org
from .models import Organization from .models import Organization
logger = get_logger(__file__) logger = get_logger(__file__)
from threading import local
tl = local() tl = local()
__all__ = [ __all__ = [
@ -73,7 +72,7 @@ class OrgModelMixin(models.Model):
class OrgViewGenericMixin: class OrgViewGenericMixin:
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
print("Crrent org: {}".format(current_org)) print("Current org: {}".format(current_org))
if not current_org: if not current_org:
return redirect('orgs:switch-a-org') return redirect('orgs:switch-a-org')
@ -83,6 +82,8 @@ class OrgViewGenericMixin:
print("Is org admin") print("Is org admin")
return redirect('orgs:switch-a-org') return redirect('orgs:switch-a-org')
return HttpResponseForbidden() return HttpResponseForbidden()
else:
print(current_org.can_admin_by(request.user))
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

10
apps/orgs/serializers.py Normal file
View File

@ -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']

View File

@ -2,10 +2,17 @@
# #
from django.conf.urls import url from django.conf.urls import url
from .. import views
from rest_framework.routers import DefaultRouter
from .. import api
app_name = 'orgs' app_name = 'orgs'
router = DefaultRouter()
router.register(r'orgs', api.OrgViewSet, 'org')
urlpatterns = [ urlpatterns = [
# url(r'^(?P<pk>[0-9a-zA-Z\-]{36})/$', views.OrgDetailView.as_view(), name='asset-index') ]
]
urlpatterns += router.urls

View File

@ -16,6 +16,8 @@ _thread_locals = local()
def get_org_from_request(request): def get_org_from_request(request):
oid = request.session.get("oid") oid = request.session.get("oid")
if not oid:
oid = request.META.get("HTTP_X_JMS_ORG")
org = Organization.get_instance(oid) org = Organization.get_instance(oid)
return org return org

View File

@ -250,6 +250,8 @@ function initTree() {
{#$.fn.zTree.init($("#assetTree"), setting);#} {#$.fn.zTree.init($("#assetTree"), setting);#}
$.fn.zTree.init($("#assetTree"), setting, zNodes); $.fn.zTree.init($("#assetTree"), setting, zNodes);
zTree = $.fn.zTree.getZTreeObj("assetTree"); zTree = $.fn.zTree.getZTreeObj("assetTree");
var root = zTree.getNodes()[0];
zTree.expandNode(root);
{#selectQueryNode();#} {#selectQueryNode();#}
}); });
} }

View File

@ -250,6 +250,22 @@ function makeLabel(data) {
var jumpserver = {}; var jumpserver = {};
jumpserver.checked = false; jumpserver.checked = false;
jumpserver.selected = {}; 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) { jumpserver.initDataTable = function (options) {
// options = { // options = {
// ele *: $('#dataTable_id'), // ele *: $('#dataTable_id'),
@ -293,21 +309,7 @@ jumpserver.initDataTable = function (options) {
}, },
columns: options.columns || [], columns: options.columns || [],
select: options.select || select, select: options.select || select,
language: { language: jumpserver.language,
search: "搜索",
lengthMenu: "每页 _MENU_",
info: "显示第 _START_ 至 _END_ 项结果; 总共 _TOTAL_ 项",
infoFiltered: "",
infoEmpty: "",
zeroRecords: "没有匹配项",
emptyTable: "没有记录",
paginate: {
first: "«",
previous: "",
next: "",
last: "»"
}
},
lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]] lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
}); });
table.on('select', function(e, dt, type, indexes) { table.on('select', function(e, dt, type, indexes) {
@ -343,6 +345,16 @@ jumpserver.initDataTable = function (options) {
return table; return table;
}; };
jumpserver.initStaticTable = function (selector) {
$(selector).DataTable({
"searching": false,
"bInfo": false,
"paging": false,
"order": [],
"language": jumpserver.language
});
};
jumpserver.initServerSideDataTable = function (options) { jumpserver.initServerSideDataTable = function (options) {
// options = { // options = {
// ele *: $('#dataTable_id'), // ele *: $('#dataTable_id'),
@ -374,11 +386,11 @@ jumpserver.initServerSideDataTable = function (options) {
selector: 'td:first-child' selector: 'td:first-child'
}; };
var table = ele.DataTable({ var table = ele.DataTable({
pageLength: options.pageLength || 15, // 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>>', // 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 || [], // order: options.order || [],
// select: options.select || 'multi', // select: options.select || 'multi',
buttons: [], // buttons: [],
columnDefs: columnDefs, columnDefs: columnDefs,
serverSide: true, serverSide: true,
processing: true, processing: true,
@ -432,21 +444,7 @@ jumpserver.initServerSideDataTable = function (options) {
}, },
columns: options.columns || [], columns: options.columns || [],
select: options.select || select, select: options.select || select,
language: { language: jumpserver.language,
search: "搜索",
lengthMenu: "每页 _MENU_",
info: "显示第 _START_ 至 _END_ 项结果; 总共 _TOTAL_ 项",
infoFiltered: "",
infoEmpty: "",
zeroRecords: "没有匹配项",
emptyTable: "没有记录",
paginate: {
first: "«",
previous: "",
next: "",
last: "»"
}
},
lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]] lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]]
}); });
table.selected = []; table.selected = [];

View File

@ -64,9 +64,12 @@
<span class="nav-label">{% trans 'Web terminal' %}</span> <span class="nav-label">{% trans 'Web terminal' %}</span>
</a> </a>
</li> </li>
{% if request.user.is_superuser %}
<li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li> <li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li>
{% endif %}
</ul> </ul>
</li> </li>
{% if request.user.is_superuser %}
<li id="ops"> <li id="ops">
<a> <a>
<i class="fa fa-coffee" style="width: 14px"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span> <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> <li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task list' %}</a></li>
</ul> </ul>
</li> </li>
{% endif %}
<li id="audits"> <li id="audits">
<a> <a>
<i class="fa fa-history" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span> <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>#} {# <li id="download"><a href="">{% trans 'File download' %}</a></li>#}
{# </ul>#} {# </ul>#}
{#</li>#} {#</li>#}
{% if request.user.is_superuser %}
<li id="settings"> <li id="settings">
<a href="{% url 'settings:basic-setting' %}"> <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> <i class="fa fa-gears"></i> <span class="nav-label">{% trans 'Settings' %}</span><span class="label label-info pull-right"></span>
</a> </a>
</li> </li>
{% endif %}
<script> <script>
$(document).ready(function () { $(document).ready(function () {

View File

@ -150,12 +150,7 @@
}); });
} }
$(document).ready(function() { $(document).ready(function() {
$('table').DataTable({ jumpserver.initStaticTable('table');
"searching": false,
"paging": false,
"bInfo" : false,
"order": []
});
$('.select2').select2({ $('.select2').select2({
dropdownAutoWidth: true, dropdownAutoWidth: true,
width: "auto" width: "auto"

View File

@ -10,10 +10,10 @@ from .. import api
app_name = 'terminal' app_name = 'terminal'
router = routers.DefaultRouter() 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})?/?status', api.StatusViewSet, 'terminal-status')
router.register(r'terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions') 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'tasks', api.TaskViewSet, 'tasks')
router.register(r'terminal', api.TerminalViewSet, 'terminal')
router.register(r'command', api.CommandViewSet, 'command') router.register(r'command', api.CommandViewSet, 'command')
router.register(r'sessions', api.SessionViewSet, 'session') router.register(r'sessions', api.SessionViewSet, 'session')
router.register(r'status', api.StatusViewSet, 'session') router.register(r'status', api.StatusViewSet, 'session')

View File

@ -195,7 +195,7 @@ class User(AbstractUser):
@property @property
def is_org_admin(self): def is_org_admin(self):
if self.is_superuser or self.admin_orgs: if self.is_superuser or self.admin_orgs.exists():
return True return True
else: else:
return False return False
@ -223,7 +223,7 @@ class User(AbstractUser):
self.is_active = True self.is_active = True
super().save(*args, **kwargs) super().save(*args, **kwargs)
if current_org and current_org.is_real(): if current_org and current_org.is_real():
self.orgs.add(current_org) self.orgs.add(current_org.id)
@property @property
def private_token(self): def private_token(self):

View File

@ -80,12 +80,7 @@
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script> <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$('table').DataTable({ jumpserver.initStaticTable('table');
"searching": false,
"bInfo" : false,
"paging": false,
"order": []
});
$('#date .input-daterange').datepicker({ $('#date .input-daterange').datepicker({
format: "yyyy-mm-dd", format: "yyyy-mm-dd",
todayBtn: "linked", todayBtn: "linked",

View File

@ -1,7 +1,6 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic.base import TemplateView 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.utils import get_logger
from common.const import create_success_msg, update_success_msg 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 common.permissions import AdminUserRequiredMixin
from ..models import User, UserGroup
from .. import forms from .. import forms
__all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView', __all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
@ -21,7 +19,7 @@ __all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
logger = get_logger(__name__) logger = get_logger(__name__)
class UserGroupListView(AdminUserRequiredMixin, OrgViewGenericMixin, TemplateView): class UserGroupListView(AdminUserRequiredMixin, TemplateView):
template_name = 'users/user_group_list.html' template_name = 'users/user_group_list.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -33,8 +31,7 @@ class UserGroupListView(AdminUserRequiredMixin, OrgViewGenericMixin, TemplateVie
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class UserGroupCreateView(AdminUserRequiredMixin, OrgViewGenericMixin, class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
SuccessMessageMixin, CreateView):
model = UserGroup model = UserGroup
form_class = forms.UserGroupForm form_class = forms.UserGroupForm
template_name = 'users/user_group_create_update.html' template_name = 'users/user_group_create_update.html'
@ -50,8 +47,7 @@ class UserGroupCreateView(AdminUserRequiredMixin, OrgViewGenericMixin,
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
OrgViewGenericMixin, UpdateView):
model = UserGroup model = UserGroup
form_class = forms.UserGroupForm form_class = forms.UserGroupForm
template_name = 'users/user_group_create_update.html' template_name = 'users/user_group_create_update.html'
@ -71,7 +67,7 @@ class UserGroupUpdateView(AdminUserRequiredMixin, SuccessMessageMixin,
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class UserGroupDetailView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailView): class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
model = UserGroup model = UserGroup
context_object_name = 'user_group' context_object_name = 'user_group'
template_name = 'users/user_group_detail.html' template_name = 'users/user_group_detail.html'
@ -87,7 +83,7 @@ class UserGroupDetailView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailVie
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class UserGroupGrantedAssetView(AdminUserRequiredMixin, OrgViewGenericMixin, DetailView): class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
model = UserGroup model = UserGroup
template_name = 'users/user_group_granted_asset.html' template_name = 'users/user_group_granted_asset.html'
context_object_name = 'user_group' context_object_name = 'user_group'

View File

@ -308,7 +308,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
file_storage = default_storage file_storage = default_storage
def dispatch(self, request, *args, **kwargs): 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 redirect(reverse('index'))
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

View File

@ -57,7 +57,7 @@ __all__ = [
logger = get_logger(__name__) logger = get_logger(__name__)
class UserListView(TemplateView): class UserListView(AdminUserRequiredMixin, TemplateView):
template_name = 'users/user_list.html' template_name = 'users/user_list.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):

View File

@ -14,7 +14,8 @@ coreapi==2.3.3
coreschema==0.0.4 coreschema==0.0.4
cryptography==2.1.4 cryptography==2.1.4
decorator==4.1.2 decorator==4.1.2
Django==1.11 #Django==1.11
#Django==2.0.7
django-auth-ldap==1.3.0 django-auth-ldap==1.3.0
django-bootstrap3==9.1.0 django-bootstrap3==9.1.0
django-celery-beat==1.1.1 django-celery-beat==1.1.1
@ -24,7 +25,8 @@ django-ranged-response==0.2.0
django-redis-cache==1.7.1 django-redis-cache==1.7.1
django-rest-swagger==2.1.2 django-rest-swagger==2.1.2
django-simple-captcha==0.5.6 django-simple-captcha==0.5.6
djangorestframework==3.7.3 #djangorestframework==3.7.3
djangorestframework==3.8.2
djangorestframework-bulk==0.2.1 djangorestframework-bulk==0.2.1
docutils==0.14 docutils==0.14
ecdsa==0.13 ecdsa==0.13
@ -69,3 +71,4 @@ sshpubkeys==2.2.0
uritemplate==3.0.0 uritemplate==3.0.0
urllib3==1.22 urllib3==1.22
vine==1.1.4 vine==1.1.4
drf-yasg==1.9.1