Browse Source

Nov 29 : [UPDT] Updated 'auto_database_backup'

pull/232/head
AjmalCybro 2 years ago
parent
commit
ccc41d634b
  1. 4
      auto_database_backup/__manifest__.py
  2. 8
      auto_database_backup/controllers/main.py
  3. 5
      auto_database_backup/doc/RELEASE_NOTES.md
  4. 121
      auto_database_backup/models/db_backup_configure.py
  5. BIN
      auto_database_backup/static/description/assets/screenshots/drive1.png
  6. BIN
      auto_database_backup/static/description/assets/screenshots/drive2.png
  7. BIN
      auto_database_backup/static/description/assets/screenshots/drive3.png
  8. BIN
      auto_database_backup/static/description/assets/screenshots/drive4.png
  9. BIN
      auto_database_backup/static/description/assets/screenshots/drive5.png
  10. BIN
      auto_database_backup/static/description/assets/screenshots/drive6.png
  11. BIN
      auto_database_backup/static/description/assets/screenshots/drive7.png
  12. BIN
      auto_database_backup/static/description/assets/screenshots/drive8.png
  13. BIN
      auto_database_backup/static/description/assets/screenshots/drive9.png
  14. 61
      auto_database_backup/static/description/index.html
  15. 37
      auto_database_backup/views/db_backup_configure_views.xml

4
auto_database_backup/__manifest__.py

