Commit 2cd092af authored by ibuler's avatar ibuler

[Update] 修改资产创建格式

parent 10616b8d
......@@ -40,8 +40,8 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, ApiMessageMixin, BulkModel
"""
API endpoint that allows Asset to be viewed or edited.
"""
filter_fields = ("hostname", "ip")
search_fields = filter_fields
filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id")
search_fields = ("hostname", "ip")
ordering_fields = ("hostname", "ip", "port", "cpu_cores")
queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer
......
......@@ -96,7 +96,7 @@ class AssetUserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
assets = [asset]
elif node_id:
node = get_object_or_404(Node, id=node_id)
assets = node.assets.all()
assets = node.get_all_assets()
if username:
kwargs['username'] = username
......
......@@ -74,7 +74,7 @@ class Protocol(models.Model):
validators=PORT_VALIDATORS)
def __str__(self):
return "{}:{}".format(self.name, self.port)
return "{}/{}".format(self.name, self.port)
class Asset(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, ])
_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)
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
UNREACHABLE, REACHABLE, UNKNOWN = range(0, 3)
......
......@@ -22,8 +22,25 @@ class ProtocolSerializer(serializers.ModelSerializer):
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):
protocols = ProtocolSerializer(many=True)
protocols = ProtocolsRelatedField(
many=True, queryset=Protocol.objects.all(), label=_("Protocols")
)
"""
资产的数据结构
......@@ -47,6 +64,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
'created_by', 'date_created',
)
extra_kwargs = {
'protocol': {'write_only': True},
'port': {'write_only': True},
'hardware_info': {'label': _('Hardware info')},
'connectivity': {'label': _('Connectivity')},
'org_name': {'label': _('Org name')}
......@@ -61,6 +80,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
@staticmethod
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]
errors = [{} for i in protocols_name]
for i, name in enumerate(protocols_name):
......@@ -71,7 +92,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
return attr
def create(self, validated_data):
protocols_data = validated_data.pop("protocols")
protocols_data = validated_data.pop("protocols", [])
# 兼容老的api
protocol = validated_data.get("protocol")
......@@ -91,7 +112,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
return instance
def update(self, instance, validated_data):
protocols_data = validated_data.pop("protocols", None)
protocols_data = validated_data.pop("protocols", [])
# 兼容老的api
protocol = validated_data.get("protocol")
......
......@@ -7,7 +7,6 @@ from rest_framework import serializers
from ..models import AuthBook, Asset
from ..backends import AssetUserManager
from common.utils import validate_ssh_private_key
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
......
......@@ -35,11 +35,10 @@
</div>
</div>
</form>
{% include 'authentication/_mfa_confirm_modal.html' %}
<script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script>
<script>
var showPassword = false;
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
var authAssetId = "";
var authHostname = "";
var authUsername = "";
......@@ -90,25 +89,6 @@ $(document).ready(function () {
$("#id_password_view").attr("type", "password")
}
}).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();
})
</script>
......
......@@ -25,12 +25,14 @@
</table>
{% include 'assets/_asset_user_auth_update_modal.html' %}
{% include 'assets/_asset_user_auth_view_modal.html' %}
{% include 'authentication/_mfa_confirm_modal.html' %}
<script>
var assetUserListUrl = "{% url "api-assets:asset-user-list" %}";
var assetUserTable;
var needPush = false;
var prefer = null;
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
function initAssetUserTable() {
var options = {
......@@ -98,7 +100,20 @@ $(document).ready(function(){
authAssetId = $(this).data("asset") ;
authHostname = $(this).data("hostname");
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() {
authUsername = $(this).data("user") ;
......@@ -126,4 +141,5 @@ $(document).ready(function(){
});
})
</script>
\ No newline at end of file
......@@ -201,49 +201,47 @@ $(document).ready(function () {
}
$(this).parent().parent().find(".protocol-port").val(port);
})
</script>
{% block form_submit %}
<script>
$(document).ready(function () {
})
.on("submit", "form", function (evt) {
evt.preventDefault();
var the_url = '{% url 'api-assets:asset-list' %}';
var redirect_to = '{% url "assets:asset-list" %}';
var form = $("form");
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
.on("submit", "form", function (evt) {
evt.preventDefault();
{% block formUrl %}
var the_url = '{% url 'api-assets:asset-list' %}';
var redirect_to = '{% url "assets:asset-list" %}';
var method = "POST";
{% endblock %}
var form = $("form");
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 = $.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"]]
protocols[formName][key] = v
}
var props = {
url: the_url,
data: data,
method: "POST",
form: form,
redirect_to: redirect_to
};
formSubmit(props);
})
</script>
});
protocols = $.map(protocols, function (v) {
return v.name + '/' + v.port
});
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: method,
form: form,
redirect_to: redirect_to
};
formSubmit(props);
})
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
......@@ -72,8 +72,7 @@
<td>{% trans 'Protocol' %}</td>
<td>
{% for protocol in asset.protocols.all %}
<b>{{ protocol.name }}:</b>
{{ protocol.port }}
<b>{{ protocol }}</b>
{% endfor %}
</td>
</tr>
......
......@@ -8,47 +8,8 @@
{% bootstrap_field form.number layout="horizontal" %}
{% endblock %}
{% block form_submit %}
<script>
$(document).ready(function () {
})
.on("submit", "form", function (evt) {
evt.preventDefault();
{% block formUrl %}
var the_url = '{% url 'api-assets:asset-detail' pk=object.id %}';
var redirect_to = '{% url "assets:asset-list" %}';
var form = $("form");
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>
var method = 'PUT';
{% endblock %}
\ No newline at end of file
......@@ -22,32 +22,6 @@
</div>
</form>
<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' %}";
$(document).ready(function () {
......
......@@ -216,7 +216,10 @@ class ApiMessageMixin:
data = {k: v for k, v in cleaned_data.items()}
action = getattr(self, "action", "create")
data["action"] = self._action_map.get(action)
message = self.success_message % data
try:
message = self.success_message % data
except:
message = ''
return message
def dispatch(self, request, *args, **kwargs):
......
This diff is collapsed.
# coding: utf-8
import os
import subprocess
import datetime
from django.conf import settings
from celery import shared_task, subtask
......@@ -105,10 +106,10 @@ def hello(name, callback=None):
@shared_task
@after_app_shutdown_clean_periodic
@register_as_period_task(interval=30)
# @after_app_shutdown_clean_periodic
# @register_as_period_task(interval=30)
def hello123():
print("Hello world")
print("{} Hello world".format(datetime.datetime.now().strftime("%H:%M:%S")))
@shared_task
......
......@@ -219,7 +219,8 @@ class OrgResourceSerializerMixin(serializers.Serializer):
由于HiddenField字段不可读,API获取资产信息时获取不到org_id,
但是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):
_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