mirror of https://github.com/jumpserver/jumpserver
parent
c21fcacf70
commit
0a9726d845
|
@ -71,8 +71,22 @@ class AssetAccountHandler(BaseAccountHandler):
|
||||||
)
|
)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handler_secret(data, section):
|
||||||
|
for account_data in data:
|
||||||
|
secret = account_data.get('secret')
|
||||||
|
if not secret:
|
||||||
|
continue
|
||||||
|
length = len(secret)
|
||||||
|
index = length // 2
|
||||||
|
if section == "front":
|
||||||
|
secret = secret[:index] + '*' * (length - index)
|
||||||
|
elif section == "back":
|
||||||
|
secret = '*' * (length - index) + secret[index:]
|
||||||
|
account_data['secret'] = secret
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_data_map(cls, accounts):
|
def create_data_map(cls, accounts, section):
|
||||||
data_map = defaultdict(list)
|
data_map = defaultdict(list)
|
||||||
|
|
||||||
if not accounts.exists():
|
if not accounts.exists():
|
||||||
|
@ -92,6 +106,7 @@ class AssetAccountHandler(BaseAccountHandler):
|
||||||
for tp, _accounts in account_type_map.items():
|
for tp, _accounts in account_type_map.items():
|
||||||
sheet_name = type_dict.get(tp, tp)
|
sheet_name = type_dict.get(tp, tp)
|
||||||
data = AccountSecretSerializer(_accounts, many=True).data
|
data = AccountSecretSerializer(_accounts, many=True).data
|
||||||
|
cls.handler_secret(data, section)
|
||||||
data_map.update(cls.add_rows(data, header_fields, sheet_name))
|
data_map.update(cls.add_rows(data, header_fields, sheet_name))
|
||||||
|
|
||||||
print('\n\033[33m- 共备份 {} 条账号\033[0m'.format(accounts.count()))
|
print('\n\033[33m- 共备份 {} 条账号\033[0m'.format(accounts.count()))
|
||||||
|
@ -104,7 +119,7 @@ class AccountBackupHandler:
|
||||||
self.plan_name = self.execution.plan.name
|
self.plan_name = self.execution.plan.name
|
||||||
self.is_frozen = False # 任务状态冻结标志
|
self.is_frozen = False # 任务状态冻结标志
|
||||||
|
|
||||||
def create_excel(self):
|
def create_excel(self, section='complete'):
|
||||||
print(
|
print(
|
||||||
'\n'
|
'\n'
|
||||||
'\033[32m>>> 正在生成资产或应用相关备份信息文件\033[0m'
|
'\033[32m>>> 正在生成资产或应用相关备份信息文件\033[0m'
|
||||||
|
@ -114,7 +129,7 @@ class AccountBackupHandler:
|
||||||
time_start = time.time()
|
time_start = time.time()
|
||||||
files = []
|
files = []
|
||||||
accounts = self.execution.backup_accounts
|
accounts = self.execution.backup_accounts
|
||||||
data_map = AssetAccountHandler.create_data_map(accounts)
|
data_map = AssetAccountHandler.create_data_map(accounts, section)
|
||||||
if not data_map:
|
if not data_map:
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
@ -160,7 +175,8 @@ class AccountBackupHandler:
|
||||||
self.execution.save()
|
self.execution.save()
|
||||||
print('已完成对任务状态的更新')
|
print('已完成对任务状态的更新')
|
||||||
|
|
||||||
def step_finished(self, is_success):
|
@staticmethod
|
||||||
|
def step_finished(is_success):
|
||||||
if is_success:
|
if is_success:
|
||||||
print('任务执行成功')
|
print('任务执行成功')
|
||||||
else:
|
else:
|
||||||
|
@ -170,14 +186,22 @@ class AccountBackupHandler:
|
||||||
is_success = False
|
is_success = False
|
||||||
error = '-'
|
error = '-'
|
||||||
try:
|
try:
|
||||||
recipients = self.execution.plan_snapshot.get('recipients')
|
recipients_part_one = self.execution.snapshot.get('recipients_part_one', [])
|
||||||
if not recipients:
|
recipients_part_two = self.execution.snapshot.get('recipients_part_two', [])
|
||||||
|
if not recipients_part_one and not recipients_part_two:
|
||||||
print(
|
print(
|
||||||
'\n'
|
'\n'
|
||||||
'\033[32m>>> 该备份任务未分配收件人\033[0m'
|
'\033[32m>>> 该备份任务未分配收件人\033[0m'
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
|
if recipients_part_one and recipients_part_two:
|
||||||
|
files = self.create_excel(section='front')
|
||||||
|
self.send_backup_mail(files, recipients_part_one)
|
||||||
|
|
||||||
|
files = self.create_excel(section='back')
|
||||||
|
self.send_backup_mail(files, recipients_part_two)
|
||||||
else:
|
else:
|
||||||
|
recipients = recipients_part_one or recipients_part_two
|
||||||
files = self.create_excel()
|
files = self.create_excel()
|
||||||
self.send_backup_mail(files, recipients)
|
self.send_backup_mail(files, recipients)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Generated by Django 4.1.10 on 2023-08-03 08:28
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_recipients(apps, schema_editor):
|
||||||
|
account_backup_model = apps.get_model('accounts', 'AccountBackupAutomation')
|
||||||
|
execution_model = apps.get_model('accounts', 'AccountBackupExecution')
|
||||||
|
for account_backup in account_backup_model.objects.all():
|
||||||
|
recipients = list(account_backup.recipients.all())
|
||||||
|
if not recipients:
|
||||||
|
continue
|
||||||
|
account_backup.recipients_part_one.set(recipients)
|
||||||
|
|
||||||
|
execution_bojs = []
|
||||||
|
for execution in execution_model.objects.all():
|
||||||
|
snapshot = execution.snapshot
|
||||||
|
recipients = snapshot.pop('recipients', {})
|
||||||
|
snapshot.update({'recipients_part_one': recipients, 'recipients_part_two': {}})
|
||||||
|
execution_bojs.append(execution)
|
||||||
|
execution_model.objects.bulk_update(execution_bojs, ['snapshot'])
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('accounts', '0012_auto_20230621_1456'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='accountbackupautomation',
|
||||||
|
name='recipients_part_one',
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True, related_name='recipient_part_one_plans',
|
||||||
|
to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='accountbackupautomation',
|
||||||
|
name='recipients_part_two',
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True, related_name='recipient_part_two_plans',
|
||||||
|
to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='accountbackupexecution',
|
||||||
|
old_name='plan_snapshot',
|
||||||
|
new_name='snapshot',
|
||||||
|
),
|
||||||
|
migrations.RunPython(migrate_recipients),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='accountbackupautomation',
|
||||||
|
name='recipients',
|
||||||
|
),
|
||||||
|
|
||||||
|
]
|
|
@ -22,9 +22,13 @@ logger = get_logger(__file__)
|
||||||
|
|
||||||
class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
|
class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
|
||||||
types = models.JSONField(default=list)
|
types = models.JSONField(default=list)
|
||||||
recipients = models.ManyToManyField(
|
recipients_part_one = models.ManyToManyField(
|
||||||
'users.User', related_name='recipient_escape_route_plans', blank=True,
|
'users.User', related_name='recipient_part_one_plans', blank=True,
|
||||||
verbose_name=_("Recipient")
|
verbose_name=_("Recipient part one")
|
||||||
|
)
|
||||||
|
recipients_part_two = models.ManyToManyField(
|
||||||
|
'users.User', related_name='recipient_part_two_plans', blank=True,
|
||||||
|
verbose_name=_("Recipient part two")
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -52,9 +56,13 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
|
||||||
'org_id': self.org_id,
|
'org_id': self.org_id,
|
||||||
'created_by': self.created_by,
|
'created_by': self.created_by,
|
||||||
'types': self.types,
|
'types': self.types,
|
||||||
'recipients': {
|
'recipients_part_one': {
|
||||||
str(recipient.id): (str(recipient), bool(recipient.secret_key))
|
str(user.id): (str(user), bool(user.secret_key))
|
||||||
for recipient in self.recipients.all()
|
for user in self.recipients_part_one.all()
|
||||||
|
},
|
||||||
|
'recipients_part_two': {
|
||||||
|
str(user.id): (str(user), bool(user.secret_key))
|
||||||
|
for user in self.recipients_part_two.all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +76,7 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
hid = str(uuid.uuid4())
|
hid = str(uuid.uuid4())
|
||||||
execution = AccountBackupExecution.objects.create(
|
execution = AccountBackupExecution.objects.create(
|
||||||
id=hid, plan=self, plan_snapshot=self.to_attr_json(), trigger=trigger
|
id=hid, plan=self, snapshot=self.to_attr_json(), trigger=trigger
|
||||||
)
|
)
|
||||||
return execution.start()
|
return execution.start()
|
||||||
|
|
||||||
|
@ -85,7 +93,7 @@ class AccountBackupExecution(OrgModelMixin):
|
||||||
timedelta = models.FloatField(
|
timedelta = models.FloatField(
|
||||||
default=0.0, verbose_name=_('Time'), null=True
|
default=0.0, verbose_name=_('Time'), null=True
|
||||||
)
|
)
|
||||||
plan_snapshot = models.JSONField(
|
snapshot = models.JSONField(
|
||||||
encoder=ModelJSONFieldEncoder, default=dict,
|
encoder=ModelJSONFieldEncoder, default=dict,
|
||||||
blank=True, null=True, verbose_name=_('Account backup snapshot')
|
blank=True, null=True, verbose_name=_('Account backup snapshot')
|
||||||
)
|
)
|
||||||
|
@ -108,16 +116,9 @@ class AccountBackupExecution(OrgModelMixin):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def types(self):
|
def types(self):
|
||||||
types = self.plan_snapshot.get('types')
|
types = self.snapshot.get('types')
|
||||||
return types
|
return types
|
||||||
|
|
||||||
@property
|
|
||||||
def recipients(self):
|
|
||||||
recipients = self.plan_snapshot.get('recipients')
|
|
||||||
if not recipients:
|
|
||||||
return []
|
|
||||||
return recipients.values()
|
|
||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def backup_accounts(self):
|
def backup_accounts(self):
|
||||||
from accounts.models import Account
|
from accounts.models import Account
|
||||||
|
|
|
@ -24,7 +24,7 @@ class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSer
|
||||||
]
|
]
|
||||||
fields = read_only_fields + [
|
fields = read_only_fields + [
|
||||||
'id', 'name', 'is_periodic', 'interval', 'crontab',
|
'id', 'name', 'is_periodic', 'interval', 'crontab',
|
||||||
'comment', 'recipients', 'types'
|
'comment', 'types', 'recipients_part_one', 'recipients_part_two'
|
||||||
]
|
]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'name': {'required': True},
|
'name': {'required': True},
|
||||||
|
@ -44,7 +44,7 @@ class AccountBackupPlanExecutionSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AccountBackupExecution
|
model = AccountBackupExecution
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
'id', 'date_start', 'timedelta', 'plan_snapshot',
|
'id', 'date_start', 'timedelta', 'snapshot',
|
||||||
'trigger', 'reason', 'is_success', 'org_id', 'recipients'
|
'trigger', 'reason', 'is_success', 'org_id'
|
||||||
]
|
]
|
||||||
fields = read_only_fields + ['plan']
|
fields = read_only_fields + ['plan']
|
||||||
|
|
Loading…
Reference in New Issue