[future] 调整app架构

pull/530/head
Administrator 2016-11-22 23:02:12 +08:00
parent fea76178ee
commit 32a5aec34e
19 changed files with 1277 additions and 274 deletions

View File

@ -0,0 +1,3 @@
from ansible import Tasker, AnsiblePlay, AnsibleTask, AnsibleHostResult
from sudo import HostAlia, UserAlia, CmdAlia, RunasAlia, Privilege, Extra_conf, Sudo
from cron import CronTable

View File

@ -4,9 +4,7 @@ from __future__ import unicode_literals, absolute_import
import logging import logging
import json import json
from jinja2 import Template
from django.db import models from django.db import models
from assets.models import Asset
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -213,212 +211,6 @@ class AnsibleHostResult(models.Model):
return {"msg": "deal with ping data failed, %s" % e.message, "data": None} return {"msg": "deal with ping data failed, %s" % e.message, "data": None}
class HostAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Host_Alias'))
host_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class UserAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('User_Alias'))
user_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class CmdAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Command_Alias'))
cmd_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class RunasAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Runas_Alias'))
runas_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class Privilege(models.Model):
user = models.ForeignKey(UserAlia, blank=True, null=True, related_name='privileges')
host = models.ForeignKey(HostAlia, blank=True, null=True, related_name='privileges')
runas = models.ForeignKey(RunasAlia, blank=True, null=True, related_name='privileges')
command = models.ForeignKey(CmdAlia, blank=True, null=True, related_name='privileges')
nopassword = models.BooleanField(default=True, verbose_name=_('Is_NoPassword'))
def __unicode__(self):
return "[%s %s %s %s %s]" % (self.user.name,
self.host.name,
self.runas.name,
self.command.name,
self.nopassword)
def to_tuple(self):
return self.user.name, self.host.name, self.runas.name, self.command.name, self.nopassword
class Extra_conf(models.Model):
line = models.TextField(blank=True, null=True, verbose_name=_('Extra_Item'))
def __unicode__(self):
return self.line
class Sudo(models.Model):
"""
Sudo配置文件对象, 用于配置sudo的配置文件
:param extra_lines: <list> [<line1>, <line2>,...]
:param privileges: <list> [(user, host, runas, command, nopassword),]
"""
asset = models.ForeignKey(Asset, null=True, blank=True, related_name='sudos')
extra_lines = models.ManyToManyField(Extra_conf, related_name='sudos', blank=True)
privilege_items = models.ManyToManyField(Privilege, related_name='sudos', blank=True)
@property
def users(self):
return {privilege.user.name: privilege.user.user_items.split(',') for privilege in self.privilege_items.all()}
@property
def commands(self):
return {privilege.command.name: privilege.command.cmd_items.split(',') for privilege in self.privilege_items.all()}
@property
def hosts(self):
return {privilege.host.name: privilege.host.host_items.split(',') for privilege in self.privilege_items.all()}
@property
def runas(self):
return {privilege.runas.name: privilege.runas.runas_items.split(',') for privilege in self.privilege_items.all()}
@property
def extras(self):
return [extra.line for extra in self.extra_lines.all()]
@property
def privileges(self):
return [privilege.to_tuple() for privilege in self.privilege_items.all()]
@property
def content(self):
template = Template(self.__sudoers_jinja2_tmp__)
context = {"User_Alias": self.users,
"Cmnd_Alias": self.commands,
"Host_Alias": self.hosts,
"Runas_Alias": self.runas,
"Extra_Lines": self.extras,
"Privileges": self.privileges}
return template.render(context)
@property
def __sudoers_jinja2_tmp__(self):
return """# management by JumpServer
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# JumpServer Generate Other Configure is here
{% if Extra_Lines -%}
{% for line in Extra_Lines -%}
{{ line }}
{% endfor %}
{%- endif %}
# Host alias specification
{% if Host_Alias -%}
{% for flag, items in Host_Alias.iteritems() -%}
Host_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# User alias specification
{% if User_Alias -%}
{% for flag, items in User_Alias.iteritems() -%}
User_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# Cmnd alias specification
{% if Cmnd_Alias -%}
{% for flag, items in Cmnd_Alias.iteritems() -%}
Cmnd_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# Run as alias specification
{% if Runas_Alias -%}
{% for flag, items in Runas_Alias.iteritems() -%}
Runas_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# User privilege specification
root ALL=(ALL:ALL) ALL
# JumpServer Generate User privilege is here.
# Note privileges is a tuple list like [(user, host, runas, command, nopassword),]
{% if Privileges -%}
{% for User_Flag, Host_Flag, Runas_Flag, Command_Flag, NopassWord in Privileges -%}
{% if NopassWord -%}
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) NOPASSWD: {{ Command_Flag }}
{%- else -%}
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) {{ Command_Flag }}
{%- endif %}
{% endfor %}
{%- endif %}
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
"""
class CronTable(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Name'),
help_text=_("Description of a crontab entry"))
month = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Month'),
help_text=_("Month of the year the job should run ( 1-12, *, */2, etc )"))
weekday = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('WeekDay'),
help_text=_("Day of the week that the job should run"
" ( 0-6 for Sunday-Saturday, *, etc )"))
day = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Day'),
help_text=_("Day of the month the job should run ( 1-31, *, */2, etc )"))
hour = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hour'),
help_text=_("Hour when the job should run ( 0-23, *, */2, etc )"))
minute = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Minute'),
help_text=_("Minute when the job should run ( 0-59, *, */2, etc )"))
job = models.CharField(max_length=4096, blank=True, null=True, verbose_name=_('Job'),
help_text=_("The command to execute or, if env is set, the value of "
"environment variable. Required if state=present."))
user = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('User'),
help_text=_("The specific user whose crontab should be modified."))
asset = models.ForeignKey(Asset, null=True, blank=True, related_name='crontables')
@property
def describe(self):
return "http://docs.ansible.com/ansible/cron_module.html"

