Commit 2cd092af authored by ibuler's avatar ibuler

[Update] 修改资产创建格式

parent 10616b8d
...@@ -40,8 +40,8 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, ApiMessageMixin, BulkModel ...@@ -40,8 +40,8 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, ApiMessageMixin, BulkModel
""" """
API endpoint that allows Asset to be viewed or edited. API endpoint that allows Asset to be viewed or edited.
""" """
filter_fields = ("hostname", "ip") filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id")
search_fields = filter_fields search_fields = ("hostname", "ip")
ordering_fields = ("hostname", "ip", "port", "cpu_cores") ordering_fields = ("hostname", "ip", "port", "cpu_cores")
queryset = Asset.objects.all() queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer serializer_class = serializers.AssetSerializer
......
...@@ -96,7 +96,7 @@ class AssetUserViewSet(IDInCacheFilterMixin, BulkModelViewSet): ...@@ -96,7 +96,7 @@ class AssetUserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
assets = [asset] assets = [asset]
elif node_id: elif node_id:
node = get_object_or_404(Node, id=node_id) node = get_object_or_404(Node, id=node_id)
assets = node.assets.all() assets = node.get_all_assets()
if username: if username:
kwargs['username'] = username kwargs['username'] = username
......
...@@ -74,7 +74,7 @@ class Protocol(models.Model): ...@@ -74,7 +74,7 @@ class Protocol(models.Model):
validators=PORT_VALIDATORS) validators=PORT_VALIDATORS)
def __str__(self): def __str__(self):
return "{}:{}".format(self.name, self.port) return "{}/{}".format(self.name, self.port)
class Asset(OrgModelMixin): class Asset(OrgModelMixin):
......
...@@ -30,8 +30,8 @@ class AssetUser(OrgModelMixin): ...@@ -30,8 +30,8 @@ class AssetUser(OrgModelMixin):
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ]) _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')) _public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
comment = models.TextField(blank=True, verbose_name=_('Comment')) comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True) date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True) date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
UNREACHABLE, REACHABLE, UNKNOWN = range(0, 3) UNREACHABLE, REACHABLE, UNKNOWN = range(0, 3)
......
...@@ -22,8 +22,25 @@ class ProtocolSerializer(serializers.ModelSerializer): ...@@ -22,8 +22,25 @@ class ProtocolSerializer(serializers.ModelSerializer):
fields = ["name", "port"] fields = ["name", "port"]
class ProtocolsRelatedField(serializers.RelatedField):
def to_representation(self, value):
return str(value)
def to_internal_value(self, data):
if '/' not in data:
raise ValidationError("protocol not contain /: {}".format(data))
v = data.split("/")
if len(v) != 2:
raise ValidationError("protocol format should be name/port: {}".format(data))
name, port = v
cleaned_data = {"name": name, "port": port}
return cleaned_data
class AssetSerializer(BulkOrgResourceModelSerializer): class AssetSerializer(BulkOrgResourceModelSerializer):
protocols = ProtocolSerializer(many=True) protocols = ProtocolsRelatedField(
many=True, queryset=Protocol.objects.all(), label=_("Protocols")
)
""" """
资产的数据结构 资产的数据结构
...@@ -47,6 +64,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer): ...@@ -47,6 +64,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
'created_by', 'date_created', 'created_by', 'date_created',
) )
extra_kwargs = { extra_kwargs = {
'protocol': {'write_only': True},
'port': {'write_only': True},
'hardware_info': {'label': _('Hardware info')}, 'hardware_info': {'label': _('Hardware info')},
'connectivity': {'label': _('Connectivity')}, 'connectivity': {'label': _('Connectivity')},
'org_name': {'label': _('Org name')} 'org_name': {'label': _('Org name')}
...@@ -61,6 +80,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer): ...@@ -61,6 +80,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
@staticmethod @staticmethod
def validate_protocols(attr): def validate_protocols(attr):
protocols_serializer = ProtocolSerializer(data=attr, many=True)
protocols_serializer.is_valid(raise_exception=True)
protocols_name = [i.get("name", "ssh") for i in attr] protocols_name = [i.get("name", "ssh") for i in attr]
errors = [{} for i in protocols_name] errors = [{} for i in protocols_name]
for i, name in enumerate(protocols_name): for i, name in enumerate(protocols_name):
...@@ -71,7 +92,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer): ...@@ -71,7 +92,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
return attr return attr
def create(self, validated_data): def create(self, validated_data):
protocols_data = validated_data.pop("protocols") protocols_data = validated_data.pop("protocols", [])
# 兼容老的api # 兼容老的api
protocol = validated_data.get("protocol") protocol = validated_data.get("protocol")
...@@ -91,7 +112,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer): ...@@ -91,7 +112,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
protocols_data = validated_data.pop("protocols", None) protocols_data = validated_data.pop("protocols", [])
# 兼容老的api # 兼容老的api
protocol = validated_data.get("protocol") protocol = validated_data.get("protocol")
......
...@@ -7,7 +7,6 @@ from rest_framework import serializers ...@@ -7,7 +7,6 @@ from rest_framework import serializers
from ..models import AuthBook, Asset from ..models import AuthBook, Asset
from ..backends import AssetUserManager from ..backends import AssetUserManager
from common.utils import validate_ssh_private_key from common.utils import validate_ssh_private_key
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer from orgs.mixins import BulkOrgResourceModelSerializer
......
...@@ -35,11 +35,10 @@ ...@@ -35,11 +35,10 @@
</div> </div>
</div> </div>
</form> </form>
{% include 'authentication/_mfa_confirm_modal.html' %}
<script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script> <script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script>
<script> <script>
var showPassword = false; var showPassword = false;
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
var authAssetId = ""; var authAssetId = "";
var authHostname = ""; var authHostname = "";
var authUsername = ""; var authUsername = "";
...@@ -90,25 +89,6 @@ $(document).ready(function () { ...@@ -90,25 +89,6 @@ $(document).ready(function () {
$("#id_password_view").attr("type", "password") $("#id_password_view").attr("type", "password")
} }
}).on("show.bs.modal", "#asset_user_auth_view", function () { }).on("show.bs.modal", "#asset_user_auth_view", function () {
var now = new Date();
if (lastMFATime === "") {
lastMFATime = 0
}
var nowTime = now.getTime() / 1000;
if (nowTime - lastMFATime > 60*10 ) {
setTimeout(function () {
$("#asset_user_auth_view").modal("hide");
}, 100);
mfaFor = "viewAuth";
$("#mfa_auth_confirm").modal("show");
} else {
showAuth();
}
}).on("success", '#mfa_auth_confirm', function () {
if (mfaFor !== "viewAuth") {
return
}
$("#asset_user_auth_view").modal("show");
showAuth(); showAuth();
}) })
</script> </script>
......
...@@ -25,12 +25,14 @@ ...@@ -25,12 +25,14 @@
</table> </table>
{% include 'assets/_asset_user_auth_update_modal.html' %} {% include 'assets/_asset_user_auth_update_modal.html' %}
{% include 'assets/_asset_user_auth_view_modal.html' %} {% include 'assets/_asset_user_auth_view_modal.html' %}
{% include 'authentication/_mfa_confirm_modal.html' %}
<script> <script>
var assetUserListUrl = "{% url "api-assets:asset-user-list" %}"; var assetUserListUrl = "{% url "api-assets:asset-user-list" %}";
var assetUserTable; var assetUserTable;
var needPush = false; var needPush = false;
var prefer = null; var prefer = null;
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
function initAssetUserTable() { function initAssetUserTable() {
var options = { var options = {
...@@ -98,7 +100,20 @@ $(document).ready(function(){ ...@@ -98,7 +100,20 @@ $(document).ready(function(){
authAssetId = $(this).data("asset") ; authAssetId = $(this).data("asset") ;
authHostname = $(this).data("hostname"); authHostname = $(this).data("hostname");
authUsername = $(this).data('user'); authUsername = $(this).data('user');
$("#asset_user_auth_view").modal('show'); var now = new Date();
var nowTime = now.getTime() / 1000;
if (nowTime - lastMFATime > 60*10 ) {
mfaFor = "viewAuth";
$("#mfa_auth_confirm").modal("show");
} else {
$("#asset_user_auth_view").modal('show');
}
})
.on("success", '#mfa_auth_confirm', function () {
if (mfaFor !== "viewAuth") {
return
}
$("#asset_user_auth_view").modal("show");
}) })
.on('click', '.btn-update-auth', function() { .on('click', '.btn-update-auth', function() {
authUsername = $(this).data("user") ; authUsername = $(this).data("user") ;
...@@ -126,4 +141,5 @@ $(document).ready(function(){ ...@@ -126,4 +141,5 @@ $(document).ready(function(){
}); });
}) })
</script> </script>
\ No newline at end of file
...@@ -201,49 +201,47 @@ $(document).ready(function () { ...@@ -201,49 +201,47 @@ $(document).ready(function () {
} }
$(this).parent().parent().find(".protocol-port").val(port); $(this).parent().parent().find(".protocol-port").val(port);
}) })
</script> .on("submit", "form", function (evt) {
{% block form_submit %} evt.preventDefault();
<script> {% block formUrl %}
$(document).ready(function () { var the_url = '{% url 'api-assets:asset-list' %}';
}) var redirect_to = '{% url "assets:asset-list" %}';
.on("submit", "form", function (evt) { var method = "POST";
evt.preventDefault(); {% endblock %}
var the_url = '{% url 'api-assets:asset-list' %}'; var form = $("form");
var redirect_to = '{% url "assets:asset-list" %}'; var protocols = {};
var form = $("form"); var data = form.serializeObject();
var protocols = {}; $.each(data, function (k, v) {
var data = form.serializeObject(); if (k.startsWith("form")){
$.each(data, function (k, v) { delete data[k];
if (k.startsWith("form")){ var _k = k.split("-");
delete data[k]; var formName = _k.slice(0, 2).join("-");
var _k = k.split("-"); var key = _k[_k.length-1];
var formName = _k.slice(0, 2).join("-"); if (!protocols[formName]) {
var key = _k[_k.length-1]; protocols[formName] = {}
if (!protocols[formName]) {
protocols[formName] = {}
}
protocols[formName][key] = v
} }
}); protocols[formName][key] = v
protocols = $.map(protocols, function ( v) {
return v
});
data["protocols"] = protocols;
if (typeof data.labels === "string") {
data["labels"] = [data["labels"]];
}
if (typeof data["nodes"] == "string") {
data["nodes"] = [data["nodes"]]
} }
var props = { });
url: the_url,
data: data, protocols = $.map(protocols, function (v) {
method: "POST", return v.name + '/' + v.port
form: form, });
redirect_to: redirect_to data["protocols"] = protocols;
}; if (typeof data.labels === "string") {
formSubmit(props); data["labels"] = [data["labels"]];
}) }
</script> if (typeof data["nodes"] == "string") {
data["nodes"] = [data["nodes"]]
}
var props = {
url: the_url,
data: data,
method: method,
form: form,
redirect_to: redirect_to
};
formSubmit(props);
})
</script>
{% endblock %} {% endblock %}
{% endblock %}
\ No newline at end of file
...@@ -72,8 +72,7 @@ ...@@ -72,8 +72,7 @@
<td>{% trans 'Protocol' %}</td> <td>{% trans 'Protocol' %}</td>
<td> <td>
{% for protocol in asset.protocols.all %} {% for protocol in asset.protocols.all %}
<b>{{ protocol.name }}:</b> <b>{{ protocol }}</b>
{{ protocol.port }}
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>
......
...@@ -8,47 +8,8 @@ ...@@ -8,47 +8,8 @@
{% bootstrap_field form.number layout="horizontal" %} {% bootstrap_field form.number layout="horizontal" %}
{% endblock %} {% endblock %}
{% block form_submit %} {% block formUrl %}
<script>
$(document).ready(function () {
})
.on("submit", "form", function (evt) {
evt.preventDefault();
var the_url = '{% url 'api-assets:asset-detail' pk=object.id %}'; var the_url = '{% url 'api-assets:asset-detail' pk=object.id %}';
var redirect_to = '{% url "assets:asset-list" %}'; var redirect_to = '{% url "assets:asset-list" %}';
var form = $("form"); var method = 'PUT';
var protocols = {};
var data = form.serializeObject();
$.each(data, function (k, v) {
if (k.startsWith("form")){
delete data[k];
var _k = k.split("-");
var formName = _k.slice(0, 2).join("-");
var key = _k[_k.length-1];
if (!protocols[formName]) {
protocols[formName] = {}
}
protocols[formName][key] = v
}
});
protocols = $.map(protocols, function ( v) {
return v
});
data["protocols"] = protocols;
if (typeof data.labels === "string") {
data["labels"] = [data["labels"]];
}
if (typeof data["nodes"] == "string") {
data["nodes"] = [data["nodes"]]
}
var props = {
url: the_url,
data: data,
method: "PUT",
form: form,
redirect_to: redirect_to
};
formSubmit(props);
});
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -22,32 +22,6 @@ ...@@ -22,32 +22,6 @@
</div> </div>
</form> </form>
<script> <script>
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
function showAuth() {
$(".mfa-field").hide();
$(".auth-field").show();
var url = "{% url "api-assets:asset-user-auth-info" %}?asset_id=" + asset_id + "&username=" + username;
$("#id_username_view").html(username);
$("#id_hostname_view").html(host);
var success = function (data) {
var password = data.password;
$("#id_password_view").val(password);
};
var error = function() {
var msg = "{% trans 'Get auth info error' %}";
toastr.error(msg)
};
APIUpdateAttr({
url: url,
method: "GET",
success: success,
flash_message: false,
error: error
})
}
var codeError = "{% trans 'Code error' %}"; var codeError = "{% trans 'Code error' %}";
$(document).ready(function () { $(document).ready(function () {
......
...@@ -216,7 +216,10 @@ class ApiMessageMixin: ...@@ -216,7 +216,10 @@ class ApiMessageMixin:
data = {k: v for k, v in cleaned_data.items()} data = {k: v for k, v in cleaned_data.items()}
action = getattr(self, "action", "create") action = getattr(self, "action", "create")
data["action"] = self._action_map.get(action) data["action"] = self._action_map.get(action)
message = self.success_message % data try:
message = self.success_message % data
except:
message = ''
return message return message
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
......
This diff is collapsed.
# coding: utf-8 # coding: utf-8
import os import os
import subprocess import subprocess
import datetime
from django.conf import settings from django.conf import settings
from celery import shared_task, subtask from celery import shared_task, subtask
...@@ -105,10 +106,10 @@ def hello(name, callback=None): ...@@ -105,10 +106,10 @@ def hello(name, callback=None):
@shared_task @shared_task
@after_app_shutdown_clean_periodic # @after_app_shutdown_clean_periodic
@register_as_period_task(interval=30) # @register_as_period_task(interval=30)
def hello123(): def hello123():
print("Hello world") print("{} Hello world".format(datetime.datetime.now().strftime("%H:%M:%S")))
@shared_task @shared_task
......
...@@ -219,7 +219,8 @@ class OrgResourceSerializerMixin(serializers.Serializer): ...@@ -219,7 +219,8 @@ class OrgResourceSerializerMixin(serializers.Serializer):
由于HiddenField字段不可读,API获取资产信息时获取不到org_id, 由于HiddenField字段不可读,API获取资产信息时获取不到org_id,
但是coco需要资产的org_id字段,所以修改为CharField类型 但是coco需要资产的org_id字段,所以修改为CharField类型
""" """
org_id = serializers.ReadOnlyField(default=get_current_org_id) org_id = serializers.ReadOnlyField(default=get_current_org_id, label=_("Organization"))
org_name = serializers.ReadOnlyField(label=_("Org name"))
def get_validators(self): def get_validators(self):
_validators = super().get_validators() _validators = super().get_validators()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment