merge: with dev

pull/9416/head
ibuler 2023-02-02 18:13:32 +08:00
commit 3520f8222c
24 changed files with 70 additions and 53 deletions

View File

@ -17,8 +17,8 @@ class AccountSerializerCreateValidateMixin:
replace_attrs: callable
def to_internal_value(self, data):
self.id = data.pop('id', None)
ret = super().to_internal_value(data)
self.id = ret.pop('id', None)
self.push_now = ret.pop('push_now', False)
self.template = ret.pop('template', False)
return ret

View File

@ -20,14 +20,14 @@ class Migration(migrations.Migration):
),
migrations.AlterModelOptions(
name='commandfilteracl',
options={'ordering': ('priority', 'name'), 'verbose_name': 'Command acl'},
options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Command acl'},
),
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', 'name'), 'verbose_name': 'Login acl'},
options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Login acl'},
),
migrations.AlterModelOptions(
name='loginassetacl',
options={'ordering': ('priority', 'name'), 'verbose_name': 'Login asset acl'},
options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Login asset acl'},
),
]

View File

@ -82,7 +82,7 @@ class BaseACL(JMSBaseModel):
objects = ACLManager.from_queryset(BaseACLQuerySet)()
class Meta:
ordering = ('priority', 'name')
ordering = ('priority', 'date_updated', 'name')
abstract = True
def is_action(self, action):

View File

@ -52,10 +52,10 @@ class LoginACLSerializer(BulkModelSerializer):
action = self.fields.get("action")
if not action:
return
choices = action._choices
choices = action.choices
if not has_valid_xpack_license():
choices.pop(LoginACL.ActionChoices.review, None)
action._choices = choices
action.choices = choices
def get_rules_serializer(self):
return RuleSerializer()

View File

@ -1,8 +1,7 @@
# Generated by Django 3.2.12 on 2022-07-11 06:13
import time
from django.db import migrations, models
from assets.models import Platform
from django.db import migrations
def migrate_asset_accounts(apps, schema_editor):

View File

@ -1,5 +1,4 @@
# Generated by Django 3.2.14 on 2022-08-11 07:11
import assets.models.platform
import django.db.models
from django.db import migrations, models

View File

@ -18,6 +18,8 @@ def _create_account_obj(secret, secret_type, gateway, asset, account_model):
def migrate_gateway_to_asset(apps, schema_editor):
db_alias = schema_editor.connection.alias
node_model = apps.get_model('assets', 'Node')
org_model = apps.get_model('orgs', 'Organization')
gateway_model = apps.get_model('assets', 'Gateway')
platform_model = apps.get_model('assets', 'Platform')
gateway_platform = platform_model.objects.using(db_alias).get(name=GATEWAY_NAME)
@ -28,6 +30,16 @@ def migrate_gateway_to_asset(apps, schema_editor):
asset_model = apps.get_model('assets', 'Asset')
protocol_model = apps.get_model('assets', 'Protocol')
gateways = gateway_model.objects.all()
org_ids = gateways.order_by('org_id').values_list('org_id', flat=True).distinct()
node_dict = {}
for org_id in org_ids:
org = org_model.objects.using(db_alias).filter(id=org_id).first()
node = node_model.objects.using(db_alias).filter(
org_id=org_id, value=org.name, full_value=f'/{org.name}'
).first()
node_dict[org_id] = node
for gateway in gateways:
comment = gateway.comment if gateway.comment else ''
data = {
@ -40,6 +52,8 @@ def migrate_gateway_to_asset(apps, schema_editor):
'platform': gateway_platform,
}
asset = asset_model.objects.using(db_alias).create(**data)
node = node_dict.get(str(gateway.org_id))
asset.nodes.set([node])
asset_dict[gateway.id] = asset
protocol_model.objects.using(db_alias).create(name='ssh', port=gateway.port, asset=asset)
hosts = [host_model(asset_ptr=asset) for asset in asset_dict.values()]

View File

@ -139,9 +139,9 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
return
category = request.path.strip('/').split('/')[-1].rstrip('s')
field_category = self.fields.get('category')
field_category._choices = Category.filter_choices(category)
field_category.choices = Category.filter_choices(category)
field_type = self.fields.get('type')
field_type._choices = AllTypes.filter_choices(category)
field_type.choices = AllTypes.filter_choices(category)
@classmethod
def setup_eager_loading(cls, queryset):

View File

@ -9,6 +9,7 @@ from ops.celery.decorator import (
)
from .models import UserLoginLog, OperateLog, FTPLog
from common.utils import get_log_keep_day
from django.utils.translation import gettext_lazy as _
def clean_login_log_period():
@ -32,8 +33,8 @@ def clean_ftp_log_period():
FTPLog.objects.filter(date_start__lt=expired_day).delete()
@register_as_period_task(interval=3600*24)
@shared_task
@register_as_period_task(interval=3600 * 24)
@shared_task(verbose_name=_('Clean audits log'))
def clean_audits_log_period():
clean_login_log_period()
clean_operation_log_period()

View File

@ -5,9 +5,10 @@ from celery import shared_task
from ops.celery.decorator import register_as_period_task
from django.contrib.sessions.models import Session
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
@register_as_period_task(interval=3600*24)
@shared_task
@register_as_period_task(interval=3600 * 24)
@shared_task(verbose_name=_('Clean expired session'))
def clean_django_sessions():
Session.objects.filter(expire_date__lt=timezone.now()).delete()

View File

@ -66,7 +66,7 @@ class LabeledChoiceField(ChoiceField):
def to_internal_value(self, data):
if isinstance(data, dict):
return data.get("value")
data = data.get("value")
return super(LabeledChoiceField, self).to_internal_value(data)

View File

@ -8,12 +8,12 @@ from common.sdk.sms.endpoint import SMS
from common.exceptions import JMSException
from common.utils.random import random_string
from common.utils import get_logger
from django.utils.translation import gettext_lazy as _
logger = get_logger(__file__)
@shared_task
@shared_task(verbose_name=_('Send email'))
def send_async(sender):
sender.gen_and_send()

View File

@ -193,7 +193,7 @@ class PlaybookFileBrowserAPIView(APIView):
"id": os.path.join(relative_path, d) if not os.path.join(relative_path, d).startswith(
'.') else d,
"isParent": True,
"open": False,
"open": True,
"pId": relative_path if not relative_path.startswith('.') else 'root',
"temp": False
}

View File