32
apps/ops/models/cron.py Normal file
View File

@ -0,0 +1,32 @@
# ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals, absolute_import
from django.db import models
from assets.models import Asset
from django.utils.translation import ugettext_lazy as _
class CronTable(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Name'),
help_text=_("Description of a crontab entry"))
month = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Month'),
help_text=_("Month of the year the job should run ( 1-12, *, */2, etc )"))
weekday = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('WeekDay'),
help_text=_("Day of the week that the job should run"
" ( 0-6 for Sunday-Saturday, *, etc )"))
day = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Day'),
help_text=_("Day of the month the job should run ( 1-31, *, */2, etc )"))
hour = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hour'),
help_text=_("Hour when the job should run ( 0-23, *, */2, etc )"))
minute = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Minute'),
help_text=_("Minute when the job should run ( 0-59, *, */2, etc )"))
job = models.CharField(max_length=4096, blank=True, null=True, verbose_name=_('Job'),
help_text=_("The command to execute or, if env is set, the value of "
"environment variable. Required if state=present."))
user = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('User'),
help_text=_("The specific user whose crontab should be modified."))
asset = models.ForeignKey(Asset, null=True, blank=True, related_name='crontables')
@property
def describe(self):
return "http://docs.ansible.com/ansible/cron_module.html"

187
apps/ops/models/sudo.py Normal file
View File

