diff --git a/apps/assets/api/__init__.py b/apps/assets/api/__init__.py index 4a41c0706..a1a3beee7 100644 --- a/apps/assets/api/__init__.py +++ b/apps/assets/api/__init__.py @@ -3,3 +3,4 @@ from .asset import * from .label import * from .system_user import * from .node import * +from .domain import * diff --git a/apps/assets/api/domain.py b/apps/assets/api/domain.py new file mode 100644 index 000000000..5114b5561 --- /dev/null +++ b/apps/assets/api/domain.py @@ -0,0 +1,55 @@ +# ~*~ coding: utf-8 ~*~ + +from rest_framework_bulk import BulkModelViewSet +from rest_framework.views import APIView, Response +from rest_framework.generics import RetrieveAPIView + +from django.views.generic.detail import SingleObjectMixin + +from common.utils import get_logger +from ..hands import IsSuperUser, IsSuperUserOrAppUser +from ..models import Domain, Gateway +from ..utils import test_gateway_connectability +from .. import serializers + + +logger = get_logger(__file__) +__all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"] + + +class DomainViewSet(BulkModelViewSet): + queryset = Domain.objects.all() + permission_classes = (IsSuperUser,) + serializer_class = serializers.DomainSerializer + + def get_serializer_class(self): + if self.request.query_params.get('gateway'): + return serializers.DomainWithGatewaySerializer + return super().get_serializer_class() + + def get_permissions(self): + if self.request.query_params.get('gateway'): + self.permission_classes = (IsSuperUserOrAppUser,) + return super().get_permissions() + + +class GatewayViewSet(BulkModelViewSet): + filter_fields = ("domain",) + search_fields = filter_fields + queryset = Gateway.objects.all() + permission_classes = (IsSuperUser,) + serializer_class = serializers.GatewaySerializer + + +class GatewayTestConnectionApi(SingleObjectMixin, APIView): + permission_classes = (IsSuperUser,) + model = Gateway + object = None + + def get(self, request, *args, **kwargs): + self.object = self.get_object(Gateway.objects.all()) + ok, e = test_gateway_connectability(self.object) + if ok: + return Response("ok") + else: + return Response({"failed": e}, status=404) diff --git a/apps/assets/forms/__init__.py b/apps/assets/forms/__init__.py index 9175d7c43..4eaa40948 100644 --- a/apps/assets/forms/__init__.py +++ b/apps/assets/forms/__init__.py @@ -3,3 +3,4 @@ from .asset import * from .label import * from .user import * +from .domain import * diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py index 65716f533..a6f488761 100644 --- a/apps/assets/forms/asset.py +++ b/apps/assets/forms/asset.py @@ -16,6 +16,7 @@ class AssetCreateForm(forms.ModelForm): fields = [ 'hostname', 'ip', 'public_ip', 'port', 'comment', 'nodes', 'is_active', 'admin_user', 'labels', 'platform', + 'domain', ] widgets = { @@ -29,6 +30,9 @@ class AssetCreateForm(forms.ModelForm): 'class': 'select2', 'data-placeholder': _('Labels') }), 'port': forms.TextInput(), + 'domain': forms.Select(attrs={ + 'class': 'select2', 'data-placeholder': _('Domain') + }), } help_texts = { 'hostname': '* required', @@ -38,7 +42,8 @@ class AssetCreateForm(forms.ModelForm): 'root or other NOPASSWD sudo privilege user existed in asset,' 'If asset is windows or other set any one, more see admin user left menu' ), - 'platform': _("* required Must set exact system platform, Windows, Linux ...") + 'platform': _("* required Must set exact system platform, Windows, Linux ..."), + 'domain': _("If your have some network not connect with each other, you can set domain") } @@ -48,6 +53,7 @@ class AssetUpdateForm(forms.ModelForm): fields = [ 'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform', 'public_ip', 'number', 'comment', 'admin_user', 'labels', + 'domain', ] widgets = { 'nodes': forms.SelectMultiple(attrs={ @@ -60,6 +66,9 @@ class AssetUpdateForm(forms.ModelForm): 'class': 'select2', 'data-placeholder': _('Labels') }), 'port': forms.TextInput(), + 'domain': forms.Select(attrs={ + 'class': 'select2', 'data-placeholder': _('Domain') + }), } help_texts = { 'hostname': '* required', @@ -70,7 +79,8 @@ class AssetUpdateForm(forms.ModelForm): 'root or other NOPASSWD sudo privilege user existed in asset,' 'If asset is windows or other set any one, more see admin user left menu' ), - 'platform': _("* required Must set exact system platform, Windows, Linux ...") + 'platform': _("* required Must set exact system platform, Windows, Linux ..."), + 'domain': _("If your have some network not connect with each other, you can set domain") } diff --git a/apps/assets/forms/domain.py b/apps/assets/forms/domain.py new file mode 100644 index 000000000..ec3af8f2e --- /dev/null +++ b/apps/assets/forms/domain.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ..models import Domain, Asset, Gateway +from .user import PasswordAndKeyAuthForm + +__all__ = ['DomainForm', 'GatewayForm'] + + +class DomainForm(forms.ModelForm): + assets = forms.ModelMultipleChoiceField( + queryset=Asset.objects.all(), label=_('Asset'), required=False, + widget=forms.SelectMultiple( + attrs={'class': 'select2', 'data-placeholder': _('Select assets')} + ) + ) + + class Meta: + model = Domain + fields = ['name', 'comment', 'assets'] + + def __init__(self, *args, **kwargs): + if kwargs.get('instance', None): + initial = kwargs.get('initial', {}) + initial['assets'] = kwargs['instance'].assets.all() + super().__init__(*args, **kwargs) + + def save(self, commit=True): + instance = super().save(commit=commit) + assets = self.cleaned_data['assets'] + instance.assets.set(assets) + return instance + + +class GatewayForm(PasswordAndKeyAuthForm): + + def save(self, commit=True): + # Because we define custom field, so we need rewrite :method: `save` + instance = super().save() + password = self.cleaned_data.get('password') + private_key, public_key = super().gen_keys() + instance.set_auth(password=password, private_key=private_key) + return instance + + class Meta: + model = Gateway + fields = [ + 'name', 'ip', 'port', 'username', 'protocol', 'domain', 'password', + 'private_key_file', 'is_active', 'comment', + ] + widgets = { + 'name': forms.TextInput(attrs={'placeholder': _('Name')}), + 'username': forms.TextInput(attrs={'placeholder': _('Username')}), + } + help_texts = { + 'name': '* required', + 'username': '* required', + } diff --git a/apps/assets/forms/user.py b/apps/assets/forms/user.py index 487d2714b..2295dc005 100644 --- a/apps/assets/forms/user.py +++ b/apps/assets/forms/user.py @@ -8,7 +8,7 @@ from common.utils import validate_ssh_private_key, ssh_pubkey_gen, get_logger logger = get_logger(__file__) __all__ = [ - 'FileForm', 'SystemUserForm', 'AdminUserForm', + 'FileForm', 'SystemUserForm', 'AdminUserForm', 'PasswordAndKeyAuthForm', ] diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index dbc703706..35c275b99 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -5,6 +5,7 @@ from .user import AdminUser, SystemUser from .label import Label from .cluster import * from .group import * +from .domain import * from .node import * from .asset import * from .utils import * diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 3f7dec4ec..b8c1f768e 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -4,14 +4,13 @@ import uuid import logging +import random from django.db import models from django.utils.translation import ugettext_lazy as _ from django.core.cache import cache from ..const import ASSET_ADMIN_CONN_CACHE_KEY -from .cluster import Cluster -from .group import AssetGroup from .user import AdminUser, SystemUser __all__ = ['Asset'] @@ -50,6 +49,7 @@ class Asset(models.Model): ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) port = models.IntegerField(default=22, verbose_name=_('Port')) + domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain")) nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes")) is_active = models.BooleanField(default=True, verbose_name=_('Is active')) @@ -122,12 +122,15 @@ class Asset(models.Model): return False def to_json(self): - return { + info = { 'id': self.id, 'hostname': self.hostname, 'ip': self.ip, 'port': self.port, } + if self.domain and self.domain.gateway_set.all(): + info["gateways"] = [d.id for d in self.domain.gateway_set.all()] + return info def _to_secret_json(self): """ @@ -168,7 +171,6 @@ class Asset(models.Model): try: asset.save() asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)] - asset.groups = [choice(AssetGroup.objects.all()) for i in range(3)] logger.debug('Generate fake asset : %s' % asset.ip) except IntegrityError: print('Error continue') diff --git a/apps/assets/models/base.py b/apps/assets/models/base.py new file mode 100644 index 000000000..ad2a3b904 --- /dev/null +++ b/apps/assets/models/base.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# +import os +import uuid +from hashlib import md5 + +import sshpubkeys +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from django.conf import settings + +from common.utils import get_signer, ssh_key_string_to_obj, ssh_key_gen +from .utils import private_key_validator + +signer = get_signer() + + +class AssetUser(models.Model): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) + username = models.CharField(max_length=128, verbose_name=_('Username')) + _password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) + _private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ]) + _public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + date_created = models.DateTimeField(auto_now_add=True) + date_updated = models.DateTimeField(auto_now=True) + created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) + + @property + def password(self): + if self._password: + return signer.unsign(self._password) + else: + return None + + @password.setter + def password(self, password_raw): + raise AttributeError("Using set_auth do that") + # self._password = signer.sign(password_raw) + + @property + def private_key(self): + if self._private_key: + return signer.unsign(self._private_key) + + @private_key.setter + def private_key(self, private_key_raw): + raise AttributeError("Using set_auth do that") + # self._private_key = signer.sign(private_key_raw) + + @property + def private_key_obj(self): + if self._private_key: + key_str = signer.unsign(self._private_key) + return ssh_key_string_to_obj(key_str, password=self.password) + else: + return None + + @property + def private_key_file(self): + if not self.private_key_obj: + return None + project_dir = settings.PROJECT_DIR + tmp_dir = os.path.join(project_dir, 'tmp') + key_str = signer.unsign(self._private_key) + key_name = '.' + md5(key_str.encode('utf-8')).hexdigest() + key_path = os.path.join(tmp_dir, key_name) + if not os.path.exists(key_path): + self.private_key_obj.write_private_key_file(key_path) + os.chmod(key_path, 0o400) + return key_path + + @property + def public_key(self): + key = signer.unsign(self._public_key) + if key: + return key + else: + return None + + @property + def public_key_obj(self): + if self.public_key: + try: + return sshpubkeys.SSHKey(self.public_key) + except TabError: + pass + return None + + def set_auth(self, password=None, private_key=None, public_key=None): + update_fields = [] + if password: + self._password = signer.sign(password) + update_fields.append('_password') + if private_key: + self._private_key = signer.sign(private_key) + update_fields.append('_private_key') + if public_key: + self._public_key = signer.sign(public_key) + update_fields.append('_public_key') + + if update_fields: + self.save(update_fields=update_fields) + + def auto_gen_auth(self): + password = str(uuid.uuid4()) + private_key, public_key = ssh_key_gen( + username=self.name, password=password + ) + self.set_auth(password=password, + private_key=private_key, + public_key=public_key) + + def _to_secret_json(self): + """Push system user use it""" + return { + 'name': self.name, + 'username': self.username, + 'password': self.password, + 'public_key': self.public_key, + 'private_key': self.private_key_file, + } + + class Meta: + abstract = True diff --git a/apps/assets/models/domain.py b/apps/assets/models/domain.py new file mode 100644 index 000000000..6f29a0381 --- /dev/null +++ b/apps/assets/models/domain.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# + +import uuid +import random + +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from .base import AssetUser + +__all__ = ['Domain', 'Gateway'] + + +class Domain(models.Model): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + date_created = models.DateTimeField(auto_now_add=True, null=True, + verbose_name=_('Date created')) + + def __str__(self): + return self.name + + def has_gateway(self): + return self.gateway_set.filter(is_active=True).exists() + + @property + def gateways(self): + return self.gateway_set.filter(is_active=True) + + def random_gateway(self): + return random.choice(self.gateways) + + +class Gateway(AssetUser): + SSH_PROTOCOL = 'ssh' + RDP_PROTOCOL = 'rdp' + PROTOCOL_CHOICES = ( + (SSH_PROTOCOL, 'ssh'), + (RDP_PROTOCOL, 'rdp'), + ) + 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")) + comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Comment")) + is_active = models.BooleanField(default=True, verbose_name=_("Is active")) + + def __str__(self): + return self.name + diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 7eaff63e6..541ef8b6a 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -2,20 +2,15 @@ # -*- coding: utf-8 -*- # -import os import logging -import uuid -from hashlib import md5 -import sshpubkeys from django.core.cache import cache from django.db import models from django.utils.translation import ugettext_lazy as _ -from django.conf import settings -from common.utils import get_signer, ssh_key_string_to_obj, ssh_key_gen -from .utils import private_key_validator +from common.utils import get_signer from ..const import SYSTEM_USER_CONN_CACHE_KEY +from .base import AssetUser __all__ = ['AdminUser', 'SystemUser',] @@ -23,117 +18,6 @@ logger = logging.getLogger(__name__) signer = get_signer() -class AssetUser(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) - username = models.CharField(max_length=128, verbose_name=_('Username')) - _password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - _private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ]) - _public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True) - date_updated = models.DateTimeField(auto_now=True) - created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) - - @property - def password(self): - if self._password: - return signer.unsign(self._password) - else: - return None - - @password.setter - def password(self, password_raw): - raise AttributeError("Using set_auth do that") - # self._password = signer.sign(password_raw) - - @property - def private_key(self): - if self._private_key: - return signer.unsign(self._private_key) - - @private_key.setter - def private_key(self, private_key_raw): - raise AttributeError("Using set_auth do that") - # self._private_key = signer.sign(private_key_raw) - - @property - def private_key_obj(self): - if self._private_key: - key_str = signer.unsign(self._private_key) - return ssh_key_string_to_obj(key_str, password=self.password) - else: - return None - - @property - def private_key_file(self): - if not self.private_key_obj: - return None - project_dir = settings.PROJECT_DIR - tmp_dir = os.path.join(project_dir, 'tmp') - key_str = signer.unsign(self._private_key) - key_name = '.' + md5(key_str.encode('utf-8')).hexdigest() - key_path = os.path.join(tmp_dir, key_name) - if not os.path.exists(key_path): - self.private_key_obj.write_private_key_file(key_path) - os.chmod(key_path, 0o400) - return key_path - - @property - def public_key(self): - key = signer.unsign(self._public_key) - if key: - return key - else: - return None - - @property - def public_key_obj(self): - if self.public_key: - try: - return sshpubkeys.SSHKey(self.public_key) - except TabError: - pass - return None - - def set_auth(self, password=None, private_key=None, public_key=None): - update_fields = [] - if password: - self._password = signer.sign(password) - update_fields.append('_password') - if private_key: - self._private_key = signer.sign(private_key) - update_fields.append('_private_key') - if public_key: - self._public_key = signer.sign(public_key) - update_fields.append('_public_key') - - if update_fields: - self.save(update_fields=update_fields) - - def auto_gen_auth(self): - password = str(uuid.uuid4()) - private_key, public_key = ssh_key_gen( - username=self.name, password=password - ) - self.set_auth(password=password, - private_key=private_key, - public_key=public_key) - - def _to_secret_json(self): - """Push system user use it""" - return { - 'name': self.name, - 'username': self.username, - 'password': self.password, - 'public_key': self.public_key, - 'private_key': self.private_key_file, - } - - class Meta: - abstract = True - - class AdminUser(AssetUser): """ A privileged user that ansible can use it to push system user and so on diff --git a/apps/assets/models/utils.py b/apps/assets/models/utils.py index a819715ab..11d347685 100644 --- a/apps/assets/models/utils.py +++ b/apps/assets/models/utils.py @@ -10,15 +10,15 @@ __all__ = ['init_model', 'generate_fake'] def init_model(): - from . import Cluster, SystemUser, AdminUser, AssetGroup, Asset - for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]: + from . import SystemUser, AdminUser, Asset + for cls in [SystemUser, AdminUser, Asset]: if hasattr(cls, 'initial'): cls.initial() def generate_fake(): - from . import Cluster, SystemUser, AdminUser, AssetGroup, Asset - for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]: + from . import SystemUser, AdminUser, Asset + for cls in [SystemUser, AdminUser, Asset]: if hasattr(cls, 'generate_fake'): cls.generate_fake() diff --git a/apps/assets/serializers/__init__.py b/apps/assets/serializers/__init__.py index c39d34767..111f070a7 100644 --- a/apps/assets/serializers/__init__.py +++ b/apps/assets/serializers/__init__.py @@ -6,3 +6,4 @@ from .admin_user import * from .label import * from .system_user import * from .node import * +from .domain import * diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index e479a7149..bcb3b81b1 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -38,7 +38,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer): model = Asset fields = ( "id", "hostname", "ip", "port", "system_users_granted", - "is_active", "system_users_join", "os", + "is_active", "system_users_join", "os", 'domain', "platform", "comment" ) diff --git a/apps/assets/serializers/cluster.py b/apps/assets/serializers/cluster.py deleted file mode 100644 index 43724a4a2..000000000 --- a/apps/assets/serializers/cluster.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# - -from rest_framework import serializers -from common.mixins import BulkSerializerMixin -from ..models import Asset, Cluster - - -class ClusterUpdateAssetsSerializer(serializers.ModelSerializer): - """ - 集群更新资产数据结构 - """ - assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) - - class Meta: - model = Cluster - fields = ['id', 'assets'] - - -class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer): - """ - cluster - """ - assets_amount = serializers.SerializerMethodField() - admin_user_name = serializers.SerializerMethodField() - assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) - system_users = serializers.SerializerMethodField() - - class Meta: - model = Cluster - fields = '__all__' - - @staticmethod - def get_assets_amount(obj): - return obj.assets.count() - - @staticmethod - def get_admin_user_name(obj): - try: - return obj.admin_user.name - except AttributeError: - return '' - - @staticmethod - def get_system_users(obj): - return ', '.join(obj.name for obj in obj.systemuser_set.all()) diff --git a/apps/assets/serializers/domain.py b/apps/assets/serializers/domain.py new file mode 100644 index 000000000..034c29387 --- /dev/null +++ b/apps/assets/serializers/domain.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +from rest_framework import serializers + +from ..models import Domain, Gateway + + +class DomainSerializer(serializers.ModelSerializer): + asset_count = serializers.SerializerMethodField() + gateway_count = serializers.SerializerMethodField() + + class Meta: + model = Domain + fields = '__all__' + + @staticmethod + def get_asset_count(obj): + return obj.assets.count() + + @staticmethod + def get_gateway_count(obj): + return obj.gateway_set.all().count() + + +class GatewaySerializer(serializers.ModelSerializer): + + class Meta: + model = Gateway + fields = [ + 'id', 'name', 'ip', 'port', 'protocol', 'username', + 'domain', 'is_active', 'date_created', 'date_updated', + 'created_by', 'comment', + ] + + +class GatewayWithAuthSerializer(GatewaySerializer): + def get_field_names(self, declared_fields, info): + fields = super().get_field_names(declared_fields, info) + fields.extend( + ['password', 'private_key'] + ) + return fields + + +class DomainWithGatewaySerializer(serializers.ModelSerializer): + gateways = GatewayWithAuthSerializer(many=True, read_only=True) + + class Meta: + model = Domain + fields = '__all__' diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 0cf5cbfd8..50a57a806 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -3,6 +3,7 @@ import json import re import os +import paramiko from celery import shared_task from django.core.cache import cache from django.utils.translation import ugettext as _ @@ -12,7 +13,7 @@ from common.utils import get_object_or_none, capacity_convert, \ from common.celery import register_as_period_task, after_app_shutdown_clean, \ after_app_ready_start, app as celery_app -from .models import SystemUser, AdminUser, Asset, Cluster +from .models import SystemUser, AdminUser, Asset from . import const @@ -438,3 +439,7 @@ def push_node_system_users_to_asset(node, assets): # def push_system_user_period(): # for system_user in SystemUser.objects.all(): # push_system_user_related_nodes(system_user) + + + + diff --git a/apps/assets/templates/assets/asset_create.html b/apps/assets/templates/assets/asset_create.html index 1eae7ebd4..7f01e0530 100644 --- a/apps/assets/templates/assets/asset_create.html +++ b/apps/assets/templates/assets/asset_create.html @@ -19,6 +19,7 @@ {% bootstrap_field form.port layout="horizontal" %} {% bootstrap_field form.platform layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %} + {% bootstrap_field form.domain layout="horizontal" %}

