Skip to content

Commit 0ca1446

Browse files
authored
Merge pull request jumpserver#1147 from jumpserver/dev
支持网域功能
2 parents 15b74da + e4c2aff commit 0ca1446

64 files changed

Lines changed: 1588 additions & 544 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/assets/api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from .label import *
44
from .system_user import *
55
from .node import *
6+
from .domain import *

apps/assets/api/admin_user.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828

2929
logger = get_logger(__file__)
3030
__all__ = [
31-
'AdminUserViewSet', 'ReplaceNodesAdminUserApi', 'AdminUserTestConnectiveApi'
31+
'AdminUserViewSet', 'ReplaceNodesAdminUserApi',
32+
'AdminUserTestConnectiveApi', 'AdminUserAuthApi',
3233
]
3334

3435

@@ -41,6 +42,12 @@ class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
4142
permission_classes = (IsSuperUser,)
4243

4344

45+
class AdminUserAuthApi(generics.UpdateAPIView):
46+
queryset = AdminUser.objects.all()
47+
serializer_class = serializers.AdminUserAuthSerializer
48+
permission_classes = (IsSuperUser,)
49+
50+
4451
class ReplaceNodesAdminUserApi(generics.UpdateAPIView):
4552
queryset = AdminUser.objects.all()
4653
serializer_class = serializers.ReplaceNodeAdminUserSerializer

apps/assets/api/domain.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# ~*~ coding: utf-8 ~*~
2+
3+
from rest_framework_bulk import BulkModelViewSet
4+
from rest_framework.views import APIView, Response
5+
from rest_framework.generics import RetrieveAPIView
6+
7+
from django.views.generic.detail import SingleObjectMixin
8+
9+
from common.utils import get_logger
10+
from ..hands import IsSuperUser, IsSuperUserOrAppUser
11+
from ..models import Domain, Gateway
12+
from ..utils import test_gateway_connectability
13+
from .. import serializers
14+
15+
16+
logger = get_logger(__file__)
17+
__all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"]
18+
19+
20+
class DomainViewSet(BulkModelViewSet):
21+
queryset = Domain.objects.all()
22+
permission_classes = (IsSuperUser,)
23+
serializer_class = serializers.DomainSerializer
24+
25+
def get_serializer_class(self):
26+
if self.request.query_params.get('gateway'):
27+
return serializers.DomainWithGatewaySerializer
28+
return super().get_serializer_class()
29+
30+
def get_permissions(self):
31+
if self.request.query_params.get('gateway'):
32+
self.permission_classes = (IsSuperUserOrAppUser,)
33+
return super().get_permissions()
34+
35+
36+
class GatewayViewSet(BulkModelViewSet):
37+
filter_fields = ("domain",)
38+
search_fields = filter_fields
39+
queryset = Gateway.objects.all()
40+
permission_classes = (IsSuperUser,)
41+
serializer_class = serializers.GatewaySerializer
42+
43+
44+
class GatewayTestConnectionApi(SingleObjectMixin, APIView):
45+
permission_classes = (IsSuperUser,)
46+
model = Gateway
47+
object = None
48+
49+
def get(self, request, *args, **kwargs):
50+
self.object = self.get_object(Gateway.objects.all())
51+
ok, e = test_gateway_connectability(self.object)
52+
if ok:
53+
return Response("ok")
54+
else:
55+
return Response({"failed": e}, status=404)

apps/assets/api/system_user.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,6 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView):
4848
permission_classes = (IsSuperUserOrAppUser,)
4949
serializer_class = serializers.SystemUserAuthSerializer
5050

51-
def update(self, request, *args, **kwargs):
52-
password = request.data.pop("password", None)
53-
private_key = request.data.pop("private_key", None)
54-
instance = self.get_object()
55-
56-
if password or private_key:
57-
instance.set_auth(password=password, private_key=private_key)
58-
return super().update(request, *args, **kwargs)
59-
6051

6152
class SystemUserPushApi(generics.RetrieveAPIView):
6253
"""

apps/assets/forms/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from .asset import *
44
from .label import *
55
from .user import *
6+
from .domain import *

apps/assets/forms/asset.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Meta:
1616
fields = [
1717
'hostname', 'ip', 'public_ip', 'port', 'comment',
1818
'nodes', 'is_active', 'admin_user', 'labels', 'platform',
19+
'domain',
1920

2021
]
2122
widgets = {
@@ -29,6 +30,9 @@ class Meta:
2930
'class': 'select2', 'data-placeholder': _('Labels')
3031
}),
3132
'port': forms.TextInput(),
33+
'domain': forms.Select(attrs={
34+
'class': 'select2', 'data-placeholder': _('Domain')
35+
}),
3236
}
3337
help_texts = {
3438
'hostname': '* required',
@@ -38,7 +42,8 @@ class Meta:
3842
'root or other NOPASSWD sudo privilege user existed in asset,'
3943
'If asset is windows or other set any one, more see admin user left menu'
4044
),
41-
'platform': _("* required Must set exact system platform, Windows, Linux ...")
45+
'platform': _("* required Must set exact system platform, Windows, Linux ..."),
46+
'domain': _("If your have some network not connect with each other, you can set domain")
4247
}
4348

4449

@@ -48,6 +53,7 @@ class Meta:
4853
fields = [
4954
'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform',
5055
'public_ip', 'number', 'comment', 'admin_user', 'labels',
56+
'domain',
5157
]
5258
widgets = {
5359
'nodes': forms.SelectMultiple(attrs={
@@ -60,6 +66,9 @@ class Meta:
6066
'class': 'select2', 'data-placeholder': _('Labels')
6167
}),
6268
'port': forms.TextInput(),
69+
'domain': forms.Select(attrs={
70+
'class': 'select2', 'data-placeholder': _('Domain')
71+
}),
6372
}
6473
help_texts = {
6574
'hostname': '* required',
@@ -70,7 +79,8 @@ class Meta:
7079
'root or other NOPASSWD sudo privilege user existed in asset,'
7180
'If asset is windows or other set any one, more see admin user left menu'
7281
),
73-
'platform': _("* required Must set exact system platform, Windows, Linux ...")
82+
'platform': _("* required Must set exact system platform, Windows, Linux ..."),
83+
'domain': _("If your have some network not connect with each other, you can set domain")
7484
}
7585

7686

apps/assets/forms/domain.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
from django import forms
4+
from django.utils.translation import gettext_lazy as _
5+
6+
from ..models import Domain, Asset, Gateway
7+
from .user import PasswordAndKeyAuthForm
8+
9+
__all__ = ['DomainForm', 'GatewayForm']
10+
11+
12+
class DomainForm(forms.ModelForm):
13+
assets = forms.ModelMultipleChoiceField(
14+
queryset=Asset.objects.all(), label=_('Asset'), required=False,
15+
widget=forms.SelectMultiple(
16+
attrs={'class': 'select2', 'data-placeholder': _('Select assets')}
17+
)
18+
)
19+
20+
class Meta:
21+
model = Domain
22+
fields = ['name', 'comment', 'assets']
23+
24+
def __init__(self, *args, **kwargs):
25+
if kwargs.get('instance', None):
26+
initial = kwargs.get('initial', {})
27+
initial['assets'] = kwargs['instance'].assets.all()
28+
super().__init__(*args, **kwargs)
29+
30+
def save(self, commit=True):
31+
instance = super().save(commit=commit)
32+
assets = self.cleaned_data['assets']
33+
instance.assets.set(assets)
34+
return instance
35+
36+
37+
class GatewayForm(PasswordAndKeyAuthForm):
38+
39+
def save(self, commit=True):
40+
# Because we define custom field, so we need rewrite :method: `save`
41+
instance = super().save()
42+
password = self.cleaned_data.get('password')
43+
private_key, public_key = super().gen_keys()
44+
instance.set_auth(password=password, private_key=private_key)
45+
return instance
46+
47+
class Meta:
48+
model = Gateway
49+
fields = [
50+
'name', 'ip', 'port', 'username', 'protocol', 'domain', 'password',
51+
'private_key_file', 'is_active', 'comment',
52+
]
53+
widgets = {
54+
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
55+
'username': forms.TextInput(attrs={'placeholder': _('Username')}),
56+
}
57+
help_texts = {
58+
'name': '* required',
59+
'username': '* required',
60+
}

apps/assets/forms/user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
logger = get_logger(__file__)
1010
__all__ = [
11-
'FileForm', 'SystemUserForm', 'AdminUserForm',
11+
'FileForm', 'SystemUserForm', 'AdminUserForm', 'PasswordAndKeyAuthForm',
1212
]
1313

1414

apps/assets/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .label import Label
66
from .cluster import *
77
from .group import *
8+
from .domain import *
89
from .node import *
910
from .asset import *
1011
from .utils import *

apps/assets/models/asset.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44

55
import uuid
66
import logging
7+
import random
78

89
from django.db import models
910
from django.utils.translation import ugettext_lazy as _
1011
from django.core.cache import cache
1112

1213
from ..const import ASSET_ADMIN_CONN_CACHE_KEY
13-
from .cluster import Cluster
14-
from .group import AssetGroup
1514
from .user import AdminUser, SystemUser
1615

1716
__all__ = ['Asset']
@@ -50,6 +49,7 @@ class Asset(models.Model):
5049
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
5150
hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
5251
port = models.IntegerField(default=22, verbose_name=_('Port'))
52+
domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"))
5353
nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes"))
5454
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
5555

@@ -122,12 +122,15 @@ def is_connective(self):
122122
return False
123123

124124
def to_json(self):
125-
return {
125+
info = {
126126
'id': self.id,
127127
'hostname': self.hostname,
128128
'ip': self.ip,
129129
'port': self.port,
130130
}
131+
if self.domain and self.domain.gateway_set.all():
132+
info["gateways"] = [d.id for d in self.domain.gateway_set.all()]
133+
return info
131134

132135
def _to_secret_json(self):
133136
"""
@@ -168,7 +171,6 @@ def generate_fake(cls, count=100):
168171
try:
169172
asset.save()
170173
asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)]
171-
asset.groups = [choice(AssetGroup.objects.all()) for i in range(3)]
172174
logger.debug('Generate fake asset : %s' % asset.ip)
173175
except IntegrityError:
174176
print('Error continue')

0 commit comments

Comments
 (0)