Merge pull request #11878 from gavindsouza/validate-backup-before-restore

feat: Validate sql file before restoring site
This commit is contained in:
mergify[bot] 2020-11-09 12:01:33 +00:00 committed by GitHub
commit c0aae3e28e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 4 deletions

View file

@ -103,11 +103,11 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
@click.option('--install-app', multiple=True, help='Install app after installation')
@click.option('--with-public-files', help='Restores the public files of the site, given path to its tar file')
@click.option('--with-private-files', help='Restores the private files of the site, given path to its tar file')
@click.option('--force', is_flag=True, default=False, help='Ignore the site downgrade warning, if applicable')
@click.option('--force', is_flag=True, default=False, help='Ignore the validations and downgrade warnings. This action is not recommended')
@pass_context
def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_password=None, db_name=None, verbose=None, install_app=None, admin_password=None, force=None, with_public_files=None, with_private_files=None):
"Restore site database from an sql file"
from frappe.installer import extract_sql_gzip, extract_files, is_downgrade
from frappe.installer import extract_sql_gzip, extract_files, is_downgrade, validate_database_sql
force = context.force or force
# Extract the gzip file if user has passed *.sql.gz file instead of *.sql file
@ -127,6 +127,7 @@ def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_pas
else:
decompressed_file_name = sql_file_path
validate_database_sql(decompressed_file_name, _raise=force)
site = get_site(context)
frappe.init(site=site)
@ -305,15 +306,16 @@ def migrate_to(context, frappe_provider):
@click.command('run-patch')
@click.argument('module')
@click.option('--force', is_flag=True)
@pass_context
def run_patch(context, module):
def run_patch(context, module, force):
"Run a particular patch"
import frappe.modules.patch_handler
for site in context.sites:
frappe.init(site=site)
try:
frappe.connect()
frappe.modules.patch_handler.run_single(module, force=context.force)
frappe.modules.patch_handler.run_single(module, force=force or context.force)
finally:
frappe.destroy()
if not context.sites:

View file

@ -110,3 +110,4 @@ class DocumentAlreadyRestored(Exception): pass
class InvalidAuthorizationHeader(CSRFTokenError): pass
class InvalidAuthorizationPrefix(CSRFTokenError): pass
class InvalidAuthorizationToken(CSRFTokenError): pass
class InvalidDatabaseFile(ValidationError): pass

View file

@ -406,3 +406,30 @@ def is_downgrade(sql_file_path, verbose=False):
print("Your site will be downgraded from Frappe {0} to {1}".format(current_version, backup_version))
return downgrade
def validate_database_sql(path, _raise=True):
"""Check if file has contents and if DefaultValue table exists
Args:
path (str): Path of the decompressed SQL file
_raise (bool, optional): Raise exception if invalid file. Defaults to True.
"""
_raise = False
error_message = ""
if not os.path.getsize(path):
error_message = f"{path} is an empty file!"
_raise = True
if not _raise:
with open(path, "r") as f:
for line in f:
if 'tabDefaultValue' in line:
error_message = "Table `tabDefaultValue` not found in file."
_raise = True
if error_message and _raise:
import click
click.secho(error_message, fg="red")
raise frappe.InvalidDatabaseFile