Unverified Commit 3855fecc authored by 老广's avatar 老广 Committed by GitHub

Password message (#2702)

* [Update] 密码信封

* [Update]  查看密码

* [Update] 支持查看密码

* [Update] 修改语言翻译

* [Update] 迁移ansible到2.8版本

* [Update] 修改auth book的可连接性

* [Update] 删除不使用的方法
parent 466b922e
...@@ -78,7 +78,7 @@ class AuthBook(AssetUser): ...@@ -78,7 +78,7 @@ class AuthBook(AssetUser):
if host == self.asset.hostname: if host == self.asset.hostname:
_connectivity = self.UNREACHABLE _connectivity = self.UNREACHABLE
for host in value.get('contacted', {}).keys(): for host in value.get('contacted', []):
if host == self.asset.hostname: if host == self.asset.hostname:
_connectivity = self.REACHABLE _connectivity = self.REACHABLE
......
{% extends '_modal.html' %}
{% load i18n %}
{% load static %}
{% block modal_id %}asset_user_auth_view{% endblock %}
{% block modal_title%}{% trans "Asset user auth" %}{% endblock %}
{% block modal_body %}
<style>
.inmodal .modal-body {
background: #fff;
}
</style>
<form class="form-horizontal" action="" style="padding-top: 20px">
<div class="form-group mfa-field">
<label for="mfa" class="col-sm-2 control-label">{% trans 'MFA' %}</label>
<div class="col-sm-8">
<input type="text" id="mfa" class="form-control input-sm" name="mfa">
<span id="mfa_error" class="help-block">{% trans "Need otp auth for view auth" %}</span>
</div>
<div class="col-sm-2">
<a class="btn btn-primary btn-sm btn-mfa">{% trans "Confirm" %}</a>
</div>
</div>
<div hidden class="auth-field">
<div class="form-group">
<label for="" class="col-sm-2 control-label">{% trans 'Hostname' %}</label>
<div class="col-sm-8">
<p class="form-control-static" id="id_hostname_view"></p>
</div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">{% trans 'Username' %}</label>
<div class="col-sm-8" >
<p class="form-control-static" id="id_username_view"></p>
</div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">{% trans 'Password' %}</label>
<div class="col-sm-8">
<input id="id_password_view" type="password" class="form-control" value="" readonly style="border: none;padding-left: 0;background-color: #fff;width: 100%">
</div>
<div class="col-sm-2" style="padding-left: 2px">
<a class="btn btn-white btn-sm btn-show-password"><i class="fa fa-eye"></i></a>
<a class="btn btn-white btn-sm btn-copy-password"><i class="fa fa-copy"></i></a>
</div>
</div>
</div>
</form>
<script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script>
<script>
var showPassword = false;
var lastMFATime = "{{ request.session.OTP_LAST_VERIFY_TIME }}";
var asset_id = "";
var host = "";
var username = "";
function initClipboard() {
var clipboard = new Clipboard('.btn-copy-password', {
text: function (trigger) {
return $("#id_password_view").val()
}
});
clipboard.on("success", function (e) {
toastr.success("{% trans "Copy success" %}")
})
}
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
})
}
function showMFA() {
$(".mfa-field").show();
$(".auth-field").hide();
}
$(document).ready(function () {
initClipboard();
}).on("click", ".btn-show-password", function () {
showPassword = !showPassword;
if (showPassword) {
$("#id_password_view").attr("type", "text")
} else {
$("#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 ) {
showAuth();
}
}).on("click", ".btn-mfa", function () {
var url = "{% url 'api-auth:user-otp-verify' %}";
var data = {
code: $("#mfa").val()
};
var success = function () {
var now = new Date();
lastMFATime = now.getTime() / 1000;
showAuth()
};
var error = function () {
$("#mfa_error").addClass("error").html("Code error");
};
APIUpdateAttr({
url: url,
method: "POST",
body: JSON.stringify(data),
success: success,
flash_message: false,
error: error
})
})
</script>
{% endblock %}
{% block modal_button %}
<button data-dismiss="modal" class="btn btn-white close_btn2" type="button">{% trans "Close" %}</button>
{% endblock %}
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
</div> </div>
</div> </div>
{% include 'assets/_asset_user_auth_modal.html' %} {% include 'assets/_asset_user_auth_modal.html' %}
{% include 'assets/_asset_user_view_auth_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
...@@ -112,9 +113,12 @@ function initTable() { ...@@ -112,9 +113,12 @@ function initTable() {
} }
}}, }},
{targets: 4, createdCell: function (td, cellData, rowData) { {targets: 4, createdCell: function (td, cellData, rowData) {
var btn = ' <a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "Update auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname);
var view_btn = ' <a class="btn btn-xs btn-primary btn-view-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "View auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname);
var test_btn = ' <a class="btn btn-xs btn-info btn-test-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Test" %}</a>'.replace("{{ DEFAULT_PK }}", cellData); var test_btn = ' <a class="btn btn-xs btn-info btn-test-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Test" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
var update_auth_btn = ' <a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "Update auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname); btn += view_btn;
$(td).html(test_btn + update_auth_btn); btn += test_btn;
$(td).html(btn);
}} }}
], ],
...@@ -201,5 +205,11 @@ $(document).ready(function () { ...@@ -201,5 +205,11 @@ $(document).ready(function () {
$('#id_password').parent().addClass('has-error'); $('#id_password').parent().addClass('has-error');
} }
}) })
.on("click", ".btn-view-auth", function (evt) {
asset_id = $(this).data("aid") ;
host = $(this).data("hostname");
username = "{{ admin_user.username }}";
$("#asset_user_auth_view").modal();
})
</script> </script>
{% endblock %} {% endblock %}
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
{% load common_tags %} {% load common_tags %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% block custom_head_css_js %}
{% endblock %}
{% block content %} {% block content %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
...@@ -87,6 +83,7 @@ ...@@ -87,6 +83,7 @@
</div> </div>
</div> </div>
{% include 'assets/_asset_user_auth_modal.html' %} {% include 'assets/_asset_user_auth_modal.html' %}
{% include 'assets/_asset_user_view_auth_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
...@@ -117,14 +114,14 @@ function initAssetUserTable() { ...@@ -117,14 +114,14 @@ function initAssetUserTable() {
$(td).html(cellData.slice(0, -6)); $(td).html(cellData.slice(0, -6));
}}, }},
{targets: 5, createdCell: function (td, cellData) { {targets: 5, createdCell: function (td, cellData) {
var update_auth_btn = ' <a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-username="DEFAULT_USERNAME">{% trans "Update auth" %}</a>'.replace("DEFAULT_USERNAME", cellData); var btn = '<a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-username="DEFAULT_USERNAME">{% trans "Update auth" %}</a>'.replace("DEFAULT_USERNAME", cellData);
var view_btn = ' <a class="btn btn-xs btn-primary btn-view-auth" data-username="DEFAULT_USERNAME">{% trans "View auth" %}</a>'.replace("DEFAULT_USERNAME", cellData);
var test_btn = ' <a class="btn btn-xs btn-info btn-test-connective" data-username="DEFAULT_USERNAME">{% trans "Test" %}</a>'.replace("DEFAULT_USERNAME", cellData);
btn += view_btn;
{% if asset.protocol == 'ssh' %} {% if asset.protocol == 'ssh' %}
var test_btn = ' <a class="btn btn-xs btn-info btn-test-connective" data-username="DEFAULT_USERNAME">{% trans "Test" %}</a>'.replace("DEFAULT_USERNAME", cellData); btn += test_btn;
$(td).html(test_btn + update_auth_btn);
{% else %}
$(td).html(update_auth_btn);
{% endif %} {% endif %}
{#var check_btn = ' <a class="btn btn-xs btn-info btn-check-asset-user-auth" data-username="DEFAULT_USERNAME">{% trans "Check auth" %}</a>'.replace("DEFAULT_USERNAME", cellData);#} $(td).html(btn);
}} }}
], ],
...@@ -142,17 +139,6 @@ var username; ...@@ -142,17 +139,6 @@ var username;
$(document).ready(function () { $(document).ready(function () {
initAssetUserTable(); initAssetUserTable();
}) })
{#.on('click', '.btn-check-asset-user-auth', function(){#}
{# var username = $(this).data('username');#}
{# var the_url = "{% url 'api-assets:asset-user-auth-info' %}" + '?asset_id={{ asset.id }}' + '&username=' + username;#}
{# $.ajax({#}
{# url: the_url,#}
{# method: 'GET',#}
{# success: function (data) {#}
{# alert("Password: " + data.password);#}
{# }#}
{# });#}
{# })#}
.on('click', '.btn-update-asset-user-auth', function() { .on('click', '.btn-update-asset-user-auth', function() {
username = $(this).data('username'); username = $(this).data('username');
var hostname = "{{ asset.hostname }}"; var hostname = "{{ asset.hostname }}";
...@@ -214,5 +200,11 @@ $(document).ready(function () { ...@@ -214,5 +200,11 @@ $(document).ready(function () {
flash_message: false flash_message: false
}); });
}) })
.on("click", ".btn-view-auth", function (evt) {
asset_id = "{{ asset.id }}" ;
host = "{{ asset.hostname }}";
username = $(this).data("username");
$("#asset_user_auth_view").modal();
})
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -133,6 +133,7 @@ ...@@ -133,6 +133,7 @@
</div> </div>
</div> </div>
{% include 'assets/_asset_user_auth_modal.html' %} {% include 'assets/_asset_user_auth_modal.html' %}
{% include 'assets/_asset_user_view_auth_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
...@@ -160,12 +161,13 @@ function initAssetsTable() { ...@@ -160,12 +161,13 @@ function initAssetsTable() {
{targets: 4, createdCell: function (td, cellData, rowData) { {targets: 4, createdCell: function (td, cellData, rowData) {
var push_btn = ''; var push_btn = '';
{% if system_user.auto_push %} {% if system_user.auto_push %}
push_btn = '<a class="btn btn-xs btn-primary btn-push-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Push" %}</a>'.replace("{{ DEFAULT_PK }}", cellData); push_btn = ' <a class="btn btn-xs btn-primary btn-push-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Push" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
{% endif %} {% endif %}
var test_btn = ' <a class="btn btn-xs btn-info btn-test-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Test" %}</a>'.replace("{{ DEFAULT_PK }}", cellData); var test_btn = ' <a class="btn btn-xs btn-info btn-test-asset" data-uid="{{ DEFAULT_PK }}" >{% trans "Test" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
var view_btn = ' <a class="btn btn-xs btn-primary btn-view-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "View auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname);
{#var unbound_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-asset-unbound" data-uid="{{ DEFAULT_PK }}">{% trans "Unbound" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);#} {#var unbound_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-asset-unbound" data-uid="{{ DEFAULT_PK }}">{% trans "Unbound" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);#}
var update_auth_btn = ' <a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "Update auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname); var update_auth_btn = ' <a class="btn btn-xs btn-primary btn-update-asset-user-auth" data-aid="{{ DEFAULT_PK }}" data-hostname="hostname777">{% trans "Update auth" %}</a>'.replace("{{ DEFAULT_PK }}", cellData).replace("hostname777", rowData.hostname);
$(td).html(push_btn + test_btn + update_auth_btn); $(td).html(update_auth_btn + view_btn + push_btn + test_btn);
}} }}
], ],
ajax_url: '{% url "api-assets:system-user-assets" pk=system_user.id %}', ajax_url: '{% url "api-assets:system-user-assets" pk=system_user.id %}',
...@@ -360,5 +362,11 @@ $(document).ready(function () { ...@@ -360,5 +362,11 @@ $(document).ready(function () {
$('#id_password').parent().addClass('has-error'); $('#id_password').parent().addClass('has-error');
} }
}) })
.on("click", ".btn-view-auth", function (evt) {
asset_id = $(this).data("aid") ;
host = $(this).data("hostname");
username = "{{ system_user.username }}";
$("#asset_user_auth_view").modal();
})
</script> </script>
{% endblock %} {% endblock %}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# #
import uuid import uuid
import time
from django.core.cache import cache from django.core.cache import cache
from django.urls import reverse from django.urls import reverse
...@@ -10,10 +11,11 @@ from django.utils.translation import ugettext as _ ...@@ -10,10 +11,11 @@ from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from rest_framework.views import APIView from rest_framework.views import APIView
from common.utils import get_logger, get_request_ip from common.utils import get_logger, get_request_ip
from common.permissions import IsOrgAdminOrAppUser from common.permissions import IsOrgAdminOrAppUser, IsValidUser
from orgs.mixins import RootOrgViewMixin from orgs.mixins import RootOrgViewMixin
from users.serializers import UserSerializer from users.serializers import UserSerializer
from users.models import User from users.models import User
...@@ -23,12 +25,13 @@ from users.utils import ( ...@@ -23,12 +25,13 @@ from users.utils import (
check_user_valid, check_otp_code, increase_login_failed_count, check_user_valid, check_otp_code, increase_login_failed_count,
is_block_login, clean_failed_count is_block_login, clean_failed_count
) )
from ..serializers import OtpVerifySerializer
from ..signals import post_auth_success, post_auth_failed from ..signals import post_auth_success, post_auth_failed
logger = get_logger(__name__) logger = get_logger(__name__)
__all__ = [ __all__ = [
'UserAuthApi', 'UserConnectionTokenApi', 'UserOtpAuthApi', 'UserAuthApi', 'UserConnectionTokenApi', 'UserOtpAuthApi',
'UserOtpVerifyApi',
] ]
...@@ -179,3 +182,20 @@ class UserOtpAuthApi(RootOrgViewMixin, APIView): ...@@ -179,3 +182,20 @@ class UserOtpAuthApi(RootOrgViewMixin, APIView):
sender=self.__class__, username=username, sender=self.__class__, username=username,
request=self.request, reason=reason request=self.request, reason=reason
) )
class UserOtpVerifyApi(CreateAPIView):
permission_classes = (IsValidUser,)
serializer_class = OtpVerifySerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
code = serializer.validated_data["code"]
if request.user.check_otp(code):
request.session["OTP_LAST_VERIFY_TIME"] = int(time.time())
return Response({"ok": "1"})
else:
return Response({"error": "Code not valid"}, status=400)
...@@ -14,3 +14,7 @@ class AccessKeySerializer(serializers.ModelSerializer): ...@@ -14,3 +14,7 @@ class AccessKeySerializer(serializers.ModelSerializer):
model = AccessKey model = AccessKey
fields = ['id', 'secret'] fields = ['id', 'secret']
read_only_fields = ['id', 'secret'] read_only_fields = ['id', 'secret']
class OtpVerifySerializer(serializers.Serializer):
code = serializers.CharField(max_length=6, min_length=6)
...@@ -16,5 +16,6 @@ urlpatterns = [ ...@@ -16,5 +16,6 @@ urlpatterns = [
path('connection-token/', path('connection-token/',
api.UserConnectionTokenApi.as_view(), name='connection-token'), api.UserConnectionTokenApi.as_view(), name='connection-token'),
path('otp/auth/', api.UserOtpAuthApi.as_view(), name='user-otp-auth'), path('otp/auth/', api.UserOtpAuthApi.as_view(), name='user-otp-auth'),
path('otp/verify/', api.UserOtpVerifyApi.as_view(), name='user-otp-verify'),
] ]
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import time
from rest_framework import permissions from rest_framework import permissions
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth.mixins import UserPassesTestMixin
......
...@@ -144,6 +144,7 @@ def is_uuid(seq): ...@@ -144,6 +144,7 @@ def is_uuid(seq):
def get_request_ip(request): def get_request_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',') x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')
if x_forwarded_for and x_forwarded_for[0]: if x_forwarded_for and x_forwarded_for[0]:
login_ip = x_forwarded_for[0] login_ip = x_forwarded_for[0]
else: else:
......
...@@ -194,7 +194,7 @@ class Config(dict): ...@@ -194,7 +194,7 @@ class Config(dict):
filename = os.path.join(self.root_path, filename) filename = os.path.join(self.root_path, filename)
try: try:
with open(filename, 'rt', encoding='utf8') as f: with open(filename, 'rt', encoding='utf8') as f:
obj = yaml.load(f) obj = yaml.safe_load(f)
except IOError as e: except IOError as e:
if silent and e.errno in (errno.ENOENT, errno.EISDIR): if silent and e.errno in (errno.ENOENT, errno.EISDIR):
return False return False
......
This diff is collapsed.
...@@ -124,6 +124,9 @@ class AdHocResultCallback(CallbackMixin, CallbackModule, CMDCallBackModule): ...@@ -124,6 +124,9 @@ class AdHocResultCallback(CallbackMixin, CallbackModule, CMDCallBackModule):
def display_ok_hosts(self): def display_ok_hosts(self):
pass pass
def display_failed_stderr(self):
pass
class CommandResultCallback(AdHocResultCallback): class CommandResultCallback(AdHocResultCallback):
""" """
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
import os import os
import shutil
from collections import namedtuple from collections import namedtuple
from ansible import context
from ansible.module_utils.common.collections import ImmutableDict
from ansible.executor.task_queue_manager import TaskQueueManager from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.vars.manager import VariableManager from ansible.vars.manager import VariableManager
from ansible.parsing.dataloader import DataLoader from ansible.parsing.dataloader import DataLoader
...@@ -33,29 +36,18 @@ Options = namedtuple('Options', [ ...@@ -33,29 +36,18 @@ Options = namedtuple('Options', [
def get_default_options(): def get_default_options():
options = Options( options = dict(
listtags=False,
listtasks=False,
listhosts=False,
syntax=False, syntax=False,
timeout=30, timeout=30,
connection='ssh', connection='ssh',
module_path='',
forks=10, forks=10,
remote_user='root', remote_user='root',
private_key_file=None, private_key_file=None,
ssh_common_args="",
ssh_extra_args="",
sftp_extra_args="",
scp_extra_args="",
become=None, become=None,
become_method=None, become_method=None,
become_user=None, become_user=None,
verbosity=None, verbosity=1,
extra_vars=[],
check=False, check=False,
playbook_path='/etc/ansible/',
passwords=None,
diff=False, diff=False,
gathering='implicit', gathering='implicit',
remote_tmp='/tmp/.ansible' remote_tmp='/tmp/.ansible'
...@@ -108,9 +100,9 @@ class PlayBookRunner: ...@@ -108,9 +100,9 @@ class PlayBookRunner:
inventory=self.inventory, inventory=self.inventory,
variable_manager=self.variable_manager, variable_manager=self.variable_manager,
loader=self.loader, loader=self.loader,
options=self.options, passwords={"conn_pass": self.passwords}
passwords=self.passwords
) )
context.CLIARGS = ImmutableDict(self.options)
if executor._tqm: if executor._tqm:
executor._tqm._stdout_callback = self.results_callback executor._tqm._stdout_callback = self.results_callback
...@@ -185,11 +177,10 @@ class AdHocRunner: ...@@ -185,11 +177,10 @@ class AdHocRunner:
return cleaned_tasks return cleaned_tasks
def update_options(self, options): def update_options(self, options):
_options = {k: v for k, v in self.default_options.items()}
if options and isinstance(options, dict): if options and isinstance(options, dict):
options = self.__class__.default_options._replace(**options) _options.update(options)
else: return _options
options = self.__class__.default_options
return options
def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no'): def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no'):
""" """
...@@ -202,6 +193,7 @@ class AdHocRunner: ...@@ -202,6 +193,7 @@ class AdHocRunner:
self.check_pattern(pattern) self.check_pattern(pattern)
self.results_callback = self.get_result_callback() self.results_callback = self.get_result_callback()
cleaned_tasks = self.clean_tasks(tasks) cleaned_tasks = self.clean_tasks(tasks)
context.CLIARGS = ImmutableDict(self.options)
play_source = dict( play_source = dict(
name=play_name, name=play_name,
...@@ -220,9 +212,8 @@ class AdHocRunner: ...@@ -220,9 +212,8 @@ class AdHocRunner:
inventory=self.inventory, inventory=self.inventory,
variable_manager=self.variable_manager, variable_manager=self.variable_manager,
loader=self.loader, loader=self.loader,
options=self.options,
stdout_callback=self.results_callback, stdout_callback=self.results_callback,
passwords=self.options.passwords, passwords={"conn_pass": self.options.get("password", "")}
) )
try: try:
tqm.run(play) tqm.run(play)
...@@ -230,8 +221,9 @@ class AdHocRunner: ...@@ -230,8 +221,9 @@ class AdHocRunner:
except Exception as e: except Exception as e:
raise AnsibleError(e) raise AnsibleError(e)
finally: finally:
tqm.cleanup() if tqm is not None:
self.loader.cleanup_all_tmp_files() tqm.cleanup()
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
class CommandRunner(AdHocRunner): class CommandRunner(AdHocRunner):
......
...@@ -15,7 +15,7 @@ class TestAdHocRunner(unittest.TestCase): ...@@ -15,7 +15,7 @@ class TestAdHocRunner(unittest.TestCase):
host_data = [ host_data = [
{ {
"hostname": "testserver", "hostname": "testserver",
"ip": "192.168.244.168", "ip": "192.168.244.185",
"port": 22, "port": 22,
"username": "root", "username": "root",
"password": "redhat", "password": "redhat",
......
...@@ -35,7 +35,6 @@ class JMSBaseInventory(BaseInventory): ...@@ -35,7 +35,6 @@ class JMSBaseInventory(BaseInventory):
info["vars"].update({ info["vars"].update({
label.name: label.value label.name: label.value
}) })
info["groups"].append("{}:{}".format(label.name, label.value))
if asset.domain: if asset.domain:
info["vars"].update({ info["vars"].update({
"domain": asset.domain.name, "domain": asset.domain.name,
......
...@@ -715,9 +715,12 @@ String.prototype.format = function(args) { ...@@ -715,9 +715,12 @@ String.prototype.format = function(args) {
return result; return result;
}; };
function setCookie(key, value) { function setCookie(key, value, time) {
var expires = new Date(); var expires = new Date();
expires.setTime(expires.getTime() + (24 * 60 * 60 * 1000)); if (!time) {
time = expires.getTime() + (24 * 60 * 60 * 1000);
}
expires.setTime(time);
document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/'; document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/';
} }
......
/*!
* clipboard.js v1.5.5
* https://zenorocha.github.io/clipboard.js
*
* Licensed MIT © Zeno Rocha
*/
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,r){function o(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,e,n){var r=t("matches-selector");e.exports=function(t,e,n){for(var o=n?t:t.parentNode;o&&o!==document;){if(r(o,e))return o;o=o.parentNode}}},{"matches-selector":2}],2:[function(t,e,n){function r(t,e){if(i)return i.call(t,e);for(var n=t.parentNode.querySelectorAll(e),r=0;r<n.length;++r)if(n[r]==t)return!0;return!1}var o=Element.prototype,i=o.matchesSelector||o.webkitMatchesSelector||o.mozMatchesSelector||o.msMatchesSelector||o.oMatchesSelector;e.exports=r},{}],3:[function(t,e,n){function r(t,e,n,r){var i=o.apply(this,arguments);return t.addEventListener(n,i),{destroy:function(){t.removeEventListener(n,i)}}}function o(t,e,n,r){return function(n){n.delegateTarget=i(n.target,e,!0),n.delegateTarget&&r.call(t,n)}}var i=t("closest");e.exports=r},{closest:1}],4:[function(t,e,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.function=function(t){var e=Object.prototype.toString.call(t);return"[object Function]"===e}},{}],5:[function(t,e,n){function r(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!c.string(e))throw new TypeError("Second argument must be a String");if(!c.function(n))throw new TypeError("Third argument must be a Function");if(c.node(t))return o(t,e,n);if(c.nodeList(t))return i(t,e,n);if(c.string(t))return a(t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function o(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}function i(t,e,n){return Array.prototype.forEach.call(t,function(t){t.addEventListener(e,n)}),{destroy:function(){Array.prototype.forEach.call(t,function(t){t.removeEventListener(e,n)})}}}function a(t,e,n){return s(document.body,t,e,n)}var c=t("./is"),s=t("delegate");e.exports=r},{"./is":4,delegate:3}],6:[function(t,e,n){function r(t){var e;if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName)t.focus(),t.setSelectionRange(0,t.value.length),e=t.value;else{t.hasAttribute("contenteditable")&&t.focus();var n=window.getSelection(),r=document.createRange();r.selectNodeContents(t),n.removeAllRanges(),n.addRange(r),e=n.toString()}return e}e.exports=r},{}],7:[function(t,e,n){function r(){}r.prototype={on:function(t,e,n){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){function r(){o.off(t,r),e.apply(n,arguments)}var o=this;return r._=e,this.on(t,r,n)},emit:function(t){var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,o=n.length;for(r;o>r;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],o=[];if(r&&e)for(var i=0,a=r.length;a>i;i++)r[i].fn!==e&&r[i].fn._!==e&&o.push(r[i]);return o.length?n[t]=o:delete n[t],this}},e.exports=r},{}],8:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.__esModule=!0;var i=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),a=t("select"),c=r(a),s=function(){function t(e){o(this,t),this.resolveOptions(e),this.initSelection()}return t.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action=e.action,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""},t.prototype.initSelection=function t(){if(this.text&&this.target)throw new Error('Multiple attributes declared, use either "target" or "text"');if(this.text)this.selectFake();else{if(!this.target)throw new Error('Missing required attributes, use either "target" or "text"');this.selectTarget()}},t.prototype.selectFake=function t(){var e=this;this.removeFake(),this.fakeHandler=document.body.addEventListener("click",function(){return e.removeFake()}),this.fakeElem=document.createElement("textarea"),this.fakeElem.style.position="absolute",this.fakeElem.style.left="-9999px",this.fakeElem.style.top=(window.pageYOffset||document.documentElement.scrollTop)+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=c.default(this.fakeElem),this.copyText()},t.prototype.removeFake=function t(){this.fakeHandler&&(document.body.removeEventListener("click"),this.fakeHandler=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)},t.prototype.selectTarget=function t(){this.selectedText=c.default(this.target),this.copyText()},t.prototype.copyText=function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(n){e=!1}this.handleResult(e)},t.prototype.handleResult=function t(e){e?this.emitter.emit("success",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)}):this.emitter.emit("error",{action:this.action,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})},t.prototype.clearSelection=function t(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()},t.prototype.destroy=function t(){this.removeFake()},i(t,[{key:"action",set:function t(){var e=arguments.length<=0||void 0===arguments[0]?"copy":arguments[0];if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!=typeof e||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');this._target=e}},get:function t(){return this._target}}]),t}();n.default=s,e.exports=n.default},{select:6}],9:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function a(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}n.__esModule=!0;var c=t("./clipboard-action"),s=r(c),u=t("tiny-emitter"),l=r(u),f=t("good-listener"),d=r(f),h=function(t){function e(n,r){o(this,e),t.call(this),this.resolveOptions(r),this.listenClick(n)}return i(e,t),e.prototype.resolveOptions=function t(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText},e.prototype.listenClick=function t(e){var n=this;this.listener=d.default(e,"click",function(t){return n.onClick(t)})},e.prototype.onClick=function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})},e.prototype.defaultAction=function t(e){return a("action",e)},e.prototype.defaultTarget=function t(e){var n=a("target",e);return n?document.querySelector(n):void 0},e.prototype.defaultText=function t(e){return a("text",e)},e.prototype.destroy=function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)},e}(l.default);n.default=h,e.exports=n.default},{"./clipboard-action":8,"good-listener":5,"tiny-emitter":7}]},{},[9])(9)});
\ No newline at end of file
...@@ -147,6 +147,10 @@ class User(AbstractUser): ...@@ -147,6 +147,10 @@ class User(AbstractUser):
def otp_secret_key(self, item): def otp_secret_key(self, item):
self._otp_secret_key = signer.sign(item) self._otp_secret_key = signer.sign(item)
def check_otp(self, code):
from ..utils import check_otp_code
return check_otp_code(self.otp_secret_key, code)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('users:user-detail', args=(self.id,)) return reverse('users:user-detail', args=(self.id,))
......
amqp==2.1.4 amqp==2.1.4
ansible==2.4.2.0 ansible==2.8.0
asn1crypto==0.24.0 asn1crypto==0.24.0
bcrypt==3.1.4 bcrypt==3.1.4
billiard==3.5.0.3 billiard==3.5.0.3
...@@ -24,7 +24,7 @@ django-ranged-response==0.2.0 ...@@ -24,7 +24,7 @@ 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.8.2 djangorestframework==3.9.4
djangorestframework-bulk==0.2.1 djangorestframework-bulk==0.2.1
docutils==0.14 docutils==0.14
ecdsa==0.13 ecdsa==0.13
...@@ -38,7 +38,7 @@ gunicorn==19.9.0 ...@@ -38,7 +38,7 @@ gunicorn==19.9.0
idna==2.6 idna==2.6
itsdangerous==0.24 itsdangerous==0.24
itypes==1.1.0 itypes==1.1.0
Jinja2==2.10 Jinja2==2.10.1
jmespath==0.9.3 jmespath==0.9.3
kombu==4.0.2 kombu==4.0.2
ldap3==2.4 ldap3==2.4
...@@ -46,7 +46,7 @@ MarkupSafe==1.0 ...@@ -46,7 +46,7 @@ MarkupSafe==1.0
mysqlclient==1.3.14 mysqlclient==1.3.14
olefile==0.44 olefile==0.44
openapi-codec==1.3.2 openapi-codec==1.3.2
paramiko==2.4.1 paramiko==2.4.2
passlib==1.7.1 passlib==1.7.1
Pillow==4.3.0 Pillow==4.3.0
pyasn1==0.4.2 pyasn1==0.4.2
...@@ -57,20 +57,20 @@ PyNaCl==1.2.1 ...@@ -57,20 +57,20 @@ PyNaCl==1.2.1
python-dateutil==2.6.1 python-dateutil==2.6.1
python-gssapi==0.6.4 python-gssapi==0.6.4
pytz==2018.3 pytz==2018.3
PyYAML==3.12 PyYAML==5.1
redis==2.10.6 redis==2.10.6
requests==2.18.4 requests==2.22.0
jms-storage==0.0.22 jms-storage==0.0.22
s3transfer==0.1.13 s3transfer==0.1.13
simplejson==3.13.2 simplejson==3.13.2
six==1.11.0 six==1.11.0
sshpubkeys==3.1.0 sshpubkeys==3.1.0
uritemplate==3.0.0 uritemplate==3.0.0
urllib3==1.22 urllib3==1.25.2
vine==1.1.4 vine==1.1.4
drf-yasg==1.9.1 drf-yasg==1.9.1
Werkzeug==0.14.1 Werkzeug==0.14.1
drf-nested-routers==0.90.2 drf-nested-routers==0.91
aliyun-python-sdk-core-v3==2.9.1 aliyun-python-sdk-core-v3==2.9.1
aliyun-python-sdk-ecs==4.10.1 aliyun-python-sdk-ecs==4.10.1
python-keycloak==0.13.3 python-keycloak==0.13.3
......
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