diff --git a/apps/ops/models/__init__.py b/apps/ops/models/__init__.py new file mode 100644 index 000000000..c54d2d467 --- /dev/null +++ b/apps/ops/models/__init__.py @@ -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 diff --git a/apps/ops/models.py b/apps/ops/models/ansible.py similarity index 50% rename from apps/ops/models.py rename to apps/ops/models/ansible.py index 4d2346f37..f71d115a8 100644 --- a/apps/ops/models.py +++ b/apps/ops/models/ansible.py @@ -4,9 +4,7 @@ from __future__ import unicode_literals, absolute_import import logging import json -from jinja2 import Template from django.db import models -from assets.models import Asset 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} -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: [, ,...] - :param privileges: [(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" - - diff --git a/apps/ops/models/cron.py b/apps/ops/models/cron.py new file mode 100644 index 000000000..634e78be6 --- /dev/null +++ b/apps/ops/models/cron.py @@ -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" \ No newline at end of file diff --git a/apps/ops/models/sudo.py b/apps/ops/models/sudo.py new file mode 100644 index 000000000..707d03857 --- /dev/null +++ b/apps/ops/models/sudo.py @@ -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: [, ,...] + :param privileges: [(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 +""" \ No newline at end of file diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 21b1470ba..13fe8d0c1 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -1,9 +1,9 @@ from __future__ import absolute_import, unicode_literals 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") diff --git a/apps/ops/templates/cron/_cron.html b/apps/ops/templates/cron/_cron.html new file mode 100644 index 000000000..59d03e5ee --- /dev/null +++ b/apps/ops/templates/cron/_cron.html @@ -0,0 +1,97 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load bootstrap %} +{% block custom_head_css_js %} + + + +{% endblock %} + +{% block content %} +
+
+
+
+
+
{% block user_template_title %}{% trans 'Create user' %}{% endblock %}
+ +
+
+
+ {% csrf_token %} +

{% trans 'Account' %}

+ {% block username %} {% endblock %} + {{ form.email|bootstrap_horizontal }} + {{ form.name|bootstrap_horizontal }} + {{ form.groups|bootstrap_horizontal }} + +
+ {% block password %} {% endblock %} + +
+

{% trans 'Security and Role' %}

+ {{ form.role|bootstrap_horizontal }} +
+ +
+
+ + +
+ {{ form.date_expired.errors }} +
+
+{# {{ form.date_expired|bootstrap_horizontal }}#} +
+ +
+ {{ form.enable_otp }} +
+
+
+

{% trans 'Profile' %}

+ {{ form.phone|bootstrap_horizontal }} + {{ form.wechat|bootstrap_horizontal }} + {{ form.comment|bootstrap_horizontal }} +
+
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} +{% block custom_foot_js %} + + +{% endblock %} diff --git a/apps/ops/templates/cron/create.html b/apps/ops/templates/cron/create.html index 566549bdf..291a5656a 100644 --- a/apps/ops/templates/cron/create.html +++ b/apps/ops/templates/cron/create.html @@ -1,10 +1,16 @@ - - - - - Title - - - - - \ No newline at end of file +{% extends 'cron/_cron.html' %} +{% load i18n %} +{% load bootstrap %} +{% block user_template_title %}{% trans "Create user" %}{% endblock %} +{% block username %} + {{ form.username|bootstrap_horizontal }} +{% endblock %} +{% block password %} +

{% trans 'Password' %}

+
+ +
+ {% trans 'Reset link will be generated and sent to the user. ' %} +
+
+{% endblock %} \ No newline at end of file diff --git a/apps/ops/templates/cron/detail.html b/apps/ops/templates/cron/detail.html index 566549bdf..b87e17a39 100644 --- a/apps/ops/templates/cron/detail.html +++ b/apps/ops/templates/cron/detail.html @@ -1,10 +1,393 @@ - - - - - Title - - +{% extends 'base.html' %} +{% load common_tags %} +{% load users_tags %} +{% load static %} +{% load i18n %} - - \ No newline at end of file +{% block custom_head_css_js %} + + + + +{% endblock %} +{% block content %} +
+
+
+
+ +
+
+
+
+ {{ user_object.name }} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + {% if user_object.phone %} + + + + + {% endif %} + {% if user_object.wechat %} + + + + + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
{% trans 'Name' %}:{{ user_object.name }}
{% trans 'Username' %}:{{ user_object.username }}
{% trans 'Email' %}:{{ user_object.email }}
{% trans 'Phone' %}:{{ user_object.phone }}
{% trans 'Wechat' %}:{{ user_object.wechat }}
{% trans 'Role' %}:{{ user_object.get_role_display }}
{% trans 'Date expired' %}:{{ user_object.date_expired|date:"Y-m-j H:i:s" }}
{% trans 'Created by' %}:{{ user_object.created_by }}
{% trans 'Date joined' %}:{{ user_object.date_joined|date:"Y-m-j H:i:s" }}
{% trans 'Last login' %}:{{ user_object.last_login|date:"Y-m-j H:i:s" }}
{% trans 'Comment' %}:{{ user_object.comment }}
+
+
+
+
+
+
+ {% trans 'Quick modify' %} +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'Active' %}: +
+
+ + +
+
+
{% trans 'Enable OTP' %}: +
+
+ + +
+
+
{% trans 'Reset password' %}: + + + +
{% trans 'Reset ssh key' %}: + + + +
{% trans 'Update ssh key' %}: + + + +
+
+
+ +
+
+ {% trans 'User group' %} +
+
+ + + + + + + + + + + + {% for group in user_object.groups.all %} + + + + + {% endfor %} + +
+ +
+ +
{{ group.name }} + +
+
+
+
+
+
+
+
+
+ {% include 'users/_user_update_pk_modal.html' %} +{% endblock %} +{% block custom_foot_js %} + +{% endblock %} diff --git a/apps/ops/templates/cron/update.html b/apps/ops/templates/cron/update.html index 566549bdf..f033e1ed8 100644 --- a/apps/ops/templates/cron/update.html +++ b/apps/ops/templates/cron/update.html @@ -1,10 +1,20 @@ - - - - - Title - - - - - \ No newline at end of file +{% extends 'cron/_cron.html' %} +{% load i18n %} +{% block user_template_title %}{% trans "Update user" %}{% endblock %} +{% block username %} +
+ +
+ +
+
+{% endblock %} +{% block password %} +

{% trans 'Password' %}

+
+ +
+ +
+
+{% endblock %} diff --git a/apps/ops/templates/sudo/_sudo.html b/apps/ops/templates/sudo/_sudo.html new file mode 100644 index 000000000..59d03e5ee --- /dev/null +++ b/apps/ops/templates/sudo/_sudo.html @@ -0,0 +1,97 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load bootstrap %} +{% block custom_head_css_js %} + + + +{% endblock %} + +{% block content %} +
+
+
+
+
+
{% block user_template_title %}{% trans 'Create user' %}{% endblock %}
+ +
+
+
+ {% csrf_token %} +

{% trans 'Account' %}

+ {% block username %} {% endblock %} + {{ form.email|bootstrap_horizontal }} + {{ form.name|bootstrap_horizontal }} + {{ form.groups|bootstrap_horizontal }} + +
+ {% block password %} {% endblock %} + +
+

{% trans 'Security and Role' %}

+ {{ form.role|bootstrap_horizontal }} +
+ +
+
+ + +
+ {{ form.date_expired.errors }} +
+
+{# {{ form.date_expired|bootstrap_horizontal }}#} +
+ +
+ {{ form.enable_otp }} +
+
+
+

{% trans 'Profile' %}

+ {{ form.phone|bootstrap_horizontal }} + {{ form.wechat|bootstrap_horizontal }} + {{ form.comment|bootstrap_horizontal }} +
+
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} +{% block custom_foot_js %} + + +{% endblock %} diff --git a/apps/ops/templates/sudo/create.html b/apps/ops/templates/sudo/create.html index 566549bdf..19727e102 100644 --- a/apps/ops/templates/sudo/create.html +++ b/apps/ops/templates/sudo/create.html @@ -1,10 +1,16 @@ - - - - - Title - - - - - \ No newline at end of file +{% extends 'sudo/_sudo.html' %} +{% load i18n %} +{% load bootstrap %} +{% block user_template_title %}{% trans "Create user" %}{% endblock %} +{% block username %} + {{ form.username|bootstrap_horizontal }} +{% endblock %} +{% block password %} +

{% trans 'Password' %}

+
+ +
+ {% trans 'Reset link will be generated and sent to the user. ' %} +
+
+{% endblock %} \ No newline at end of file diff --git a/apps/ops/templates/sudo/detail.html b/apps/ops/templates/sudo/detail.html index 566549bdf..b87e17a39 100644 --- a/apps/ops/templates/sudo/detail.html +++ b/apps/ops/templates/sudo/detail.html @@ -1,10 +1,393 @@ - - - - - Title - - +{% extends 'base.html' %} +{% load common_tags %} +{% load users_tags %} +{% load static %} +{% load i18n %} - - \ No newline at end of file +{% block custom_head_css_js %} + + + + +{% endblock %} +{% block content %} +
+
+
+
+ +
+
+
+
+ {{ user_object.name }} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + {% if user_object.phone %} + + + + + {% endif %} + {% if user_object.wechat %} + + + + + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
{% trans 'Name' %}:{{ user_object.name }}
{% trans 'Username' %}:{{ user_object.username }}
{% trans 'Email' %}:{{ user_object.email }}
{% trans 'Phone' %}:{{ user_object.phone }}
{% trans 'Wechat' %}:{{ user_object.wechat }}
{% trans 'Role' %}:{{ user_object.get_role_display }}
{% trans 'Date expired' %}:{{ user_object.date_expired|date:"Y-m-j H:i:s" }}
{% trans 'Created by' %}:{{ user_object.created_by }}
{% trans 'Date joined' %}:{{ user_object.date_joined|date:"Y-m-j H:i:s" }}
{% trans 'Last login' %}:{{ user_object.last_login|date:"Y-m-j H:i:s" }}
{% trans 'Comment' %}:{{ user_object.comment }}
+
+
+
+
+
+
+ {% trans 'Quick modify' %} +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'Active' %}: +
+
+ + +
+
+
{% trans 'Enable OTP' %}: +
+
+ + +
+
+
{% trans 'Reset password' %}: + + + +
{% trans 'Reset ssh key' %}: + + + +
{% trans 'Update ssh key' %}: + + + +
+
+
+ +
+
+ {% trans 'User group' %} +
+
+ + + + + + + + + + + + {% for group in user_object.groups.all %} + + + + + {% endfor %} + +
+ +
+ +
{{ group.name }} + +
+
+
+
+
+
+
+
+
+ {% include 'users/_user_update_pk_modal.html' %} +{% endblock %} +{% block custom_foot_js %} + +{% endblock %} diff --git a/apps/ops/templates/sudo/update.html b/apps/ops/templates/sudo/update.html index 566549bdf..3172d23f4 100644 --- a/apps/ops/templates/sudo/update.html +++ b/apps/ops/templates/sudo/update.html @@ -1,10 +1,20 @@ - - - - - Title - - - - - \ No newline at end of file +{% extends 'sudo/_sudo.html' %} +{% load i18n %} +{% block user_template_title %}{% trans "Update user" %}{% endblock %} +{% block username %} +
+ +
+ +
+
+{% endblock %} +{% block password %} +

{% trans 'Password' %}

+
+ +
+ +
+
+{% endblock %} diff --git a/apps/ops/tests/__init__.py b/apps/ops/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/ops/tests.py b/apps/ops/tests/tests.py similarity index 100% rename from apps/ops/tests.py rename to apps/ops/tests/tests.py diff --git a/apps/ops/utils/__init__.py b/apps/ops/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/ops/ansible_api.py b/apps/ops/utils/ansible_api.py similarity index 99% rename from apps/ops/ansible_api.py rename to apps/ops/utils/ansible_api.py index 48a313767..1ecc707ed 100644 --- a/apps/ops/ansible_api.py +++ b/apps/ops/utils/ansible_api.py @@ -18,7 +18,7 @@ from ansible.utils.display import Display from ansible.playbook.play import Play 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__) diff --git a/apps/ops/utils.py b/apps/ops/utils/mixins.py similarity index 92% rename from apps/ops/utils.py rename to apps/ops/utils/mixins.py index 9cb69df23..9f925a420 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils/mixins.py @@ -10,7 +10,4 @@ class CreateSudoPrivilegesMixin(object): class ListSudoPrivilegesMixin(object): def get_all_privilege(self): - pass - - - + pass \ No newline at end of file diff --git a/apps/ops/views.py b/apps/ops/views.py index 4b312dd2c..5423b4942 100644 --- a/apps/ops/views.py +++ b/apps/ops/views.py @@ -7,7 +7,7 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.detail import DetailView, SingleObjectMixin from .hands import AdminUserRequiredMixin -from .utils import CreateSudoPrivilegesMixin, ListSudoPrivilegesMixin +from .utils.mixins import CreateSudoPrivilegesMixin, ListSudoPrivilegesMixin from models import *