{% trans 'Auth' %}

diff --git a/apps/assets/templates/assets/asset_update.html b/apps/assets/templates/assets/asset_update.html index 5d8006451..3e96438bc 100644 --- a/apps/assets/templates/assets/asset_update.html +++ b/apps/assets/templates/assets/asset_update.html @@ -24,6 +24,7 @@ {% bootstrap_field form.port layout="horizontal" %} {% bootstrap_field form.platform layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %} + {% bootstrap_field form.domain layout="horizontal" %}

{% trans 'Auth' %}

diff --git a/apps/assets/templates/assets/domain_create_update.html b/apps/assets/templates/assets/domain_create_update.html new file mode 100644 index 000000000..36ca40fc1 --- /dev/null +++ b/apps/assets/templates/assets/domain_create_update.html @@ -0,0 +1,31 @@ +{% extends '_base_create_update.html' %} +{% load static %} +{% load bootstrap3 %} +{% load i18n %} + +{% block form %} +
+ {% csrf_token %} + {% bootstrap_field form.name layout="horizontal" %} + {% bootstrap_field form.assets layout="horizontal" %} + {% bootstrap_field form.comment layout="horizontal" %} + +
+
+
+ + +
+
+
+{% endblock %} + +{% block custom_foot_js %} + +{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/domain_detail.html b/apps/assets/templates/assets/domain_detail.html new file mode 100644 index 000000000..e60daa334 --- /dev/null +++ b/apps/assets/templates/assets/domain_detail.html @@ -0,0 +1,132 @@ +{% extends 'base.html' %} +{% load static %} +{% load i18n %} + +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+ +
+
+
+
+ {{ object.name }} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'Name' %}:{{ object.name }}
{% trans 'Asset' %}:{{ object.assets.count }}
{% trans 'Gateway' %}:{{ object.gateway_set.count }}
{% trans 'Date created' %}:{{ object.date_created }}
{% trans 'Created by' %}:{{ object.created_by }}
{% trans 'Comment' %}:{{ object.comment }}
+
+
+
+
+
+
+
+
+{% endblock %} +{% block content_bottom_left %}{% endblock %} +{% block custom_foot_js %} + +{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/domain_gateway_list.html b/apps/assets/templates/assets/domain_gateway_list.html new file mode 100644 index 000000000..1f25e6ac1 --- /dev/null +++ b/apps/assets/templates/assets/domain_gateway_list.html @@ -0,0 +1,131 @@ +{% extends 'base.html' %} +{% load static %} +{% load i18n %} + +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+ +
+
+
+
+
+
+ {% trans 'Gateway list' %} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + +
+ + {% trans 'Name' %}{% trans 'IP' %}{% trans 'Port' %}{% trans 'Protocol' %}{% trans 'Username' %}{% trans 'Comment' %}{% trans 'Action' %}
+
+
+
+
+
+
+
+
+{% endblock %} +{% block content_bottom_left %}{% endblock %} +{% block custom_foot_js %} + +{% endblock %} diff --git a/apps/assets/templates/assets/domain_list.html b/apps/assets/templates/assets/domain_list.html new file mode 100644 index 000000000..03b671bf3 --- /dev/null +++ b/apps/assets/templates/assets/domain_list.html @@ -0,0 +1,70 @@ +{% extends '_base_list.html' %} +{% load i18n static %} +{% block table_search %}{% endblock %} +{% block table_container %} +
+ {% trans "Create domain" %} +
+ + + + + + + + + + + + + +
+ + {% trans 'Name' %}{% trans 'Asset' %}{% trans 'Gateway' %}{% trans 'Comment' %}{% trans 'Action' %}
+{% endblock %} +{% block content_bottom_left %}{% endblock %} +{% block custom_foot_js %} + +{% endblock %} + + + diff --git a/apps/assets/templates/assets/gateway_create_update.html b/apps/assets/templates/assets/gateway_create_update.html new file mode 100644 index 000000000..7d6800c41 --- /dev/null +++ b/apps/assets/templates/assets/gateway_create_update.html @@ -0,0 +1,68 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load bootstrap3 %} +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+
+
{{ action }}
+ +
+
+
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} +

{% trans 'Basic' %}

+ {% bootstrap_field form.name layout="horizontal" %} + {% bootstrap_field form.ip layout="horizontal" %} + {% bootstrap_field form.port layout="horizontal" %} + {% bootstrap_field form.protocol layout="horizontal" %} + {% bootstrap_field form.domain layout="horizontal" %} + + {% block auth %} +

{% trans 'Auth' %}

+
+ {% bootstrap_field form.username layout="horizontal" %} + {% bootstrap_field form.password layout="horizontal" %} + {% bootstrap_field form.private_key_file layout="horizontal" %} +
+ {% endblock %} + +

{% trans 'Other' %}

+ {% bootstrap_field form.is_active layout="horizontal" %} + {% bootstrap_field form.comment layout="horizontal" %} +
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index 28d792bd2..b74b402cf 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -206,7 +206,7 @@ {% endblock %} {% block custom_foot_js %}