@ -0,0 +1,187 @@
# ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals, absolute_import
from jinja2 import Template
from django.db import models
from assets.models import Asset
from django.utils.translation import ugettext_lazy as _
class HostAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Host_Alias'))
host_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class UserAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('User_Alias'))
user_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class CmdAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Command_Alias'))
cmd_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class RunasAlia(models.Model):
name = models.CharField(max_length=128, blank=True, null=True, unique=True, verbose_name=_('Runas_Alias'))
runas_items = models.TextField(blank=True, null=True, verbose_name=_('Host_Items'))
def __unicode__(self):
return self.name
class Privilege(models.Model):
user = models.ForeignKey(UserAlia, blank=True, null=True, related_name='privileges')
host = models.ForeignKey(HostAlia, blank=True, null=True, related_name='privileges')
runas = models.ForeignKey(RunasAlia, blank=True, null=True, related_name='privileges')
command = models.ForeignKey(CmdAlia, blank=True, null=True, related_name='privileges')
nopassword = models.BooleanField(default=True, verbose_name=_('Is_NoPassword'))
def __unicode__(self):
return "[%s %s %s %s %s]" % (self.user.name,
self.host.name,
self.runas.name,
self.command.name,
self.nopassword)
def to_tuple(self):
return self.user.name, self.host.name, self.runas.name, self.command.name, self.nopassword
class Extra_conf(models.Model):
line = models.TextField(blank=True, null=True, verbose_name=_('Extra_Item'))
def __unicode__(self):
return self.line
class Sudo(models.Model):
"""
Sudo配置文件对象, 用于配置sudo的配置文件
:param extra_lines: <list> [<line1>, <line2>,...]
:param privileges: <list> [(user, host, runas, command, nopassword),]
"""
asset = models.ForeignKey(Asset, null=True, blank=True, related_name='sudos')
extra_lines = models.ManyToManyField(Extra_conf, related_name='sudos', blank=True)
privilege_items = models.ManyToManyField(Privilege, related_name='sudos', blank=True)
@property
def users(self):
return {privilege.user.name: privilege.user.user_items.split(',') for privilege in self.privilege_items.all()}
@property
def commands(self):
return {privilege.command.name: privilege.command.cmd_items.split(',') for privilege in self.privilege_items.all()}
@property
def hosts(self):
return {privilege.host.name: privilege.host.host_items.split(',') for privilege in self.privilege_items.all()}
@property
def runas(self):
return {privilege.runas.name: privilege.runas.runas_items.split(',') for privilege in self.privilege_items.all()}
@property
def extras(self):
return [extra.line for extra in self.extra_lines.all()]
@property
def privileges(self):
return [privilege.to_tuple() for privilege in self.privilege_items.all()]
@property
def content(self):
template = Template(self.__sudoers_jinja2_tmp__)
context = {"User_Alias": self.users,
"Cmnd_Alias": self.commands,
"Host_Alias": self.hosts,
"Runas_Alias": self.runas,
"Extra_Lines": self.extras,
"Privileges": self.privileges}
return template.render(context)
@property
def __sudoers_jinja2_tmp__(self):
return """# management by JumpServer
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# JumpServer Generate Other Configure is here
{% if Extra_Lines -%}
{% for line in Extra_Lines -%}
{{ line }}
{% endfor %}
{%- endif %}
# Host alias specification
{% if Host_Alias -%}
{% for flag, items in Host_Alias.iteritems() -%}
Host_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# User alias specification
{% if User_Alias -%}
{% for flag, items in User_Alias.iteritems() -%}
User_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# Cmnd alias specification
{% if Cmnd_Alias -%}
{% for flag, items in Cmnd_Alias.iteritems() -%}
Cmnd_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# Run as alias specification
{% if Runas_Alias -%}
{% for flag, items in Runas_Alias.iteritems() -%}
Runas_Alias {{ flag }} = {{ items|join(', ') }}
{% endfor %}
{%- endif %}
# User privilege specification
root ALL=(ALL:ALL) ALL
# JumpServer Generate User privilege is here.
# Note privileges is a tuple list like [(user, host, runas, command, nopassword),]
{% if Privileges -%}
{% for User_Flag, Host_Flag, Runas_Flag, Command_Flag, NopassWord in Privileges -%}
{% if NopassWord -%}
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) NOPASSWD: {{ Command_Flag }}
{%- else -%}
{{ User_Flag }} {{ Host_Flag }}=({{ Runas_Flag }}) {{ Command_Flag }}
{%- endif %}
{% endfor %}
{%- endif %}
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
"""

View File

@ -1,9 +1,9 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from celery import shared_task from celery import shared_task
from common import celery_app
from ops.ansible_api import Config, ADHocRunner from common import celery_app
from ops.utils.ansible_api import Config, ADHocRunner
@shared_task(name="get_asset_hardware_info") @shared_task(name="get_asset_hardware_info")

View File

@ -0,0 +1,97 @@
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
<link href="{% static "css/plugins/datepicker/datepicker3.css" %}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% block user_template_title %}{% trans 'Create user' %}{% endblock %}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
{% csrf_token %}
<h3>{% trans 'Account' %}</h3>
{% block username %} {% endblock %}
{{ form.email|bootstrap_horizontal }}
{{ form.name|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{% block password %} {% endblock %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Security and Role' %}</h3>
{{ form.role|bootstrap_horizontal }}
<div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
<div class="col-sm-9">
<div class="input-group date">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input id="{{ form.date_expired.id_for_label }}" name="{{ form.date_expired.html_name }}" type="text" class="form-control" value="{{ form.date_expired.value|date:'Y-m-d' }}">
</div>
<span class="help-block ">{{ form.date_expired.errors }}</span>
</div>
</div>
{# {{ form.date_expired|bootstrap_horizontal }}#}
<div class="form-group">
<label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
<div class="col-sm-8">
{{ form.enable_otp }}
</div>
</div>
<div class="hr-line-dashed"></div>
<h3>{% trans 'Profile' %}</h3>
{{ form.phone|bootstrap_horizontal }}
{{ form.wechat|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
<script>
$(document).ready(function () {
$('.select2').select2();
$('.input-group.date').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
});
})
</script>
{% endblock %}

View File

@ -1,10 +1,16 @@
<!DOCTYPE html> {% extends 'cron/_cron.html' %}
<html lang="en"> {% load i18n %}
<head> {% load bootstrap %}
<meta charset="UTF-8"> {% block user_template_title %}{% trans "Create user" %}{% endblock %}
<title>Title</title> {% block username %}
</head> {{ form.username|bootstrap_horizontal }}
<body> {% endblock %}
{% block password %}
</body> <h3>{% trans 'Password' %}</h3>
</html> <div class="form-group">
<label class="col-sm-2 control-label">{% trans 'Password' %}</label>
<div class="col-sm-8 controls" >
{% trans 'Reset link will be generated and sent to the user. ' %}
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,393 @@
<!DOCTYPE html> {% extends 'base.html' %}
<html lang="en"> {% load common_tags %}
<head> {% load users_tags %}
<meta charset="UTF-8"> {% load static %}
<title>Title</title> {% load i18n %}
</head>
<body>
</body> {% block custom_head_css_js %}
</html> <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="{% url 'users:user-detail' pk=user_object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
</li>
<li>
<a href="{% url 'users:user-asset-permission' pk=user_object.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
</li>
<li><a href="{% url 'users:user-granted-asset' pk=user_object.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a></li>
<li><a href="{% url 'users:user-login-history' pk=user_object.id %}" class="text-center"><i class="fa fa-calculator-o"></i> {% trans 'Login history' %}</a></li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ user_object.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td colspan="2">
<img src="{{ user_object | user_avatar_url }}" class="img-circle" width="64" height="64">
</td>
</tr>
<tr>
<td width="20%">{% trans 'Name' %}:</td>
<td><b>{{ user_object.name }}</b></td>
</tr>
<tr>
<td>{% trans 'Username' %}:</td>
<td><b>{{ user_object.username }}</b></td>
</tr>
<tr>
<td>{% trans 'Email' %}:</td>
<td><b>{{ user_object.email }}</b></td>
</tr>
{% if user_object.phone %}
<tr>
<td>{% trans 'Phone' %}:</td>
<td><b>{{ user_object.phone }}</b></td>
</tr>
{% endif %}
{% if user_object.wechat %}
<tr>
<td>{% trans 'Wechat' %}:</td>
<td><b>{{ user_object.wechat }}</b></td>
</tr>
{% endif %}
<tr>
<td>{% trans 'Role' %}:</td>
<td><b>{{ user_object.get_role_display }}</b></td>
</tr>
<tr>
<td>{% trans 'Date expired' %}:</td>
<td><b>{{ user_object.date_expired|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ user_object.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Date joined' %}:</td>
<td><b>{{ user_object.date_joined|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Last login' %}:</td>
<td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ user_object.comment }}</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td width="50%">{% trans 'Active' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" {% if user_object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
<label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</span></td>
</tr>
<tr>
<td>{% trans 'Enable OTP' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
id="enable_otp">
<label class="onoffswitch-label" for="enable_otp">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</span></td>
</tr>
<tr>
<td>{% trans 'Reset password' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Reset ssh key' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Update ssh key' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_update_pk" style="width: 54px;" data-toggle="modal" data-target="#user_update_pk_modal">{% trans 'Update' %}</button>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'User group' %}
</div>
<div class="panel-body">
<table class="table group_edit">
<tbody>
<form>
<tr>
<td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Join user groups' %}" id="slct_groups" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for group in groups %}
<option value="{{ group.id }}" id="opt_{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td colspan="2" class="no-borders">
<button type="button" class="btn btn-info btn-small" id="btn_add_user_group">{% trans 'Join' %}</button>
</td>
</tr>
</form>
{% for group in user_object.groups.all %}
<tr>
<td ><b class="bdg_user_group" data-gid={{ group.id }}>{{ group.name }}</b></td>
<td>
<button class="btn btn-danger pull-right btn-xs btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% include 'users/_user_update_pk_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
<script>
jumpserver.selected_groups = {};
function updateUserGroups(user_groups) {
var the_url = "{% url 'users:group-user-edit-api' pk=user_object.id %}";
var body = {
id: {{ user_object.id }},
groups: Object.assign([], user_groups)
};
var success = function(data) {
// remove all the selected groups from select > option and rendered ul element;
$('.select2-selection__rendered').empty();
$('#slct_groups').val('');
$.map(jumpserver.selected_groups, function(group_name, index) {
$('#opt_' + index).remove();
// change tr html of user groups.
$('.group_edit tbody').append(
'<tr>' +
'<td><b class="bdg_user_group" data-gid="' + index + '">' + group_name + '</b></td>' +
'<td><button class="btn btn-danger btn-xs pull-right btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button></td>' +
'</tr>'
)
});
// clear jumpserver.selected_groups
jumpserver.selected_groups = {};
toastr.success('{% trans "UserGroup Update Success!" %}')
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success,
method: 'PUT'
});
}
$(document).ready(function() {
$('.select2').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.selected_groups[data.id] = data.text;
}).on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.selected_groups[data.id]
})
}).on('click', '#is_active', function() {
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {
'is_active': checked
};
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success_message: success
});
}).on('click', '#enable_otp', function() {
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {
'enable_otp': checked
};
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success_message: success
});
}).on('click', '#btn_add_user_group', function() {
if (Object.keys(jumpserver.selected_groups).length === 0) {
return false;
}
var user_groups = $('.bdg_user_group').map(function() {
return $(this).data('gid');
}).get();
$.map(jumpserver.selected_groups, function(value, index) {
user_groups.push(parseInt(index));
$('#opt_' + index).remove();
});
updateUserGroups(user_groups)
}).on('click', '.btn_delete_user_group', function() {
var $this = $(this);
var $tr = $this.closest('tr');
var $badge = $tr.find('.bdg_user_group');
var gid = $badge.data('gid');
var group_name = $badge.html() || $badge.text();
$('#slct_groups').append(
'<option value="' + gid + '" id="opt_' + gid + '">' + group_name + '</option>'
);
$tr.remove();
var user_groups = $('.bdg_user_group').map(function() {
return $(this).data('gid');
}).get();
updateUserGroups(user_groups)
}).on('click', '#btn_reset_password', function() {
function doReset() {
var the_url = '{% url "users:user-reset-password-api" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans 'E-mail sent successfully. An e-mail has been sent to the user\'s mailbox.' %}";
swal("{% trans 'Password-Reset' %}", msg, "success");
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s password.' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
}).on('click', '#btn_reset_pk', function() {
function doReset() {
var the_url = '{% url "users:user-reset-pk-api" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans 'The reset-ssh-public-key E-mail has been sent successfully. Please inform the user to update his new ssh public key.' %}";
swal("{% trans 'SSH-Public-Key Reset' %}", msg, "success");
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s public key.' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
}).on('click', '#btn_user_update_pk', function(){
var $this = $(this);
var pk = $('#txt_pk').val();
var the_url = '{% url "users:user-update-pk-api" pk=user_object.id %}';
var body = {'_public_key': pk};
var success = function() {
$('#txt_pk').val('');
$this.closest('.modal').modal('hide');
var msg = "{% trans 'Successfully updated the SSH public key.' %}";
swal("{% trans 'User SSH Public Key Update' %}", msg, "success");
};
var fail = function() {
var msg = "{% trans 'Failed to update the user\'s SSH public key.' %}";
swal({
title: "{% trans 'User SSH Public Key Update' %}",
text: msg,
type: "error",
showCancelButton: false,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: true
}, function () {
$('#txt_pk').focus();
}
);
}
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
});
</script>
{% endblock %}

View File

@ -1,10 +1,20 @@
<!DOCTYPE html> {% extends 'cron/_cron.html' %}
<html lang="en"> {% load i18n %}
<head> {% block user_template_title %}{% trans "Update user" %}{% endblock %}
<meta charset="UTF-8"> {% block username %}
<title>Title</title> <div class="form-group">
</head> <label for="{{ form.username.id_for_label }}" class="col-sm-2 control-label">{% trans 'Username' %}</label>
<body> <div class="col-sm-9 controls" >
<input id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}" type="text" value="{{ user_object.username }}" readonly class="form-control">
</body> </div>
</html> </div>
{% endblock %}
{% block password %}
<h3>{% trans 'Password' %}</h3>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">{% trans 'Password' %}</label>
<div class="col-sm-9 controls" >
<input id="password" name="password" type="password" class="form-control">
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,97 @@
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
<link href="{% static "css/plugins/datepicker/datepicker3.css" %}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% block user_template_title %}{% trans 'Create user' %}{% endblock %}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
{% csrf_token %}
<h3>{% trans 'Account' %}</h3>
{% block username %} {% endblock %}
{{ form.email|bootstrap_horizontal }}
{{ form.name|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{% block password %} {% endblock %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Security and Role' %}</h3>
{{ form.role|bootstrap_horizontal }}
<div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
<div class="col-sm-9">
<div class="input-group date">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input id="{{ form.date_expired.id_for_label }}" name="{{ form.date_expired.html_name }}" type="text" class="form-control" value="{{ form.date_expired.value|date:'Y-m-d' }}">
</div>
<span class="help-block ">{{ form.date_expired.errors }}</span>
</div>
</div>
{# {{ form.date_expired|bootstrap_horizontal }}#}
<div class="form-group">
<label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
<div class="col-sm-8">
{{ form.enable_otp }}
</div>
</div>
<div class="hr-line-dashed"></div>
<h3>{% trans 'Profile' %}</h3>
{{ form.phone|bootstrap_horizontal }}
{{ form.wechat|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
<script>
$(document).ready(function () {
$('.select2').select2();
$('.input-group.date').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
});
})
</script>
{% endblock %}

View File

@ -1,10 +1,16 @@
<!DOCTYPE html> {% extends 'sudo/_sudo.html' %}
<html lang="en"> {% load i18n %}
<head> {% load bootstrap %}
<meta charset="UTF-8"> {% block user_template_title %}{% trans "Create user" %}{% endblock %}
<title>Title</title> {% block username %}
</head> {{ form.username|bootstrap_horizontal }}
<body> {% endblock %}
{% block password %}
</body> <h3>{% trans 'Password' %}</h3>
</html> <div class="form-group">
<label class="col-sm-2 control-label">{% trans 'Password' %}</label>
<div class="col-sm-8 controls" >
{% trans 'Reset link will be generated and sent to the user. ' %}
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,393 @@
<!DOCTYPE html> {% extends 'base.html' %}
<html lang="en"> {% load common_tags %}
<head> {% load users_tags %}
<meta charset="UTF-8"> {% load static %}
<title>Title</title> {% load i18n %}
</head>
<body>
</body> {% block custom_head_css_js %}
</html> <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="{% url 'users:user-detail' pk=user_object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
</li>
<li>
<a href="{% url 'users:user-asset-permission' pk=user_object.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
</li>
<li><a href="{% url 'users:user-granted-asset' pk=user_object.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a></li>
<li><a href="{% url 'users:user-login-history' pk=user_object.id %}" class="text-center"><i class="fa fa-calculator-o"></i> {% trans 'Login history' %}</a></li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ user_object.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td colspan="2">
<img src="{{ user_object | user_avatar_url }}" class="img-circle" width="64" height="64">
</td>
</tr>
<tr>
<td width="20%">{% trans 'Name' %}:</td>
<td><b>{{ user_object.name }}</b></td>
</tr>
<tr>
<td>{% trans 'Username' %}:</td>
<td><b>{{ user_object.username }}</b></td>
</tr>
<tr>
<td>{% trans 'Email' %}:</td>
<td><b>{{ user_object.email }}</b></td>
</tr>
{% if user_object.phone %}
<tr>
<td>{% trans 'Phone' %}:</td>
<td><b>{{ user_object.phone }}</b></td>
</tr>
{% endif %}
{% if user_object.wechat %}
<tr>
<td>{% trans 'Wechat' %}:</td>
<td><b>{{ user_object.wechat }}</b></td>
</tr>
{% endif %}
<tr>
<td>{% trans 'Role' %}:</td>
<td><b>{{ user_object.get_role_display }}</b></td>
</tr>
<tr>
<td>{% trans 'Date expired' %}:</td>
<td><b>{{ user_object.date_expired|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ user_object.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Date joined' %}:</td>
<td><b>{{ user_object.date_joined|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Last login' %}:</td>
<td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ user_object.comment }}</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td width="50%">{% trans 'Active' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" {% if user_object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
<label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</span></td>
</tr>
<tr>
<td>{% trans 'Enable OTP' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
id="enable_otp">
<label class="onoffswitch-label" for="enable_otp">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</span></td>
</tr>
<tr>
<td>{% trans 'Reset password' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Reset ssh key' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Update ssh key' %}:</td>
<td>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_update_pk" style="width: 54px;" data-toggle="modal" data-target="#user_update_pk_modal">{% trans 'Update' %}</button>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'User group' %}
</div>
<div class="panel-body">
<table class="table group_edit">
<tbody>
<form>
<tr>
<td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Join user groups' %}" id="slct_groups" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for group in groups %}
<option value="{{ group.id }}" id="opt_{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td colspan="2" class="no-borders">
<button type="button" class="btn btn-info btn-small" id="btn_add_user_group">{% trans 'Join' %}</button>
</td>
</tr>
</form>
{% for group in user_object.groups.all %}
<tr>
<td ><b class="bdg_user_group" data-gid={{ group.id }}>{{ group.name }}</b></td>
<td>
<button class="btn btn-danger pull-right btn-xs btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% include 'users/_user_update_pk_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
<script>
jumpserver.selected_groups = {};
function updateUserGroups(user_groups) {
var the_url = "{% url 'users:group-user-edit-api' pk=user_object.id %}";
var body = {
id: {{ user_object.id }},
groups: Object.assign([], user_groups)
};
var success = function(data) {
// remove all the selected groups from select > option and rendered ul element;
$('.select2-selection__rendered').empty();
$('#slct_groups').val('');
$.map(jumpserver.selected_groups, function(group_name, index) {
$('#opt_' + index).remove();
// change tr html of user groups.
$('.group_edit tbody').append(
'<tr>' +
'<td><b class="bdg_user_group" data-gid="' + index + '">' + group_name + '</b></td>' +
'<td><button class="btn btn-danger btn-xs pull-right btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button></td>' +
'</tr>'
)
});
// clear jumpserver.selected_groups
jumpserver.selected_groups = {};
toastr.success('{% trans "UserGroup Update Success!" %}')
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success,
method: 'PUT'
});
}
$(document).ready(function() {
$('.select2').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.selected_groups[data.id] = data.text;
}).on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.selected_groups[data.id]
})
}).on('click', '#is_active', function() {
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {
'is_active': checked
};
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success_message: success
});
}).on('click', '#enable_otp', function() {
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {
'enable_otp': checked
};
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success_message: success
});
}).on('click', '#btn_add_user_group', function() {
if (Object.keys(jumpserver.selected_groups).length === 0) {
return false;
}
var user_groups = $('.bdg_user_group').map(function() {
return $(this).data('gid');
}).get();
$.map(jumpserver.selected_groups, function(value, index) {
user_groups.push(parseInt(index));
$('#opt_' + index).remove();
});
updateUserGroups(user_groups)
}).on('click', '.btn_delete_user_group', function() {
var $this = $(this);
var $tr = $this.closest('tr');
var $badge = $tr.find('.bdg_user_group');
var gid = $badge.data('gid');
var group_name = $badge.html() || $badge.text();
$('#slct_groups').append(
'<option value="' + gid + '" id="opt_' + gid + '">' + group_name + '</option>'
);
$tr.remove();
var user_groups = $('.bdg_user_group').map(function() {
return $(this).data('gid');
}).get();
updateUserGroups(user_groups)
}).on('click', '#btn_reset_password', function() {
function doReset() {
var the_url = '{% url "users:user-reset-password-api" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans 'E-mail sent successfully. An e-mail has been sent to the user\'s mailbox.' %}";
swal("{% trans 'Password-Reset' %}", msg, "success");
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s password.' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
}).on('click', '#btn_reset_pk', function() {
function doReset() {
var the_url = '{% url "users:user-reset-pk-api" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans 'The reset-ssh-public-key E-mail has been sent successfully. Please inform the user to update his new ssh public key.' %}";
swal("{% trans 'SSH-Public-Key Reset' %}", msg, "success");
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s public key.' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
doReset();
});
}).on('click', '#btn_user_update_pk', function(){
var $this = $(this);
var pk = $('#txt_pk').val();
var the_url = '{% url "users:user-update-pk-api" pk=user_object.id %}';
var body = {'_public_key': pk};
var success = function() {
$('#txt_pk').val('');
$this.closest('.modal').modal('hide');
var msg = "{% trans 'Successfully updated the SSH public key.' %}";
swal("{% trans 'User SSH Public Key Update' %}", msg, "success");
};
var fail = function() {
var msg = "{% trans 'Failed to update the user\'s SSH public key.' %}";
swal({
title: "{% trans 'User SSH Public Key Update' %}",
text: msg,
type: "error",
showCancelButton: false,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: true
}, function () {
$('#txt_pk').focus();
}
);
}
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
});
</script>
{% endblock %}

View File

@ -1,10 +1,20 @@
<!DOCTYPE html> {% extends 'sudo/_sudo.html' %}
<html lang="en"> {% load i18n %}
<head> {% block user_template_title %}{% trans "Update user" %}{% endblock %}
<meta charset="UTF-8"> {% block username %}
<title>Title</title> <div class="form-group">
</head> <label for="{{ form.username.id_for_label }}" class="col-sm-2 control-label">{% trans 'Username' %}</label>
<body> <div class="col-sm-9 controls" >
<input id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}" type="text" value="{{ user_object.username }}" readonly class="form-control">
</body> </div>
</html> </div>
{% endblock %}
{% block password %}
<h3>{% trans 'Password' %}</h3>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">{% trans 'Password' %}</label>
<div class="col-sm-9 controls" >
<input id="password" name="password" type="password" class="form-control">
</div>
</div>
{% endblock %}

View File

View File

View File

@ -18,7 +18,7 @@ from ansible.utils.display import Display
from ansible.playbook.play import Play from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
from models import Tasker, AnsiblePlay, AnsibleTask, AnsibleHostResult from ops.models import Tasker, AnsiblePlay, AnsibleTask, AnsibleHostResult
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -10,7 +10,4 @@ class CreateSudoPrivilegesMixin(object):
class ListSudoPrivilegesMixin(object): class ListSudoPrivilegesMixin(object):
def get_all_privilege(self): def get_all_privilege(self):
pass pass

View File

@ -7,7 +7,7 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.detail import DetailView, SingleObjectMixin
from .hands import AdminUserRequiredMixin from .hands import AdminUserRequiredMixin
from .utils import CreateSudoPrivilegesMixin, ListSudoPrivilegesMixin from .utils.mixins import CreateSudoPrivilegesMixin, ListSudoPrivilegesMixin
from models import * from models import *