@ -22,7 +22,7 @@
{
'name': "Automatic Database Backup To Local Server, Remote Server, Google Drive And Dropbox",
'version': '15.0.3.0.1',
'version': '15.0.3.1.1',
'summary': """Generate automatic backup of databases and store to local, google drive, dropbox, onedrive or remote server""",
'description': """This module has been developed for creating database backups automatically
and store it to the different locations.""",
@ -31,7 +31,7 @@
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'category': 'Tools',
'depends': ['base', 'mail', 'google_drive'],
'depends': ['base', 'mail'],
'data': [
'security/ir.model.access.csv',
'data/data.xml',

8
auto_database_backup/controllers/main.py

@ -33,3 +33,11 @@ class OnedriveAuth(http.Controller):
backup_config.get_onedrive_tokens(kw.get('code'))
url_return = state.get('url_return')
return request.redirect(url_return)
@http.route('/google_drive/authentication', type='http', auth="public")
def gdrive_oauth2callback(self, **kw):
state = json.loads(kw['state'])
backup_config = request.env['db.backup.configure'].sudo().browse(state.get('backup_config_id'))
backup_config.get_gdrive_tokens(kw.get('code'))
url_return = state.get('url_return')
return request.redirect(url_return)

5
auto_database_backup/doc/RELEASE_NOTES.md

@ -15,3 +15,8 @@
#### ADD
- Onedrive integration added. Backup can be stored in to onedrive.
#### 15.11.2022
#### Version 15.0.3.1.1
#### ADD
- Google Drive authentication updated.

121
auto_database_backup/models/db_backup_configure.py

@ -45,6 +45,9 @@ _logger = logging.getLogger(__name__)
ONEDRIVE_SCOPE = ['offline_access openid Files.ReadWrite.All']
MICROSOFT_GRAPH_END_POINT = "https://graph.microsoft.com"
GOOGLE_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth'
GOOGLE_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
GOOGLE_API_BASE_URL = 'https://www.googleapis.com'
class AutoDatabaseBackup(models.Model):
@ -100,6 +103,118 @@ class AutoDatabaseBackup(models.Model):
onedrive_folder_id = fields.Char(string='Folder ID')
is_onedrive_token_generated = fields.Boolean(string='onedrive Tokens Generated',
compute='_compute_is_onedrive_token_generated', copy=False)
gdrive_refresh_token = fields.Char(string='Google drive Refresh Token', copy=False)
gdrive_access_token = fields.Char(string='Google Drive Access Token', copy=False)
is_google_drive_token_generated = fields.Boolean(string='Google drive Token Generated',
compute='_compute_is_google_drive_token_generated', copy=False)
gdrive_client_id = fields.Char(string='Google Drive Client ID', copy=False)
gdrive_client_secret = fields.Char(string='Google Drive Client Secret', copy=False)
gdrive_token_validity = fields.Datetime(string='Google Drive Token Validity', copy=False)
gdrive_redirect_uri = fields.Char(string='Google Drive Redirect URI', compute='_compute_redirect_uri')
onedrive_redirect_uri = fields.Char(string='Onedrive Redirect URI', compute='_compute_redirect_uri')
@api.depends('backup_destination')
def _compute_redirect_uri(self):
for rec in self:
base_url = request.env['ir.config_parameter'].get_param('web.base.url')
rec.onedrive_redirect_uri = base_url + '/onedrive/authentication'
rec.gdrive_redirect_uri = base_url + '/google_drive/authentication'
@api.depends('gdrive_access_token', 'gdrive_refresh_token')
def _compute_is_google_drive_token_generated(self):
"""
Set True if the Google Drive refresh token is generated
"""
for rec in self:
rec.is_google_drive_token_generated = bool(rec.gdrive_access_token) and bool(rec.gdrive_refresh_token)
def action_get_gdrive_auth_code(self):
"""
Generate ogoogle drive authorization code
"""
action = self.env["ir.actions.act_window"].sudo()._for_xml_id("auto_database_backup.action_db_backup_configure")
base_url = request.env['ir.config_parameter'].get_param('web.base.url')
url_return = base_url + '/web#id=%d&action=%d&view_type=form&model=%s' % (self.id, action['id'], 'db.backup.configure')
state = {
'backup_config_id': self.id,
'url_return': url_return
}
encoded_params = urls.url_encode({
'response_type': 'code',
'client_id': self.gdrive_client_id,
'scope': 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file',
'redirect_uri': base_url + '/google_drive/authentication',
'access_type': 'offline',
'state': json.dumps(state),
'approval_prompt': 'force',
})
auth_url = "%s?%s" % (GOOGLE_AUTH_ENDPOINT, encoded_params)
return {
'type': 'ir.actions.act_url',
'target': 'self',
'url': auth_url,
}
def generate_gdrive_refresh_token(self):
"""
generate google drive access token from refresh token if expired
"""
headers = {"content-type": "application/x-www-form-urlencoded"}
data = {
'refresh_token': self.gdrive_refresh_token,
'client_id': self.gdrive_client_id,
'client_secret': self.gdrive_client_secret,
'grant_type': 'refresh_token',
}
try:
res = requests.post(GOOGLE_TOKEN_ENDPOINT, data=data, headers=headers)
res.raise_for_status()
response = res.content and res.json() or {}
if response:
expires_in = response.get('expires_in')
self.write({
'gdrive_access_token': response.get('access_token'),
'gdrive_token_validity': fields.Datetime.now() + timedelta(seconds=expires_in) if expires_in else False,
})
except requests.HTTPError as error:
error_key = error.response.json().get("error", "nc")
error_msg = _(
"An error occurred while generating the token. Your authorization code may be invalid or has already expired [%s]. "
"You should check your Client ID and secret on the Google APIs plateform or try to stop and restart your calendar synchronisation.",
error_key)
raise UserError(error_msg)
def get_gdrive_tokens(self, authorize_code):
"""
Generate onedrive tokens from authorization code
"""
base_url = request.env['ir.config_parameter'].get_param('web.base.url')
headers = {"content-type": "application/x-www-form-urlencoded"}
data = {
'code': authorize_code,
'client_id': self.gdrive_client_id,
'client_secret': self.gdrive_client_secret,
'grant_type': 'authorization_code',
'redirect_uri': base_url + '/google_drive/authentication'
}
try:
res = requests.post(GOOGLE_TOKEN_ENDPOINT, params=data,
headers=headers)
res.raise_for_status()
response = res.content and res.json() or {}
if response:
expires_in = response.get('expires_in')
self.write({
'gdrive_access_token': response.get('access_token'),
'gdrive_refresh_token': response.get('refresh_token'),
'gdrive_token_validity': fields.Datetime.now() + timedelta(
seconds=expires_in) if expires_in else False,
})
except requests.HTTPError:
error_msg = _("Something went wrong during your token generation. Maybe your Authorization Code is invalid")
raise UserError(error_msg)
@api.depends('onedrive_access_token', 'onedrive_refresh_token')
def _compute_is_onedrive_token_generated(self):
@ -382,12 +497,14 @@ class AutoDatabaseBackup(models.Model):
client.close()
# Google Drive backup
elif rec.backup_destination == 'google_drive':
if rec.gdrive_token_validity <= fields.Datetime.now():
rec.generate_gdrive_refresh_token()
temp = tempfile.NamedTemporaryFile(suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, rec.backup_format)
try:
access_token = self.env['google.drive.config'].sudo().get_access_token()
headers = {"Authorization": "Bearer %s" % access_token}
# access_token = self.env['google.drive.config'].sudo().get_access_token()
headers = {"Authorization": "Bearer %s" % rec.gdrive_access_token}
para = {
"name": backup_filename,
"parents": [rec.google_drive_folderid],

BIN
auto_database_backup/static/description/assets/screenshots/drive1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
auto_database_backup/static/description/assets/screenshots/drive9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

61
auto_database_backup/static/description/index.html

@ -305,17 +305,68 @@
Store Backup to Google Drive</h4>
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Select backup destination as Google Drive. Enter google drive folder ID.
Enable and configure Google Drive option from general settings.
you'll need to create a new
Google API project and enabling the Google Drive API, Go to the <a href="https://console.developers.google.com/"
target="_blank">Google API Console</a> and log into your
account.
While creating the project, for the Redirect URI restrictions, copy your Odoo database URI followed by
/google_drive/authentication. Example:
</p>
<img src="assets/screenshots/backup7.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/drive1.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Setup refresh token from general settings
Enable Google Drive API
</p>
<img src="assets/screenshots/backup8.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/drive2.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<img src="assets/screenshots/drive3.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Create Credentials, Follow
the steps, select Website application for the Application Type.
</p>
<img src="assets/screenshots/drive4.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Under the Authorized
JavaScript Origins section, click + Add URI and type your company’s Odoo URL address.
Under the Authorized redirect URIs section, click + Add URI and type your company’s Odoo URL address followed
by <i>/google_drive/authentication</i>.
After all the steps are completed, A client ID and Secret will be given, copy the credentials
</p>
<img src="assets/screenshots/drive5.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Configure Backup, Copy
Client ID and Client Secret from Google Drive API Credentials page into their respective fields.
</p>
<img src="assets/screenshots/drive6.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Setup Tokens, it will be
redirected to an authorization page.
</p>
<img src="assets/screenshots/drive7.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<img src="assets/screenshots/drive8.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Reset the token if
required.
</p>
<img src="assets/screenshots/drive9.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
</div>

37
auto_database_backup/views/db_backup_configure_views.xml

@ -37,7 +37,7 @@
</group>
<group>
<field name="backup_destination" required="1"/>
<div class="text-muted" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')]}">Enable and configure Google Drive option from General Settings</div>
<!-- <div class="text-muted" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')]}">Enable and configure Google Drive option from General Settings</div>-->
<field name="backup_path" attrs="{'invisible': [('backup_destination', '!=', 'local')], 'required': [('backup_destination', '=', 'local')]}"/>
<field name="ftp_host" attrs="{'invisible': [('backup_destination', '!=', 'ftp')], 'required': [('backup_destination', '=', 'ftp')]}"/>
<field name="ftp_port" attrs="{'invisible': [('backup_destination', '!=', 'ftp')], 'required': [('backup_destination', '=', 'ftp')]}"/>
@ -49,6 +49,12 @@
<field name="sftp_user" attrs="{'invisible': [('backup_destination', '!=', 'sftp')], 'required': [('backup_destination', '=', 'sftp')]}"/>
<field name="sftp_password" attrs="{'invisible': [('backup_destination', '!=', 'sftp')], 'required': [('backup_destination', '=', 'sftp')]}" password="True"/>
<field name="sftp_path" attrs="{'invisible': [('backup_destination', '!=', 'sftp')], 'required': [('backup_destination', '=', 'sftp')]}"/>
<field name="gdrive_client_id" string="Client ID" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')], 'required': [('backup_destination', '=', 'google_drive')]}"/>
<field name="gdrive_client_secret" string="Client Secret" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')], 'required': [('backup_destination', '=', 'google_drive')]}" password="True"/>
<field name="gdrive_redirect_uri" string="Redirect URI" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')]}"/>
<field name="gdrive_access_token" password="True" invisible="1"/>
<field name="gdrive_refresh_token" password="True" invisible="1"/>
<field name="gdrive_token_validity" invisible="1"/>
<field name="google_drive_folderid" attrs="{'invisible': [('backup_destination', '!=', 'google_drive')], 'required': [('backup_destination', '=', 'google_drive')]}"/>
<field name="dropbox_client_id" string="App Key" attrs="{'invisible': [('backup_destination', '!=', 'dropbox')], 'required': [('backup_destination', '=', 'dropbox')]}" password="True"/>
<field name="dropbox_client_secret" string="App Secret" attrs="{'invisible': [('backup_destination', '!=', 'dropbox')], 'required': [('backup_destination', '=', 'dropbox')]}" password="True"/>
@ -59,6 +65,7 @@
<field name="onedrive_refresh_token" string="Refresh Token" invisible="1" password="True"/>
<field name="onedrive_token_validity" string="Token Validity" invisible="1"/>
<field name="is_onedrive_token_generated" invisible="1"/>
<field name="is_google_drive_token_generated" invisible="1"/>
<div>
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'dropbox'), ('is_dropbox_token_generated', '=', False)]}">
<i class="text-success fa fa-check"></i>
@ -87,6 +94,34 @@
</button>
</div>
</div>
<div attrs="{'invisible': [('backup_destination', '!=', 'google_drive')]}">
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'google_drive'), ('is_google_drive_token_generated', '=', False)]}">
<i class="text-success fa fa-check"></i>
Refresh token set
</div>
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'google_drive'), ('is_google_drive_token_generated', '=', True)]}">
<i class="fa fa-exclamation-triangle text-warning"></i>
No refresh token set
</div>
</div>
<div attrs="{'invisible': [('backup_destination', '!=', 'google_drive')]}">
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'google_drive'), ('is_google_drive_token_generated', '=', True)]}">
<button class="btn btn-link"
name="action_get_gdrive_auth_code"
type="object">
<i class="fa fa-arrow-right"></i>
Setup Token
</button>
</div>
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'google_drive'), ('is_google_drive_token_generated', '=', False)]}">
<button class="btn btn-link"
name="action_get_gdrive_auth_code"
type="object">
<i class="fa fa-arrow-right"></i>
Reset Token
</button>
</div>
</div>
<div>
<div attrs="{'invisible': ['|', ('backup_destination', '!=', 'onedrive'), ('is_onedrive_token_generated', '=', True)]}">
<button class="btn btn-link"

Loading…
Cancel
Save