You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							235 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							235 lines
						
					
					
						
							12 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ############################################################################### | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |
| #    Author: Aslam AK (odoo@cybrosys.com) | |
| # | |
| #    You can modify it under the terms of the GNU LESSER | |
| #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | |
| # | |
| #    This program is distributed in the hope that it will be useful, | |
| #    but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |
| #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |
| # | |
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |
| #    (LGPL v3) along with this program. | |
| #    If not, see <http://www.gnu.org/licenses/>. | |
| # | |
| ############################################################################### | |
| import boto3 | |
| import dropbox | |
| import ftplib | |
| import nextcloud_client | |
| import os | |
| import paramiko | |
| import requests | |
| from datetime import datetime | |
| from odoo import fields, models | |
| 
 | |
| 
 | |
| class DatabaseRestoreManager(models.Model): | |
|     """ | |
|     Dashboard model to view all database backups | |
|     """ | |
|     _name = 'database.manager' | |
|     _description = 'Dashboard Model to View All Database Backups' | |
| 
 | |
|     def action_import_files(self): | |
|         """ | |
|         Import latest backups from the storages configured | |
|         """ | |
|         return_data = {} | |
|         backup_count = int(self.env['ir.config_parameter'].get_param( | |
|             'odoo_database_restore_manager.backup_count')) | |
|         if backup_count <= 0: | |
|             return ['error', 'Please set a backup count', 'Storages'] | |
|         if not self.env['db.backup.configure'].search([]): | |
|             return ['error', 'No Backups Found', 'auto_database_backup'] | |
|         for rec in self.env['db.backup.configure'].search([]): | |
|             if rec.backup_destination == 'dropbox': | |
|                 try: | |
|                     dbx_dict = {} | |
|                     dbx = dropbox.Dropbox(app_key=rec.dropbox_client_key, | |
|                                           app_secret=rec.dropbox_client_secret, | |
|                                           oauth2_refresh_token= | |
|                                           rec.dropbox_refresh_token) | |
|                     response = dbx.files_list_folder(path=rec.dropbox_folder) | |
|                     for files in response.entries: | |
|                         file = dbx.files_get_temporary_link( | |
|                             path=files.path_lower) | |
|                         dbx_dict[file.metadata.name] = \ | |
|                             file.link, 'Dropbox', files.client_modified | |
|                     return_data.update(dict(list( | |
|                         sorted(dbx_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'Dropbox'] | |
|             if rec.backup_destination == 'onedrive': | |
|                 try: | |
|                     onedrive_dict = {} | |
|                     if rec.onedrive_token_validity <= fields.Datetime.now(): | |
|                         rec.generate_onedrive_refresh_token() | |
|                     url = "https://graph.microsoft.com/v1.0/me/drive/items" \ | |
|                           "/%s/children?Content-Type=application/json" \ | |
|                           % rec.onedrive_folder_key | |
|                     response = requests.request("GET", url, headers={ | |
|                         'Authorization': 'Bearer "' + | |
|                                          rec.onedrive_access_token + '"'}, | |
|                                                 data={}) | |
|                     for file in response.json().get('value'): | |
|                         if list(file.keys())[0] == '@microsoft.graph.downloadUrl': | |
|                             onedrive_dict[file['name']] = file[ | |
|                                 '@microsoft.graph.downloadUrl'], 'OneDrive', \ | |
|                                 datetime.strptime( | |
|                                     file['createdDateTime'], | |
|                                     "%Y-%m-%dT%H:%M:%S.%fZ").strftime( | |
|                                     "%Y-%m-%d %H:%M:%S") | |
|                     return_data.update(dict(list( | |
|                         sorted(onedrive_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'OneDrive'] | |
|             if rec.backup_destination == 'google_drive': | |
|                 try: | |
|                     gdrive_dict = {} | |
|                     if rec.gdrive_token_validity <= fields.Datetime.now(): | |
|                         rec.generate_gdrive_refresh_token() | |
|                     response = requests.get( | |
|                         f"https://www.googleapis.com/drive/v3/files", | |
|                         headers={ | |
|                          "Authorization": "Bearer %s" | |
|                                           % rec.gdrive_access_token}, | |
|                         params={ | |
|                             "q": f"'{rec.google_drive_folder_key}' in parents", | |
|                             "fields": | |
|                                 "files(name, webContentLink, createdTime)", }) | |
|                     for file_data in response.json().get("files", []): | |
|                         gdrive_dict[file_data.get("name")] = file_data.get( | |
|                             "webContentLink"), 'Google Drive', \ | |
|                             datetime.strptime(file_data.get("createdTime"), | |
|                             "%Y-%m-%dT%H:%M:%S.%fZ").strftime( | |
|                             "%Y-%m-%d %H:%M:%S") | |
|                     return_data.update(dict(list( | |
|                         sorted(gdrive_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'Google Drive'] | |
|             if rec.backup_destination == 'local': | |
|                 try: | |
|                     local_dict = {} | |
|                     for root, dirs, files in os.walk(rec.backup_path): | |
|                         for file in files: | |
|                             file_path = os.path.join(root, file) | |
|                             create_date = datetime.fromtimestamp( | |
|                                 os.path.getctime(file_path)).strftime( | |
|                                 "%Y-%m-%d %H:%M:%S") | |
|                             local_dict[ | |
|                                 file] = file_path, 'Local Storage', create_date | |
|                     return_data.update(dict(list( | |
|                         sorted(local_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'Local'] | |
|             if rec.backup_destination == 'ftp': | |
|                 try: | |
|                     ftp_dict = {} | |
|                     ftp_server = ftplib.FTP() | |
|                     ftp_server.connect(rec.ftp_host, int(rec.ftp_port)) | |
|                     ftp_server.login(rec.ftp_user, rec.ftp_password) | |
|                     for file in ftp_server.nlst(rec.ftp_path): | |
|                         file_details = ftp_server.voidcmd("MDTM " + file) | |
|                         ftp_dict[os.path.basename( | |
|                             file)] = file, 'FTP Storage', datetime.strptime( | |
|                             file_details[4:].strip(), "%Y%m%d%H%M%S") | |
|                     ftp_server.quit() | |
|                     return_data.update(dict(list( | |
|                         sorted(ftp_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'FTP server'] | |
|             if rec.backup_destination == 'sftp': | |
|                 sftp_client = paramiko.SSHClient() | |
|                 sftp_client.set_missing_host_key_policy( | |
|                     paramiko.AutoAddPolicy()) | |
|                 try: | |
|                     sftp_dict = {} | |
|                     sftp_client.connect(hostname=rec.sftp_host, | |
|                                         username=rec.sftp_user, | |
|                                         password=rec.sftp_password, | |
|                                         port=rec.sftp_port) | |
|                     sftp_server = sftp_client.open_sftp() | |
|                     sftp_server.chdir(rec.sftp_path) | |
|                     file_list = sftp_server.listdir() | |
|                     for file_name in file_list: | |
|                         sftp_dict[file_name] = os.path.join(rec.sftp_path, | |
|                                                             file_name),\ | |
|                             'SFTP Storage', datetime.fromtimestamp( | |
|                             sftp_server.stat(file_name).st_mtime) | |
|                     sftp_server.close() | |
|                     return_data.update(dict(list( | |
|                         sorted(sftp_dict.items(), key=lambda x: x[1][2], | |
|                                reverse=True))[:backup_count])) | |
|                 except Exception as error: | |
|                     return ['error', error, 'SFTP server'] | |
|                 finally: | |
|                     sftp_client.close() | |
|             if rec.backup_destination == 'next_cloud': | |
|                 try: | |
|                     nxt_dixt = {} | |
|                     nc_access = nextcloud_client.Client(rec.domain) | |
|                     nc_access.login(rec.next_cloud_user_name, | |
|                                     rec.next_cloud_password) | |
|                     for file_name in [file.name for file in | |
|                                       nc_access.list( | |
|                                           '/' + rec.nextcloud_folder_key)]: | |
|                         link_info = nc_access.share_file_with_link( | |
|                             '/' + rec.nextcloud_folder_key + '/' + file_name, | |
|                             publicUpload=False) | |
|                         file_info = nc_access.file_info( | |
|                             '/' + rec.nextcloud_folder_key + '/' + file_name) | |
|                         input_datetime = datetime.strptime( | |
|                             file_info.attributes['{DAV:}getlastmodified'], | |
|                             "%a, %d %b %Y %H:%M:%S %Z") | |
|                         output_date_str = input_datetime.strftime( | |
|                             "%Y-%m-%d %H:%M:%S") | |
|                         nxt_dixt[ | |
|                             file_name] = link_info.get_link() + '/download', 'Nextcloud', output_date_str | |
|                     return_data.update(dict(list(sorted(nxt_dixt.items(), | |
|                                                         key=lambda x: x[1][2], | |
|                                                         reverse=True))[ | |
|                                             :backup_count])) | |
|                 except Exception as e: | |
|                     # Handle any exceptions that occur during SFTP Storage | |
|                     # backup retrieval | |
|                     return ['error', e, 'Nextcloud'] | |
|             if rec.backup_destination == 'amazon_s3': | |
|                 try: | |
|                     s3_dixt = {} | |
|                     client = boto3.client('s3', aws_access_key_id=rec.aws_access_key, | |
|                                           aws_secret_access_key=rec.aws_secret_access_key) | |
|                     region = client.get_bucket_location(Bucket=rec.bucket_file_name) | |
|                     client = boto3.client( | |
|                         's3', region_name=region['LocationConstraint'], | |
|                         aws_access_key_id=rec.aws_access_key, | |
|                         aws_secret_access_key=rec.aws_secret_access_key | |
|                     ) | |
|                     response = client.list_objects(Bucket=rec.bucket_file_name, Prefix=rec.aws_folder_name) | |
|                     for data in response['Contents']: | |
|                         if data['Size'] != 0: | |
|                              url = client.generate_presigned_url( | |
|                                  ClientMethod='get_object', | |
|                                  Params={'Bucket': rec.bucket_file_name, | |
|                                          'Key': data['Key']}, ExpiresIn=3600) | |
|                              s3_dixt[data['Key']] = url, 'AmazonS3', data['LastModified'] | |
|                     return_data.update(dict(list(sorted(s3_dixt.items(), | |
|                                                             key=lambda x: x[1][2], | |
|                                                             reverse=True))[ | |
|                                                 :backup_count])) | |
|                 except Exception as e: | |
|                     # Handle any exceptions that occur during amazon_s3 Storage | |
|                     # backup retrieval | |
|                     return ['error', e, 'Amazon S3'] | |
|         return return_data
 | |
| 
 |