From 20cf7c7c52038bd2979568684ac5ad7596049246 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 29 Apr 2020 11:08:09 +0800 Subject: [PATCH] [Update] Add settings api --- apps/settings/api.py | 64 ++++++++++++++- apps/settings/serializers/__init__.py | 1 + apps/settings/serializers/settings.py | 113 ++++++++++++++++++++++++++ apps/settings/urls/api_urls.py | 6 ++ apps/settings/utils/__init__.py | 1 + apps/settings/utils/common.py | 18 ++++ 6 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 apps/settings/serializers/settings.py create mode 100644 apps/settings/utils/common.py diff --git a/apps/settings/api.py b/apps/settings/api.py index 38167a7e3..69f0129f8 100644 --- a/apps/settings/api.py +++ b/apps/settings/api.py @@ -12,18 +12,19 @@ from django.utils.translation import ugettext_lazy as _ from .utils import ( LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil, - LDAP_USE_CACHE_FLAGS, LDAPTestUtil, + LDAP_USE_CACHE_FLAGS, LDAPTestUtil, ObjectDict ) from .tasks import sync_ldap_user_task from common.permissions import IsOrgAdmin, IsSuperUser from common.utils import get_logger from .serializers import ( MailTestSerializer, LDAPTestConfigSerializer, LDAPUserSerializer, - PublicSettingSerializer, LDAPTestLoginSerializer, + PublicSettingSerializer, LDAPTestLoginSerializer, BaseSettingSerializer, + BasicSettingSerializer, EmailContentSettingSerializer, EmailSettingSerializer, + SecuritySettingSerializer, LdapSettingSerializer, TerminalSettingSerializer ) from users.models import User - logger = get_logger(__file__) @@ -59,7 +60,7 @@ class MailTestingAPI(APIView): use_tls=email_use_tls, use_ssl=email_use_ssl, ) send_mail( - subject, message, email_from, [email_recipient], + subject, message, email_from, [email_recipient], connection=connection ) except SMTPSenderRefused as e: @@ -275,3 +276,58 @@ class PublicSettingApi(generics.RetrieveAPIView): return instance +class BaseSettingApi(generics.RetrieveUpdateAPIView): + permission_classes = (IsSuperUser,) + serializer_class = BaseSettingSerializer + setting_fields = [] + + def get_object(self): + instance = {field: getattr(settings, field) for field in self.setting_fields} + return ObjectDict(instance) + + def perform_update(self, serializer): + serializer.save() + + +class BasicSettingApi(BaseSettingApi): + serializer_class = BasicSettingSerializer + setting_fields = ['SITE_URL', 'USER_GUIDE_URL', 'EMAIL_SUBJECT_PREFIX'] + + +class EmailSettingApi(BaseSettingApi): + serializer_class = EmailSettingSerializer + setting_fields = ['EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER', + 'EMAIL_HOST_PASSWORD', 'EMAIL_FROM', 'EMAIL_RECIPIENT', + 'EMAIL_USE_SSL', 'EMAIL_USE_TLS'] + + +class EmailContentSettingApi(BaseSettingApi): + serializer_class = EmailContentSettingSerializer + setting_fields = ['EMAIL_CUSTOM_USER_CREATED_SUBJECT', 'EMAIL_CUSTOM_USER_CREATED_HONORIFIC', + 'EMAIL_CUSTOM_USER_CREATED_BODY', 'EMAIL_CUSTOM_USER_CREATED_SIGNATURE', ] + + +class LdapSettingApi(BaseSettingApi): + serializer_class = LdapSettingSerializer + setting_fields = ['AUTH_LDAP_SERVER_URI', 'AUTH_LDAP_BIND_DN', + 'AUTH_LDAP_BIND_PASSWORD', 'AUTH_LDAP_SEARCH_OU', + 'AUTH_LDAP_SEARCH_FILTER', 'AUTH_LDAP_USER_ATTR_MAP', + 'AUTH_LDAP'] + + +class TerminalSettingApi(BaseSettingApi): + serializer_class = TerminalSettingSerializer + setting_fields = ['TERMINAL_PASSWORD_AUTH', 'TERMINAL_PUBLIC_KEY_AUTH', + 'TERMINAL_HEARTBEAT_INTERVAL', 'TERMINAL_ASSET_LIST_SORT_BY', + 'TERMINAL_ASSET_LIST_PAGE_SIZE', 'TERMINAL_SESSION_KEEP_DURATION', + 'TERMINAL_TELNET_REGEX'] + + +class SecuritySettingApi(BaseSettingApi): + serializer_class = SecuritySettingSerializer + setting_fields = ['SECURITY_MFA_AUTH', 'SECURITY_COMMAND_EXECUTION', + 'SECURITY_SERVICE_ACCOUNT_REGISTRATION', 'SECURITY_LOGIN_LIMIT_COUNT', + 'SECURITY_LOGIN_LIMIT_TIME', 'SECURITY_MAX_IDLE_TIME', + 'SECURITY_PASSWORD_EXPIRATION_TIME', 'SECURITY_PASSWORD_MIN_LENGTH', + 'SECURITY_PASSWORD_UPPER_CASE', 'SECURITY_PASSWORD_LOWER_CASE', + 'SECURITY_PASSWORD_NUMBER', 'SECURITY_PASSWORD_SPECIAL_CHAR'] diff --git a/apps/settings/serializers/__init__.py b/apps/settings/serializers/__init__.py index 045763364..5868a76df 100644 --- a/apps/settings/serializers/__init__.py +++ b/apps/settings/serializers/__init__.py @@ -4,3 +4,4 @@ from .email import * from .ldap import * from .public import * +from .settings import * diff --git a/apps/settings/serializers/settings.py b/apps/settings/serializers/settings.py new file mode 100644 index 000000000..de22ba2eb --- /dev/null +++ b/apps/settings/serializers/settings.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +from django.db import transaction +from django.utils.translation import ugettext_lazy as _ +from rest_framework import serializers +from ..models import Setting + +__all__ = ['BaseSettingSerializer', 'BasicSettingSerializer', 'EmailSettingSerializer', + "EmailContentSettingSerializer", 'LdapSettingSerializer', + 'TerminalSettingSerializer', 'SecuritySettingSerializer'] + + +class BaseSettingSerializer(serializers.Serializer): + encrypt_fields = ["EMAIL_HOST_PASSWORD", "AUTH_LDAP_BIND_PASSWORD"] + + def create(self, validated_data): + pass + + def update(self, instance, validated_data): + self.update_validated_settings(validated_data) + for field_name, field_value in validated_data.items(): + setattr(instance, field_name, field_value) + return instance + + def update_validated_settings(self, validated_data, category='default'): + with transaction.atomic(): + for field_name, field_value in validated_data.items(): + try: + setting = Setting.objects.get(name=field_name) + except Setting.DoesNotExist: + setting = Setting() + encrypted = True if field_name in self.encrypt_fields else False + setting.name = field_name + setting.category = category + setting.encrypted = encrypted + setting.cleaned_value = field_value + setting.save() + + +class BasicSettingSerializer(BaseSettingSerializer): + SITE_URL = serializers.URLField(required=True) + USER_GUIDE_URL = serializers.URLField(required=False) + EMAIL_SUBJECT_PREFIX = serializers.CharField(max_length=1024, required=True) + + +class EmailSettingSerializer(BaseSettingSerializer): + encrypt_fields = ["EMAIL_HOST_PASSWORD", ] + + EMAIL_HOST = serializers.CharField(max_length=1024, required=True) + EMAIL_PORT = serializers.CharField(max_length=5, required=True) + EMAIL_HOST_USER = serializers.CharField(max_length=128, required=True) + EMAIL_HOST_PASSWORD = serializers.CharField(max_length=1024, required=False, write_only=True) + EMAIL_FROM = serializers.CharField(max_length=128, required=False) + EMAIL_RECIPIENT = serializers.CharField(max_length=128, allow_blank='', required=False) + EMAIL_USE_SSL = serializers.BooleanField(required=False) + EMAIL_USE_TLS = serializers.BooleanField(required=False) + + +class EmailContentSettingSerializer(BaseSettingSerializer): + EMAIL_CUSTOM_USER_CREATED_SUBJECT = serializers.CharField(max_length=1024, required=False, ) + EMAIL_CUSTOM_USER_CREATED_HONORIFIC = serializers.CharField(max_length=1024, required=False, ) + EMAIL_CUSTOM_USER_CREATED_BODY = serializers.CharField(max_length=4096, required=False) + EMAIL_CUSTOM_USER_CREATED_SIGNATURE = serializers.CharField(max_length=512, required=False) + + +class LdapSettingSerializer(BaseSettingSerializer): + encrypt_fields = ["AUTH_LDAP_BIND_PASSWORD", ] + + AUTH_LDAP_SERVER_URI = serializers.CharField(required=True) + AUTH_LDAP_BIND_DN = serializers.CharField(required=False) + AUTH_LDAP_BIND_PASSWORD = serializers.CharField(max_length=1024, write_only=True) + AUTH_LDAP_SEARCH_OU = serializers.CharField(max_length=1024, required=False) + AUTH_LDAP_SEARCH_FILTER = serializers.CharField(max_length=1024, required=True) + AUTH_LDAP_USER_ATTR_MAP = serializers.CharField(max_length=1024, required=True) + AUTH_LDAP = serializers.BooleanField(required=False) + + +class TerminalSettingSerializer(BaseSettingSerializer): + SORT_BY_CHOICES = ( + ('hostname', _('Hostname')), + ('ip', _('IP')) + ) + + PAGE_SIZE_CHOICES = ( + ('all', _('All')), + ('auto', _('Auto')), + (10, 10), + (15, 15), + (25, 25), + (50, 50), + ) + TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False) + TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(required=False) + TERMINAL_HEARTBEAT_INTERVAL = serializers.IntegerField(min_value=5, max_value=99999, required=True) + TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES) + TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES) + TERMINAL_SESSION_KEEP_DURATION = serializers.IntegerField(min_value=1, max_value=99999, required=True) + TERMINAL_TELNET_REGEX = serializers.CharField(required=False) + + +class SecuritySettingSerializer(BaseSettingSerializer): + SECURITY_MFA_AUTH = serializers.BooleanField(required=False) + SECURITY_COMMAND_EXECUTION = serializers.BooleanField(required=False) + SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField(required=True) + SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(min_value=3, max_value=99999, required=True) + SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(min_value=5, max_value=99999, required=True) + SECURITY_MAX_IDLE_TIME = serializers.IntegerField(min_value=5, max_value=99999, required=False) + SECURITY_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(min_value=1, max_value=99999, required=True) + SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(min_value=6, max_value=30, required=True) + SECURITY_PASSWORD_UPPER_CASE = serializers.BooleanField(required=False) + SECURITY_PASSWORD_LOWER_CASE = serializers.BooleanField(required=False) + SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False) + SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False) diff --git a/apps/settings/urls/api_urls.py b/apps/settings/urls/api_urls.py index 689e1ea82..093bc9c15 100644 --- a/apps/settings/urls/api_urls.py +++ b/apps/settings/urls/api_urls.py @@ -14,5 +14,11 @@ urlpatterns = [ path('ldap/users/import/', api.LDAPUserImportAPI.as_view(), name='ldap-user-import'), path('ldap/cache/refresh/', api.LDAPCacheRefreshAPI.as_view(), name='ldap-cache-refresh'), + path('basic/', api.BasicSettingApi.as_view(), name='basic-settings'), + path('email/', api.EmailSettingApi.as_view(), name='email-settings'), + path('email-content/', api.EmailContentSettingApi.as_view(), name='email-content-settings'), + path('ldap/', api.LdapSettingApi.as_view(), name='ldap-settings'), + path('terminal/', api.TerminalSettingApi.as_view(), name='terminal-settings'), + path('security/', api.SecuritySettingApi.as_view(), name='security-settings'), path('public/', api.PublicSettingApi.as_view(), name='public-setting'), ] diff --git a/apps/settings/utils/__init__.py b/apps/settings/utils/__init__.py index 87bc6198f..e17c4e43c 100644 --- a/apps/settings/utils/__init__.py +++ b/apps/settings/utils/__init__.py @@ -2,3 +2,4 @@ # from .ldap import * +from .common import * diff --git a/apps/settings/utils/common.py b/apps/settings/utils/common.py new file mode 100644 index 000000000..e64ceaf7f --- /dev/null +++ b/apps/settings/utils/common.py @@ -0,0 +1,18 @@ +# coding: utf-8 + + +class ObjectDict(dict): + def __getattr__(self, name): + if name in self: + return self[name] + else: + raise AttributeError("No such attribute: " + name) + + def __setattr__(self, name, value): + self[name] = value + + def __delattr__(self, name): + if name in self: + del self[name] + else: + raise AttributeError("No such attribute: " + name)