@ -13,7 +13,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='playbook',
name='create_method',
field=models.CharField(choices=[('blank', 'Blank'), ('upload', 'Upload'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'),
field=models.CharField(choices=[('blank', 'Blank'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'),
),
migrations.AddField(
model_name='playbook',

View File

@ -70,9 +70,7 @@ class AssetPermissionSerializer(BulkOrgResourceModelSerializer):
actions = self.fields.get("actions")
if not actions:
return
choices = actions._choices
actions._choices = choices
actions.default = list(choices.keys())
actions.default = list(actions.choices.keys())
@classmethod
def setup_eager_loading(cls, queryset):

View File

@ -19,12 +19,13 @@ from perms.notifications import (
PermedAssetsWillExpireUserMsg,
AssetPermsWillExpireForOrgAdminMsg,
)
from django.utils.translation import gettext_lazy as _
logger = get_logger(__file__)
@register_as_period_task(interval=settings.PERM_EXPIRED_CHECK_PERIODIC)
@shared_task()
@shared_task(verbose_name=_('Check asset permission expired'))
@atomic()
@tmp_to_root_org()
def check_asset_permission_expired():
@ -36,7 +37,7 @@ def check_asset_permission_expired():
@register_as_period_task(crontab=CRONTAB_AT_AM_TEN)
@shared_task()
@shared_task(verbose_name=_('Send asset permission expired notification'))
@atomic()
@tmp_to_root_org()
def check_asset_permission_will_expired():

View File

@ -4,7 +4,6 @@ from rest_framework.exceptions import PermissionDenied
from rest_framework.decorators import action
from common.api import JMSModelViewSet
from common.api import PaginatedResponseMixin
from ..filters import RoleFilter
from ..serializers import RoleSerializer, RoleUserSerializer
from ..models import Role, SystemRole, OrgRole
@ -18,6 +17,7 @@ __all__ = [
class RoleViewSet(JMSModelViewSet):
queryset = Role.objects.all()
ordering = ('-builtin', 'scope', 'name')
serializer_classes = {
'default': RoleSerializer,
'users': RoleUserSerializer,
@ -62,8 +62,7 @@ class RoleViewSet(JMSModelViewSet):
return super().perform_update(serializer)
def get_queryset(self):
queryset = super().get_queryset() \
.annotate(permissions_amount=Count('permissions'))
queryset = super().get_queryset().annotate(permissions_amount=Count('permissions'))
return queryset
@action(methods=['GET'], detail=True)

View File

@ -15,7 +15,7 @@ class LDAPTestConfigSerializer(serializers.Serializer):
AUTH_LDAP_BIND_PASSWORD = EncryptedField(required=False, allow_blank=True)
AUTH_LDAP_SEARCH_OU = serializers.CharField()
AUTH_LDAP_SEARCH_FILTER = serializers.CharField()
AUTH_LDAP_USER_ATTR_MAP = serializers.CharField()
AUTH_LDAP_USER_ATTR_MAP = serializers.JSONField()
AUTH_LDAP_START_TLS = serializers.BooleanField(required=False)
AUTH_LDAP = serializers.BooleanField(required=False)

View File

@ -50,17 +50,18 @@ class DeployAppletHostManager:
host_id = str(self.deployment.host.id)
if not site_url:
site_url = "http://localhost:8080"
if not download_host:
download_host = site_url
options = self.deployment.host.deploy_options
site_url = site_url.rstrip("/")
core_host = options.get("CORE_HOST", site_url)
core_host = core_host.rstrip("/")
if not download_host:
download_host = core_host
download_host = download_host.rstrip("/")
def handler(plays):
for play in plays:
play["vars"].update(options)
play["vars"]["APPLET_DOWNLOAD_HOST"] = download_host
play["vars"]["CORE_HOST"] = site_url
play["vars"]["CORE_HOST"] = core_host
play["vars"]["BOOTSTRAP_TOKEN"] = bootstrap_token
play["vars"]["HOST_ID"] = host_id
play["vars"]["HOST_NAME"] = self.deployment.host.name

View File

@ -1,3 +1,4 @@
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
@ -27,6 +28,8 @@ class DeployOptionsSerializer(serializers.Serializer):
(1, _("Disabled")),
(0, _("Enabled")),
)
CORE_HOST = serializers.CharField(default=settings.SITE_URL, label=_('API Server'), max_length=1024)
RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing"))
RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024)
RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode'))

View File

@ -21,13 +21,14 @@ from .models import (
Status, Session, Command, Task, AppletHostDeployment
)
from .utils import find_session_replay_local
from django.utils.translation import gettext_lazy as _
CACHE_REFRESH_INTERVAL = 10
RUNNING = False
logger = get_task_logger(__name__)
@shared_task
@shared_task(verbose_name=_('Periodic delete terminal status'))
@register_as_period_task(interval=3600)
@after_app_ready_start
@after_app_shutdown_clean_periodic
@ -36,7 +37,7 @@ def delete_terminal_status_period():
Status.objects.filter(date_created__lt=yesterday).delete()
@shared_task
@shared_task(verbose_name=_('Clean orphan session'))
@register_as_period_task(interval=600)
@after_app_ready_start
@after_app_shutdown_clean_periodic
@ -55,7 +56,7 @@ def clean_orphan_session():
session.save()
@shared_task
@shared_task(verbose_name=_('Periodic clean expired session'))
@register_as_period_task(interval=3600 * 24)
@after_app_ready_start
@after_app_shutdown_clean_periodic
@ -81,7 +82,7 @@ def clean_expired_session_period():
logger.info("Clean session replay done")
@shared_task
@shared_task(verbose_name=_('Upload session replay to external storage'))
def upload_session_replay_to_external_storage(session_id):
logger.info(f'Start upload session to external storage: {session_id}')
session = Session.objects.filter(id=session_id).first()
@ -108,14 +109,14 @@ def upload_session_replay_to_external_storage(session_id):
return
@shared_task
@shared_task(verbose_name=_('Run applet host deployment'))
def run_applet_host_deployment(did):
with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did)
deployment.start()
@shared_task
@shared_task(verbose_name=_('Install applet'))
def run_applet_host_deployment_install_applet(did, applet_id):
with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did)

View File

@ -39,9 +39,9 @@ class TicketSerializer(OrgResourceModelSerializerMixin):
tp = self.fields.get('type')
if not tp:
return
choices = tp._choices
choices = tp.choices
choices.pop(TicketType.general, None)
tp._choices = choices
tp.choices = choices
@classmethod
def setup_eager_loading(cls, queryset):

View File

@ -36,7 +36,7 @@ class UserFilter(BaseFilterSet):
if not role:
return queryset.none()
queryset = queryset.prefetch_related('role_bindings') \
.filter(role_bindings__role_id=role.id) \
.filter(role_bindings__role_id=role.id, role_bindings__role__scope='system') \
.distinct()
return queryset
@ -45,6 +45,6 @@ class UserFilter(BaseFilterSet):
if not role:
return queryset.none()
queryset = queryset.prefetch_related('role_bindings') \
.filter(role_bindings__role_id=role.id) \
.filter(role_bindings__role_id=role.id, role_bindings__role__scope='org') \
.distinct()
return queryset

View File

@ -16,12 +16,12 @@ from .models import User
from users.notifications import UserExpirationReminderMsg
from settings.utils import LDAPServerUtil, LDAPImportUtil
from common.const.crontab import CRONTAB_AT_AM_TEN, CRONTAB_AT_PM_TWO
from django.utils.translation import gettext_lazy as _
logger = get_logger(__file__)
@shared_task
@shared_task(verbose_name=_('Check password expired'))
def check_password_expired():
users = User.get_nature_users().filter(source=User.Source.local)
for user in users:
@ -35,7 +35,7 @@ def check_password_expired():
PasswordExpirationReminderMsg(user).publish_async()
@shared_task
@shared_task(verbose_name=_('Periodic check password expired'))
@after_app_ready_start
def check_password_expired_periodic():
tasks = {
@ -49,11 +49,11 @@ def check_password_expired_periodic():
create_or_update_celery_periodic_tasks(tasks)
@shared_task
@shared_task(verbose_name=_('Check user expired'))
def check_user_expired():
date_expired_lt = timezone.now() + timezone.timedelta(days=User.DATE_EXPIRED_WARNING_DAYS)
users = User.get_nature_users()\
.filter(source=User.Source.local)\
users = User.get_nature_users() \
.filter(source=User.Source.local) \
.filter(date_expired__lt=date_expired_lt)
for user in users:
@ -66,7 +66,7 @@ def check_user_expired():
UserExpirationReminderMsg(user).publish_async()
@shared_task
@shared_task(verbose_name=_('Periodic check user expired'))
@after_app_ready_start
def check_user_expired_periodic():
tasks = {
@ -80,7 +80,7 @@ def check_user_expired_periodic():
create_or_update_celery_periodic_tasks(tasks)
@shared_task
@shared_task(verbose_name=_('Import ldap user'))
def import_ldap_user():
logger.info("Start import ldap user task")
util_server = LDAPServerUtil()
@ -101,7 +101,7 @@ def import_ldap_user():
logger.info('Imported {} users successfully'.format(len(users)))
@shared_task
@shared_task(verbose_name=_('Periodic import ldap user'))
@after_app_ready_start
def import_ldap_user_periodic():
if not settings.AUTH_LDAP: