diff --git a/app_auto_backup/__init__.py b/app_auto_backup/__init__.py index cde864ba..aa4d0fd6 100644 --- a/app_auto_backup/__init__.py +++ b/app_auto_backup/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- +from . import controllers from . import models diff --git a/app_auto_backup/__manifest__.py b/app_auto_backup/__manifest__.py index 4d9977dc..67ff252f 100644 --- a/app_auto_backup/__manifest__.py +++ b/app_auto_backup/__manifest__.py @@ -4,7 +4,7 @@ { 'name': "Database auto backup,数据库自动备份", - 'version': '16.24.03.12', + 'version': '16.24.05.22', 'summary': 'Automated backups, optimized from auto_backup of Yenthe Van Ginneken', @@ -31,7 +31,8 @@ # any module necessary for this one to work correctly 'depends': [ - 'base' + 'base', + 'app_odoo_customize' ], 'external_dependencies': { 'python': ['paramiko'], @@ -43,5 +44,6 @@ 'security/ir.model.access.csv', 'views/backup_view.xml', 'data/backup_data.xml', + 'views/db_backup_details.xml', ], } diff --git a/app_auto_backup/controllers/__init__.py b/app_auto_backup/controllers/__init__.py new file mode 100644 index 00000000..65a8c120 --- /dev/null +++ b/app_auto_backup/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import main diff --git a/app_auto_backup/controllers/main.py b/app_auto_backup/controllers/main.py new file mode 100644 index 00000000..872e9d50 --- /dev/null +++ b/app_auto_backup/controllers/main.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +import logging +import os + +from odoo import http, _ +from odoo.http import request, content_disposition +from odoo.exceptions import AccessError, UserError + +_logger = logging.getLogger(__name__) + + +class AppAutoBackup(http.Controller): + + @http.route("/download/backupfile/", type="http", auth="user") + def download_backupfile(self, file_path, **kw): + if os.path.exists(file_path): + try: + with open(file_path, 'rb') as file: + file_content = file.read() + file_name = file_path.split("/")[-1] + headers = [ + ('Content-Type', 'application/octet-stream'), + ('Content-Disposition', content_disposition(file_name)), + ] + return request.make_response(file_content, headers) + except Exception as e: + raise UserError(e) + else: + return 'File not found' \ No newline at end of file diff --git a/app_auto_backup/models/__init__.py b/app_auto_backup/models/__init__.py index b4746b69..4d57b241 100644 --- a/app_auto_backup/models/__init__.py +++ b/app_auto_backup/models/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import db_backup +from . import db_backup_details diff --git a/app_auto_backup/models/db_backup.py b/app_auto_backup/models/db_backup.py index b98c3871..e9610330 100644 --- a/app_auto_backup/models/db_backup.py +++ b/app_auto_backup/models/db_backup.py @@ -35,7 +35,7 @@ class DbBackup(models.Model): port = fields.Char('Port', required=True, default=8069) name = fields.Char('Database', required=True, help='Database you want to schedule backups for', default=_get_db_name) - folder = fields.Char('Backup Directory', help='Absolute path for storing the backups', required='True', + folder = fields.Char('Backup Directory', help='Absolute path for storing the backups', required=True, default='/usr/lib/python3/dist-packages/odoo/backups') backup_type = fields.Selection([('zip', 'Zip'), ('dump', 'Dump')], 'Backup Type', required=True, default='zip') autoremove = fields.Boolean('Auto. Remove Backups', @@ -73,6 +73,7 @@ class DbBackup(models.Model): email_to_notify = fields.Char('E-mail to notify', help='Fill in the e-mail where you want to be notified that the backup failed on ' 'the FTP.') + backup_details_ids = fields.One2many('db.backup.details', 'db_backup_id', 'Backup Details') def test_sftp_connection(self, context=None): self.ensure_one() @@ -136,11 +137,17 @@ class DbBackup(models.Model): fp = open(file_path, 'wb') self._take_dump(rec.name, fp, 'db.backup', rec.backup_type) fp.close() + rec.backup_details_ids.create({ + 'name': bkp_file, + 'file_path': file_path, + 'url': '/download/backupfile/%s' % file_path, + 'db_backup_id': rec.id, + }) except Exception as error: - _logger.debug( + _logger.warning( "Couldn't backup database %s. Bad database administrator password for server running at " "http://%s:%s" % (rec.name, rec.host, rec.port)) - _logger.debug("Exact error from the exception: %s", str(error)) + _logger.warning("Exact error from the exception: %s", str(error)) continue # Check if user wants to write to SFTP or not. @@ -262,7 +269,11 @@ class DbBackup(models.Model): # Only delete files (which are .dump and .zip), no directories. if os.path.isfile(fullpath) and (".dump" in f or '.zip' in f): _logger.info("Delete local out-of-date file: %s", fullpath) - os.remove(fullpath) + backup_details_id = self.env['db.backup.details'].search([('file_path', '=', fullpath)]) + if backup_details_id: + backup_details_id.unlink() + else: + os.remove(fullpath) # This is more or less the same as the default Odoo function at # https://github.com/odoo/odoo/blob/e649200ab44718b8faefc11c2f8a9d11f2db7753/odoo/service/db.py#L209 diff --git a/app_auto_backup/models/db_backup_details.py b/app_auto_backup/models/db_backup_details.py new file mode 100644 index 00000000..1ed334c6 --- /dev/null +++ b/app_auto_backup/models/db_backup_details.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +import os + +from odoo import api, fields, models, _ +from odoo.exceptions import AccessError, UserError + + +class DbBackupDetails(models.Model): + _name = 'db.backup.details' + _description = 'Database Backup Details' + + name = fields.Char(string='Name') + file_path = fields.Char(string="File Path") + url = fields.Char(string='URL') + db_backup_id = fields.Many2one('db.backup', 'Database Backup') + + def action_download_file(self): + self.ensure_one() + if not self.file_path or not self.url: + raise UserError(_("File Path or URL not found.")) + else: + return { + 'type': 'ir.actions.act_url', + 'url': self.url, + 'target': 'new', + } + + def unlink(self): + if self.file_path: + if os.path.exists(self.file_path): + os.remove(self.file_path) + return super(DbBackupDetails, self).unlink() + + def action_remove_file(self): + self.ensure_one() + self.unlink() diff --git a/app_auto_backup/security/ir.model.access.csv b/app_auto_backup/security/ir.model.access.csv index 093a80b8..6199afa0 100644 --- a/app_auto_backup/security/ir.model.access.csv +++ b/app_auto_backup/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink admin_access, db_backup admin access,model_db_backup,base.group_no_one,1,1,1,1 admin_security_rule, Model db_backup admin access,model_db_backup,app_auto_backup.group_manager,1,1,1,1 +admin_db_backup_details, Model db_backup_details admin access,model_db_backup_details,app_auto_backup.group_manager,1,1,1,1 diff --git a/app_auto_backup/views/backup_view.xml b/app_auto_backup/views/backup_view.xml index 368ba6a5..fedcc870 100644 --- a/app_auto_backup/views/backup_view.xml +++ b/app_auto_backup/views/backup_view.xml @@ -8,76 +8,76 @@
-
- - - - - - - - - - - - - - - -
- Warning: + + + + + + + + + + + + + + + +
+ Warning: Use SFTP with caution! This writes files to external servers under the path you specify. -
- - - - - - - - - - -
+ + + + + + + +