From 76df1de634fcfb475bfe955abec79b380acc8a64 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 21 Dec 2017 11:31:13 +0800 Subject: [PATCH] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=98=8E=E6=98=BE=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api.py | 2 + apps/assets/forms.py | 17 +- apps/assets/models/asset.py | 6 +- apps/assets/models/group.py | 1 - apps/assets/models/user.py | 16 +- apps/assets/tasks.py | 6 - .../assets/templates/assets/asset_detail.html | 30 +- apps/assets/templates/assets/asset_list.html | 80 ++--- .../assets/templates/assets/cluster_list.html | 1 + .../templates/assets/system_user_list.html | 7 + .../templates/assets/user_asset_list.html | 273 ++++-------------- apps/assets/utils.py | 10 + apps/common/models.py | 3 - apps/common/utils.py | 8 +- apps/jumpserver/settings.py | 1 - apps/ops/ansible/callback.py | 19 +- apps/ops/ansible/inventory.py | 1 + apps/ops/templates/ops/task_list.html | 4 +- apps/ops/utils.py | 7 +- apps/perms/forms.py | 31 ++ .../perms/asset_permission_create_update.html | 2 +- .../perms/asset_permission_list.html | 6 + apps/perms/views.py | 28 +- .../img/avatar/admin.png} | Bin apps/static/img/avatar/user.png | Bin 0 -> 62768 bytes apps/static/js/jumpserver.js | 24 +- apps/templates/_left_side_bar.html | 2 +- apps/templates/_nav.html | 14 +- apps/templates/_user_profile.html | 19 ++ apps/terminal/tasks.py | 6 - .../templates/terminal/command_list.html | 5 +- .../templates/terminal/terminal_list.html | 8 +- apps/users/forms.py | 33 ++- apps/users/models/user.py | 11 +- .../users/templates/users/login_log_list.html | 8 +- apps/users/templates/users/user_list.html | 2 +- 36 files changed, 302 insertions(+), 389 deletions(-) rename apps/{media/avatar/default.png => static/img/avatar/admin.png} (100%) create mode 100644 apps/static/img/avatar/user.png diff --git a/apps/assets/api.py b/apps/assets/api.py index 860f7111c..1fe371dcd 100644 --- a/apps/assets/api.py +++ b/apps/assets/api.py @@ -44,9 +44,11 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet): else: assets_granted = get_user_granted_assets(self.request.user) queryset = self.queryset.filter(id__in=[asset.id for asset in assets_granted]) + cluster_id = self.request.query_params.get('cluster_id') asset_group_id = self.request.query_params.get('asset_group_id') admin_user_id = self.request.query_params.get('admin_user_id') + if cluster_id: queryset = queryset.filter(cluster__id=cluster_id) if asset_group_id: diff --git a/apps/assets/forms.py b/apps/assets/forms.py index 2bf6df507..e41044f16 100644 --- a/apps/assets/forms.py +++ b/apps/assets/forms.py @@ -1,5 +1,4 @@ # coding:utf-8 -import uuid from django import forms from django.utils.translation import gettext_lazy as _ @@ -9,7 +8,6 @@ from common.utils import validate_ssh_private_key, ssh_pubkey_gen, ssh_key_gen, logger = get_logger(__file__) -from rest_framework import serializers class AssetCreateForm(forms.ModelForm): @@ -57,11 +55,11 @@ class AssetUpdateForm(forms.ModelForm): class AssetBulkUpdateForm(forms.ModelForm): - assets = forms.MultipleChoiceField( + assets = forms.ModelMultipleChoiceField( required=True, help_text='* required', label=_('Select assets'), - choices=[(asset.id, asset.hostname) for asset in Asset.objects.all()], + queryset=Asset.objects.all(), widget=forms.SelectMultiple( attrs={ 'class': 'select2', @@ -94,10 +92,9 @@ class AssetBulkUpdateForm(forms.ModelForm): cleaned_data = {k: v for k, v in self.cleaned_data.items() if k in changed_fields} - print(cleaned_data) - assets_id = cleaned_data.pop('assets') + assets = cleaned_data.pop('assets') groups = cleaned_data.pop('groups', []) - assets = Asset.objects.filter(id__in=assets_id) + assets = Asset.objects.filter(id__in=[asset.id for asset in assets]) assets.update(**cleaned_data) if groups: for asset in assets: @@ -175,16 +172,18 @@ class AdminUserForm(forms.ModelForm): password = None if private_key: - public_key = ssh_pubkey_gen(private_key) + public_key = ssh_pubkey_gen(private_key, password=password) admin_user.set_auth(password=password, public_key=public_key, private_key=private_key) return admin_user def clean_private_key_file(self): private_key_file = self.cleaned_data['private_key_file'] + password = self.cleaned_data['password'] + if private_key_file: private_key = private_key_file.read() - if not validate_ssh_private_key(private_key): + if not validate_ssh_private_key(private_key, password): raise forms.ValidationError(_('Invalid private key')) return private_key return private_key_file diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 1bbc2ddd7..02d2724d6 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -18,10 +18,6 @@ __all__ = ['Asset'] logger = logging.getLogger(__name__) -def get_default_cluster(): - return Cluster.initial() - - class Asset(models.Model): # Todo: Move them to settings STATUS_CHOICES = ( @@ -48,7 +44,7 @@ class Asset(models.Model): hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) port = models.IntegerField(default=22, verbose_name=_('Port')) groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups')) - cluster = models.ForeignKey(Cluster, blank=True, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('Cluster'),) + cluster = models.ForeignKey(Cluster, blank=True, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('Cluster')) is_active = models.BooleanField(default=True, verbose_name=_('Is active')) type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, default='Server', verbose_name=_('Asset type'),) env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, default='Prod', verbose_name=_('Asset environment'),) diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py index 965ceb1f3..18b0c5289 100644 --- a/apps/assets/models/group.py +++ b/apps/assets/models/group.py @@ -10,7 +10,6 @@ from django.db import models import logging from django.utils.translation import ugettext_lazy as _ -from .user import SystemUser __all__ = ['AssetGroup'] logger = logging.getLogger(__name__) diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 56651b4eb..674ffa008 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -66,16 +66,15 @@ class AssetUser(models.Model): @property def private_key_file(self): - if not self.private_key: + if not self.private_key_obj: return None project_dir = settings.PROJECT_DIR tmp_dir = os.path.join(project_dir, 'tmp') key_str = signer.unsign(self._private_key) - key_name = md5(key_str.encode('utf-8')).hexdigest() + key_name = '.' + md5(key_str.encode('utf-8')).hexdigest() key_path = os.path.join(tmp_dir, key_name) if not os.path.exists(key_path): - with open(key_path, 'w') as f: - f.write(key_str) + self.private_key_obj.write_private_key_file(key_path) os.chmod(key_path, 0o400) return key_path @@ -105,7 +104,6 @@ class AssetUser(models.Model): update_fields.append('_public_key') if update_fields: - print(update_fields) self.save(update_fields=update_fields) def auto_gen_auth(self): @@ -149,7 +147,11 @@ class AdminUser(AssetUser): @property def become_pass(self): - return signer.unsign(self._become_pass) + password = signer.unsign(self._become_pass) + if password: + return password + else: + return "" @become_pass.setter def become_pass(self, password): @@ -199,7 +201,7 @@ class SystemUser(AssetUser): ('K', 'Public key'), ) cluster = models.ManyToManyField('assets.Cluster', blank=True, verbose_name=_("Cluster")) - priority = models.IntegerField(default=10, verbose_name=_("Priority")) # Todo: If user granted more priority user, default will be login as the hign + priority = models.IntegerField(default=10, verbose_name=_("Priority")) protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol')) auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) sudo = models.TextField(default='/sbin/ifconfig', verbose_name=_('Sudo')) diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 09430da96..a46e697fc 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -402,12 +402,6 @@ def push_system_user_on_auth_change(sender, instance=None, update_fields=None, * push_system_user_to_cluster_assets.delay(instance, task_name) -@receiver(on_app_ready, dispatch_uid="my_unique_identifier") -def test_admin_user_on_app_ready(sender, **kwargs): - logger.debug("Receive app ready signal, test admin connectability") - test_admin_user_connectability_period.delay() - - celery_app.conf['CELERYBEAT_SCHEDULE'].update( { 'update_assets_hardware_period': { diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html index dce243c0e..cb5b082cc 100644 --- a/apps/assets/templates/assets/asset_detail.html +++ b/apps/assets/templates/assets/asset_detail.html @@ -63,7 +63,7 @@ {% trans 'Public IP' %}: - {{ asset.public_ip }} + {{ asset.public_ip|default:"" }} {% trans 'Port' %}: @@ -74,12 +74,12 @@ {% if asset.admin_user_avail %} {{ asset.admin_user_avail.name }} {% else %} - None + {% endif %} {% trans 'Remote card IP' %}: - {{ asset.remote_card_ip }} + {{ asset.remote_card_ip|default:"" }} {% trans 'Cluster' %}: @@ -87,39 +87,39 @@ {% trans 'Cabinet number' %}: - {{ asset.cabinet_no }} + {{ asset.cabinet_no|default:"" }} {% trans 'Cabinet position' %}: - {{ asset.cabinet_pos }} + {{ asset.cabinet_pos|default:"" }} {% trans 'Vendor' %}: - {{ asset.vendor }} + {{ asset.vendor|default:"" }} {% trans 'Model' %}: - {{ asset.model }} + {{ asset.model|default:"" }} {% trans 'CPU' %}: - {{ asset.cpu_model }} {{ asset.cpu_count }}*{{ asset.cpu_cores }} + {{ asset.cpu_model|default:"" }} {{ asset.cpu_count|default:"" }}*{{ asset.cpu_cores|default:"" }} {% trans 'Memory' %}: - {{ asset.memory }} + {{ asset.memory|default:"" }} {% trans 'Disk' %}: - {{ asset.disk_total }} + {{ asset.disk_total|default:"" }} {% trans 'Platform' %}: - {{ asset.platform }} + {{ asset.platform|default:"" }} {% trans 'OS' %}: - {{ asset.os }} {{ asset.os_version }} {{ asset.os_arch }} + {{ asset.os|default:"" }} {{ asset.os_version|default:"" }} {{ asset.os_arch|default:"" }} {% trans 'Asset status' %}: @@ -127,7 +127,7 @@ {% trans 'Is active' %}: - {{ asset.is_active }} + {{ asset.is_active|yesno:"Yes,No" }} {% trans 'Asset type' %}: @@ -139,11 +139,11 @@ {% trans 'Serial number' %}: - {{ asset.sn }} + {{ asset.sn|default:"" }} {% trans 'Asset number' %}: - {{ asset.number }} + {{ asset.number|default:"" }} {% trans 'Created by' %}: diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index d1475906d..fa7638879 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -64,8 +64,7 @@ {% endblock %} + {% block table_search %}{% endblock %} {% block table_container %}
diff --git a/apps/assets/templates/assets/system_user_list.html b/apps/assets/templates/assets/system_user_list.html index 2580b3b7d..5ad20a57f 100644 --- a/apps/assets/templates/assets/system_user_list.html +++ b/apps/assets/templates/assets/system_user_list.html @@ -1,6 +1,13 @@ {% extends '_base_list.html' %} {% load i18n %} +{% block help_message %} +
+ 系统用户是 用户登录资产(服务器)时使用的用户,如 web, sa, dba等具有特殊功能的用户。系统用户创建时,如果选择了自动推送 + Jumpserver会使用ansible自动推送到系统用户所在集群的资产中,如果资产(交换机)不支持ansible, 请手动填写账号密码。 +
+{% endblock %} + {% block table_search %} {% endblock %} diff --git a/apps/assets/templates/assets/user_asset_list.html b/apps/assets/templates/assets/user_asset_list.html index 0b137a961..4278ffa4e 100644 --- a/apps/assets/templates/assets/user_asset_list.html +++ b/apps/assets/templates/assets/user_asset_list.html @@ -5,26 +5,22 @@ - {% endblock %} {% block content_left_head %}{% endblock %} {% block table_search %} -{#
#} -{# #} -{#
#} + {% endblock %} - {% block table_container %} @@ -36,8 +32,8 @@ - - + + @@ -48,216 +44,45 @@ {% block custom_foot_js %} diff --git a/apps/assets/utils.py b/apps/assets/utils.py index e21a2120e..ab63bbafc 100644 --- a/apps/assets/utils.py +++ b/apps/assets/utils.py @@ -1,5 +1,6 @@ # ~*~ coding: utf-8 ~*~ # +from collections import defaultdict from common.utils import get_object_or_none from .models import Asset, SystemUser @@ -17,3 +18,12 @@ def get_system_user_by_name(name): return system_user +def check_assets_have_system_user(assets, system_users): + errors = defaultdict(list) + + for system_user in system_users: + clusters = system_user.cluster.all() + for asset in assets: + if asset.cluster not in clusters: + errors[asset].append(system_user) + return errors diff --git a/apps/common/models.py b/apps/common/models.py index bd4b2abe9..beeb30826 100644 --- a/apps/common/models.py +++ b/apps/common/models.py @@ -1,5 +1,2 @@ -from __future__ import unicode_literals - from django.db import models -# Create your models here. diff --git a/apps/common/utils.py b/apps/common/utils.py index 236ae2e02..e7b07860b 100644 --- a/apps/common/utils.py +++ b/apps/common/utils.py @@ -195,11 +195,11 @@ def ssh_key_string_to_obj(text, password=None): return key -def ssh_pubkey_gen(private_key=None, username='jumpserver', hostname='localhost'): +def ssh_pubkey_gen(private_key=None, username='jumpserver', hostname='localhost', password=None): if isinstance(private_key, bytes): private_key = private_key.decode("utf-8") if isinstance(private_key, string_types): - private_key = ssh_key_string_to_obj(private_key) + private_key = ssh_key_string_to_obj(private_key, password=password) if not isinstance(private_key, (paramiko.RSAKey, paramiko.DSSKey)): raise IOError('Invalid private key') @@ -238,14 +238,14 @@ def ssh_key_gen(length=2048, type='rsa', password=None, username='jumpserver', h raise IOError('These is error when generate ssh key.') -def validate_ssh_private_key(text): +def validate_ssh_private_key(text, password=None): if isinstance(text, bytes): try: text = text.decode("utf-8") except UnicodeDecodeError: return False - key = ssh_key_string_to_obj(text) + key = ssh_key_string_to_obj(text, password=password) if key is None: return False else: diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 783c29710..e8b2d19df 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -59,7 +59,6 @@ INSTALLED_APPS = [ 'assets.apps.AssetsConfig', 'perms.apps.PermsConfig', 'ops.apps.OpsConfig', - # 'audits.apps.AuditsConfig', 'common.apps.CommonConfig', 'terminal.apps.TerminalConfig', 'rest_framework', diff --git a/apps/ops/ansible/callback.py b/apps/ops/ansible/callback.py index 37df92beb..810b14c51 100644 --- a/apps/ops/ansible/callback.py +++ b/apps/ops/ansible/callback.py @@ -1,7 +1,5 @@ # ~*~ coding: utf-8 ~*~ -from collections import defaultdict - from ansible.plugins.callback import CallbackBase from ansible.plugins.callback.default import CallbackModule @@ -21,9 +19,8 @@ class AdHocResultCallback(CallbackModule): # "contacted": {"hostname",...}, # "dark": {"hostname": {"task_name": {}, "task_name": {}},...,}, # } - self.results_raw = dict(ok=defaultdict(dict), failed=defaultdict(dict), - unreachable=defaultdict(dict), skipped=defaultdict(dict)) - self.results_summary = dict(contacted=[], dark=defaultdict(dict)) + self.results_raw = dict(ok={}, failed={}, unreachable={}, skipped={}) + self.results_summary = dict(contacted=[], dark={}) super().__init__() def gather_result(self, t, res): @@ -34,8 +31,8 @@ class AdHocResultCallback(CallbackModule): if self.results_raw[t].get(host): self.results_raw[t][host][task_name] = task_result - # else: - # self.results_raw[t][host] = {task_name: task_result} + else: + self.results_raw[t][host] = {task_name: task_result} self.clean_result(t, host, task_name, task_result) def clean_result(self, t, host, task_name, task_result): @@ -45,10 +42,10 @@ class AdHocResultCallback(CallbackModule): if host not in contacted: contacted.append(host) else: - # if dark.get(host): - dark[host][task_name] = task_result.values - # else: - # dark[host] = {task_name: task_result} + if dark.get(host): + dark[host][task_name] = task_result.values + else: + dark[host] = {task_name: task_result} if host in contacted: contacted.remove(host) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index d3d342368..94dfaa984 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -32,6 +32,7 @@ class BaseHost(Host): } """ self.host_data = host_data + print(host_data) hostname = host_data.get('hostname') or host_data.get('ip') port = host_data.get('port') or 22 super().__init__(hostname, port) diff --git a/apps/ops/templates/ops/task_list.html b/apps/ops/templates/ops/task_list.html index c08fad156..503f1046a 100644 --- a/apps/ops/templates/ops/task_list.html +++ b/apps/ops/templates/ops/task_list.html @@ -27,7 +27,7 @@
@@ -37,7 +37,7 @@ {% block table_head %} - + diff --git a/apps/ops/utils.py b/apps/ops/utils.py index a79e10aa7..994e81db0 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -1,8 +1,8 @@ # ~*~ coding: utf-8 ~*~ -import re import time from django.utils import timezone +from django.db import transaction from common.utils import get_logger, get_object_or_none, get_short_uuid_str from .ansible import AdHocRunner, CommandResultCallback @@ -58,6 +58,7 @@ def get_inventory(hostname_list, run_as_admin=False, run_as=None, become_info=No ) +@record_adhoc def get_adhoc_runner(hostname_list, run_as_admin=False, run_as=None, become_info=None): inventory = get_inventory( hostname_list, run_as_admin=run_as_admin, @@ -67,7 +68,6 @@ def get_adhoc_runner(hostname_list, run_as_admin=False, run_as=None, become_info return runner -@record_adhoc def run_adhoc_object(adhoc, **options): """ :param adhoc: Instance of AdHoc @@ -109,6 +109,8 @@ def create_or_update_task( run_as_admin=False, run_as="", become_info=None, created_by=None ): + print(options) + print(task_name) task = get_object_or_none(Task, name=task_name) if task is None: task = Task(name=task_name, created_by=created_by) @@ -125,6 +127,7 @@ def create_or_update_task( if not adhoc or adhoc != new_adhoc: new_adhoc.save() task.latest_adhoc = new_adhoc + print("Return task") return task diff --git a/apps/perms/forms.py b/apps/perms/forms.py index f6f41f624..c4c4ff0c9 100644 --- a/apps/perms/forms.py +++ b/apps/perms/forms.py @@ -38,3 +38,34 @@ class AssetPermissionForm(forms.ModelForm): 'user_groups': _('User or user group at least one required'), 'asset_groups': _('Asset or Asset group at least one required'), } + + def clean_system_users(self): + from assets.utils import check_assets_have_system_user + + errors = [] + assets = self.cleaned_data['assets'] + asset_groups = self.cleaned_data['asset_groups'] + system_users = self.cleaned_data['system_users'] + + error_data = check_assets_have_system_user(assets, system_users) + if error_data: + for asset, system_users in error_data.items(): + msg = _("Asset {} not have [{}] system users, please check \n") + error = forms.ValidationError(msg.format( + asset.hostname, + ", ".join(system_user.name for system_user in system_users) + )) + errors.append(error) + + for group in asset_groups: + msg = _("Asset {}: {} not have [{}] system users, please check") + assets = group.assets.all() + error_data = check_assets_have_system_user(assets, system_users) + for asset, system_users in error_data.items(): + errors.append(msg.format( + group.name, asset.hostname, + ", ".join(system_user.name for system_user in system_users) + )) + if errors: + raise forms.ValidationError(errors) + return self.cleaned_data['system_users'] diff --git a/apps/perms/templates/perms/asset_permission_create_update.html b/apps/perms/templates/perms/asset_permission_create_update.html index b8c2a60f0..86a11ba62 100644 --- a/apps/perms/templates/perms/asset_permission_create_update.html +++ b/apps/perms/templates/perms/asset_permission_create_update.html @@ -55,7 +55,7 @@
- +
{{ form.date_expired.errors }}
diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 71861702b..da4c88f80 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -4,6 +4,12 @@ {% block table_search %} {% endblock %} +{% block help_message %} +
+ 提前规划好集群中的系统用户,授权时选择的资产(组内资产)必须存在该系统用户,否则可能无法成功登录 +
+{% endblock %} + {% block table_container %}
diff --git a/apps/perms/views.py b/apps/perms/views.py index 2ad929c4b..d1c44a46a 100644 --- a/apps/perms/views.py +++ b/apps/perms/views.py @@ -66,9 +66,7 @@ class MessageMixin: return success_message -class AssetPermissionCreateView(AdminUserRequiredMixin, - MessageMixin, - CreateView): +class AssetPermissionCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): model = AssetPermission form_class = AssetPermissionForm template_name = 'perms/asset_permission_create_update.html' @@ -83,8 +81,19 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, kwargs.update(context) return super().get_context_data(**kwargs) + def get_success_message(self, cleaned_data): + url = reverse_lazy( + 'perms:asset-permission-detail', + kwargs={'pk': self.object.pk} + ) + success_message = _( + 'Create asset permission {name} ' + 'success.'.format(url=url, name=self.object.name) + ) + return success_message -class AssetPermissionUpdateView(AdminUserRequiredMixin, MessageMixin, UpdateView): + +class AssetPermissionUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView): model = AssetPermission form_class = AssetPermissionForm template_name = 'perms/asset_permission_create_update.html' @@ -98,6 +107,17 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, MessageMixin, UpdateView kwargs.update(context) return super().get_context_data(**kwargs) + def get_success_message(self, cleaned_data): + url = reverse_lazy( + 'perms:asset-permission-detail', + kwargs={'pk': self.object.pk} + ) + success_message = _( + 'Update asset permission {name} ' + 'success.'.format(url=url, name=self.object.name) + ) + return success_message + class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView): template_name = 'perms/asset_permission_detail.html' diff --git a/apps/media/avatar/default.png b/apps/static/img/avatar/admin.png similarity index 100% rename from apps/media/avatar/default.png rename to apps/static/img/avatar/admin.png diff --git a/apps/static/img/avatar/user.png b/apps/static/img/avatar/user.png new file mode 100644 index 0000000000000000000000000000000000000000..0c7d8fb74463092f8bb0f82d60df55df312369e2 GIT binary patch literal 62768 zcmV)IK)k<+P)RS z{nzuKd!0H}T~%G(?RL|?$2OJ|qktWe5F{cY5fCIHNJvCN2nq4X0}}AWQxK293o;T& z1|>?Ihk)&1Cv6A2sjjX%_w%3sw)b9Z%{j-%!#bUpE&bBJm)2fmtnppOH~FQn zd|+ZDU4{^hB!YAW)MzeQKtdRUW=#Ujf-?1xXjRrxAp`)U0Cy*q$O?;OORF4$R-VbFz8;W-IdH{j;YpUt6*jERs60B<99YFqxTZ^NcoyT8k!jwG>Yhs+e72 z);XP?6H@k-VXA7w>#bYpn=Tqt;-k87LebZy0n-wKZwV;3PB{C3Du8AB=@$ zG!vW=A&3EqB)|X!b2UI9Yba3>2pA0l5imjm5K=HeHW8p3tu-^RHGuhg^Cu)#36LPd zvOu5-0{s51vj8E=5GF%-gpr}S5CSPRF&tfh4InLB7}x?8Y*d3l(Ik;D0tSYV%u*;4 z0URz@W^4#lOhASi8$0wySPG&bC>Yp74G2&mpnLbvo;`o5)+jWXfCL1|L7rM@F zZgx&H@@KyE_*Z`7@ztA)o3RGt;e*3mqqO$*5APf<(`PSk9Qs>-?Js}#(cZi^-~8Q1I53cqDp^z~0uf8F0Ui)# zO&}&qz3}+{=J7jsUcTJE*$$z!Ib;q~OHMr~1Qym|5b^2uk{7w4^3 z_mrJ|wk{=49(~uK))WYu%KY|`lO&RA6us62Nzo{mJVFElE?8Bi3XlvSAwp=7fshD_ z3}Yy|zW>=@`n4B7{C>1BHwXqm2#H1jBtU|MKmmdTmst?7n$a+K9{k>&vx=Zu0E}=r z=694Lm8d3|d4MLhsBjtx5OnEn$H7?v1!1f}Bb;!wFc=7=Fr6K2CLtIxHA!;M7L(9I zU07wb2|+*-V1ZyH8Gys%ql>E>sTmLe2_u6tFrdqe%b)nM_aC2i@83W9#b5l%UhUmS zcON{s^YMrGzWV4+yShBSwYb^EtLxFs{>%U5ul|GI{=K1WgSN?5ita9!m*WV9HHwx+ zS~Mg!)fNhgNG%Qy4*%H?o)1MSTBDbOb~EhjbhJ6x?#2F1ewstE(A$LCgve0V*;Jlq##L@cpm; z@RRREnP}8}Z!@~nL?R*tqmg(!kBkBu5QYFrSjZ(mxqXsjh7%-OP;cu`n^E6I00MsW zX$BHZAdK@}Lg54m2Rb1~n30YU8ksB0=@#hdeA{Q5^9fADDBZol`ZpPuh(m-Eqam!N5!CV^lt7NUifKnV;Cwg~8O(>-~; zt*r?#upy+Vz*u5GPCG#rdAW=l5u|$qpk}fZ4*C3(XjDYMT2HmqXhDc%0A!7LiwzRk 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 -
  • {% trans 'Job Center' %}
  • -
  • {% trans 'Terminal' %} @@ -65,11 +63,11 @@ {#
  • {% trans 'File download' %}
  • #} {# #} {##} -
  • - - {% trans 'Settings' %} - -
  • +{#
  • #} +{# #} +{# {% trans 'Settings' %}#} +{# #} +{#
  • #}
  • {% trans 'Profile' %}
  • {% trans 'Profile settings' %}
  • + {% if request.user.is_superuser %} + {% if request.COOKIES.admin == 'No' %} +
  • {% trans 'Admin page' %}
  • + {% else %} +
  • {% trans 'User page' %}
  • + {% endif %} + {% endif %}
  • {% trans 'Logout' %}
  • @@ -26,3 +33,15 @@ JMS + diff --git a/apps/terminal/tasks.py b/apps/terminal/tasks.py index 87a90bfcb..ed404a54b 100644 --- a/apps/terminal/tasks.py +++ b/apps/terminal/tasks.py @@ -1,13 +1,7 @@ # -*- coding: utf-8 -*- # -import time from celery import shared_task -from django.core.cache import cache -from django.db.utils import ProgrammingError, OperationalError - -from .models import Session - CACHE_REFRESH_INTERVAL = 10 diff --git a/apps/terminal/templates/terminal/command_list.html b/apps/terminal/templates/terminal/command_list.html index 3291b53ea..20e7b1bcf 100644 --- a/apps/terminal/templates/terminal/command_list.html +++ b/apps/terminal/templates/terminal/command_list.html @@ -13,7 +13,6 @@ {% endblock %} {% block content_left_head %} - 123 {% endblock %} {% block table_search %} @@ -51,12 +50,12 @@
    - +
    diff --git a/apps/terminal/templates/terminal/terminal_list.html b/apps/terminal/templates/terminal/terminal_list.html index 966edae22..3784806ce 100644 --- a/apps/terminal/templates/terminal/terminal_list.html +++ b/apps/terminal/templates/terminal/terminal_list.html @@ -78,14 +78,8 @@ function initTable() { var reject_btn = '{% trans "Reject" %}' .replace('{{ DEFAULT_PK }}', cellData) .replace('99991938', rowData.name); - var connect_btn = '{% trans "Connect" %} ' - .replace('{{ DEFAULT_PK }}', cellData); if (rowData.is_accepted) { - {% if user.is_superuser %} - $(td).html(connect_btn + update_btn + delete_btn); - {% else %} - $(td).html(connect_btn); - {% endif %} + $(td).html(update_btn + delete_btn); } else { {% if user.is_superuser %} $(td).html(accept_btn + reject_btn); diff --git a/apps/users/forms.py b/apps/users/forms.py index c2cc8c8df..48021ec74 100644 --- a/apps/users/forms.py +++ b/apps/users/forms.py @@ -67,15 +67,23 @@ class UserProfileForm(forms.ModelForm): class UserPasswordForm(forms.Form): old_password = forms.CharField( - max_length=128, widget=forms.PasswordInput) + max_length=128, widget=forms.PasswordInput, + label=_("Old password") + ) new_password = forms.CharField( - min_length=5, max_length=128, widget=forms.PasswordInput) + min_length=5, max_length=128, + widget=forms.PasswordInput, + label=_("New password") + ) confirm_password = forms.CharField( - min_length=5, max_length=128, widget=forms.PasswordInput) + min_length=5, max_length=128, + widget=forms.PasswordInput, + label=_("Confirm password") + ) def __init__(self, *args, **kwargs): self.instance = kwargs.pop('instance') - super(UserPasswordForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def clean_old_password(self): old_password = self.cleaned_data['old_password'] @@ -102,20 +110,21 @@ class UserPublicKeyForm(forms.Form): public_key = forms.CharField( label=_('ssh public key'), max_length=5000, widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}), - help_text=_('Paste your id_rsa.pub here.')) + help_text=_('Paste your id_rsa.pub here.') + ) def __init__(self, *args, **kwargs): if 'instance' in kwargs: self.instance = kwargs.pop('instance') else: self.instance = None - super(UserPublicKeyForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def clean_public_key(self): public_key = self.cleaned_data['public_key'] if self.instance.public_key and public_key == self.instance.public_key: - raise forms.ValidationError(_('Public key should not be the ' - 'same as your old one.')) + msg = _('Public key should not be the same as your old one.') + raise forms.ValidationError(msg) if not validate_ssh_public_key(public_key): raise forms.ValidationError(_('Not a valid ssh public key')) @@ -129,11 +138,11 @@ class UserPublicKeyForm(forms.Form): class UserBulkUpdateForm(forms.ModelForm): - users = forms.MultipleChoiceField( + users = forms.ModelMultipleChoiceField( required=True, help_text='* required', label=_('Select users'), - choices=[(user.id, user.name) for user in User.objects.all()], + queryset=User.objects.all(), widget=forms.SelectMultiple( attrs={ 'class': 'select2', @@ -162,9 +171,9 @@ class UserBulkUpdateForm(forms.ModelForm): cleaned_data = {k: v for k, v in self.cleaned_data.items() if k in changed_fields} - users_id = cleaned_data.pop('users', '') + users = cleaned_data.pop('users', '') groups = cleaned_data.pop('groups', []) - users = User.objects.filter(id__in=users_id) + users = User.objects.filter(id__in=[user.id for user in users]) users.update(**cleaned_data) if groups: for user in users: diff --git a/apps/users/models/user.py b/apps/users/models/user.py index dda2be521..81faccf6c 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -146,7 +146,7 @@ class User(AbstractUser): if not self.name: self.name = self.username - super(User, self).save(*args, **kwargs) + super().save(*args, **kwargs) # Add the current user to the default group. if not self.groups.count(): group = UserGroup.initial() @@ -180,13 +180,14 @@ class User(AbstractUser): return False def avatar_url(self): + admin_default = settings.STATIC_URL + "img/avatar/admin.png" + user_default = settings.STATIC_URL + "img/avatar/user.png" if self.avatar: return self.avatar.url + if self.is_superuser: + return admin_default else: - avatar_dir = os.path.join(settings.MEDIA_ROOT, 'avatar') - if os.path.isdir(avatar_dir): - return os.path.join(settings.MEDIA_URL, 'avatar', 'default.png') - return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon' + return user_default def generate_reset_token(self): return signer.sign_t({'reset': str(self.id), 'email': self.email}, expires_in=3600) diff --git a/apps/users/templates/users/login_log_list.html b/apps/users/templates/users/login_log_list.html index 8d2859b45..7ac9fe4fc 100644 --- a/apps/users/templates/users/login_log_list.html +++ b/apps/users/templates/users/login_log_list.html @@ -31,12 +31,12 @@
    - +
    @@ -85,7 +85,9 @@ forceParse: false, autoclose: true }); - $('.select2').select2(); + $('.select2').select2({ + dropdownAutoWidth: true + }); }) {% endblock %} diff --git a/apps/users/templates/users/user_list.html b/apps/users/templates/users/user_list.html index 177819e67..7612b1dfd 100644 --- a/apps/users/templates/users/user_list.html +++ b/apps/users/templates/users/user_list.html @@ -73,7 +73,7 @@ function initTable() { } }}, {targets: 6, createdCell: function (td, cellData, rowData) { - var update_btn = '{% trans "Update" %}'.replace('00000000-0000-0000-0000-000000000000', cellData); + var update_btn = '{% trans "Update" %}'.replace('00000000-0000-0000-0000-000000000000', cellData); var del_btn = ""; if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ user.username }}") {
    {% trans 'Type' %} {% trans 'Env' %} {% trans 'Hardware' %}{% trans 'Valid' %}{% trans 'Alive' %}{% trans 'Active' %}{% trans 'Connective' %}
    {% trans 'Name' %}{% trans 'F/S/T' %}{% trans 'Run times' %} {% trans 'Versions' %} {% trans 'Hosts' %} {% trans 'Success' %}