-
Notifications
You must be signed in to change notification settings - Fork 1
Pull request for issue #10 #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| from . import models |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| { | ||
| 'name': 'Odoo Data Flow Core', | ||
| 'version': '18.0.1.0.0', | ||
| 'author': 'Odoo Data Flow', | ||
| 'depends': ['base'], | ||
| 'data': [ | ||
| 'security/ir.model.access.csv', | ||
| 'views/odf_connection_views.xml', | ||
| 'views/odf_flow_project_views.xml', | ||
| 'views/menus.xml', | ||
| 'data/scheduled_actions.xml', | ||
| ], | ||
| 'installable': True, | ||
| 'application': True, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <data noupdate="1"> | ||
| <record id="ir_cron_odf_flow_project_run" model="ir.cron"> | ||
| <field name="name">ODF: Run Flow Projects</field> | ||
| <field name="model_id" ref="model_odf_flow_project"/> | ||
| <field name="state">code</field> | ||
| <field name="code">model._run_projects()</field> | ||
| <field name="user_id" ref="base.user_root"/> | ||
| <field name="interval_number">1</field> | ||
| <field name="interval_type">hours</field> | ||
| <field name="numbercall">-1</field> | ||
| </record> | ||
| </data> | ||
| </odoo> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| from . import odf_connection | ||
| from . import odf_flow_project |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| from odoo import models, fields, api | ||
| import logging | ||
|
|
||
| _logger = logging.getLogger(__name__) | ||
|
|
||
| class OdfConnection(models.Model): | ||
| _name = 'odf.connection' | ||
| _description = 'Odoo Data Flow Connection' | ||
|
|
||
| name = fields.Char(required=True) | ||
| host = fields.Char(required=True) | ||
| port = fields.Integer(required=True, default=5432) | ||
| dbname = fields.Char(required=True) | ||
| user = fields.Char(required=True) | ||
| password = fields.Char(password=True) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storing passwords in plaintext in the database is a major security vulnerability. The You should use a secure method for storing credentials. Consider using Odoo's |
||
|
|
||
| def test_connection(self): | ||
| # This is a placeholder for the actual connection test logic. | ||
| # For now, it just logs a message. | ||
| _logger.info(f"Testing connection for {self.name}") | ||
| # In a real implementation, you would use a library like psycopg2 | ||
| # to attempt a connection and provide feedback to the user. | ||
| return { | ||
| 'type': 'ir.actions.client', | ||
| 'tag': 'display_notification', | ||
| 'params': { | ||
| 'title': 'Connection Test', | ||
| 'message': 'Connection test functionality is not yet implemented.', | ||
| 'sticky': False, | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| from odoo import models, fields, api | ||
| import logging | ||
| import traceback | ||
|
|
||
| _logger = logging.getLogger(__name__) | ||
|
|
||
| try: | ||
| from odoo_data_flow.workflow_runner import run_workflow | ||
| except ImportError: | ||
| run_workflow = None | ||
| _logger.warning("The 'odoo-data-flow' library is not installed. Please install it to use ODF Core features.") | ||
|
|
||
|
|
||
| class OdfFlowProject(models.Model): | ||
| _name = 'odf.flow.project' | ||
| _description = 'Odoo Data Flow Project' | ||
|
|
||
| name = fields.Char(required=True) | ||
| active = fields.Boolean(default=True) | ||
| source_connection_id = fields.Many2one('odf.connection', required=True) | ||
| destination_connection_id = fields.Many2one('odf.connection', required=True) | ||
| flow_file_path = fields.Char(string="Flow File Path", required=True) | ||
| status = fields.Selection([ | ||
| ('new', 'New'), | ||
| ('running', 'Running'), | ||
| ('done', 'Done'), | ||
| ('failed', 'Failed'), | ||
| ], default='new', copy=False, tracking=True) | ||
|
|
||
| @api.model | ||
| def _run_projects(self): | ||
| """ | ||
| This method is called by a scheduled action to run all active data flow projects. | ||
| """ | ||
| projects = self.search([('active', '=', True), ('status', '!=', 'running')]) | ||
| for project in projects: | ||
| project.write({'status': 'running'}) | ||
| self.env.cr.commit() | ||
|
|
||
| try: | ||
| if not run_workflow: | ||
| raise ImportError("The 'odoo-data-flow' library is not available.") | ||
|
|
||
| if not project.flow_file_path: | ||
| raise ValueError(f"Flow file path is not set for project '{project.name}'") | ||
|
|
||
| # The odoo-data-flow library expects a path to a YAML config file. | ||
| run_workflow(project.flow_file_path) | ||
|
|
||
| project.write({'status': 'done'}) | ||
| self.env.cr.commit() | ||
|
|
||
| except Exception: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catching a broad |
||
| _logger.error( | ||
| "Failed to run data flow project '%s'.\n%s", | ||
| project.name, | ||
| traceback.format_exc() | ||
| ) | ||
| project.write({'status': 'failed'}) | ||
| self.env.cr.commit() | ||
|
Comment on lines
+38
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of If you need to process each project in an isolated transaction, the recommended approach in Odoo is to use a job queue module (like I recommend refactoring this method to remove the manual commits and wrap the logic for a single project in a for project in projects:
try:
project.write({'status': 'running'})
if not run_workflow:
raise ImportError("The 'odoo-data-flow' library is not available.")
if not project.flow_file_path:
raise ValueError(f"Flow file path is not set for project '{project.name}'")
# The odoo-data-flow library expects a path to a YAML config file.
run_workflow(project.flow_file_path)
project.write({'status': 'done'})
except Exception:
_logger.error(
"Failed to run data flow project '%s'.\n%s",
project.name,
traceback.format_exc()
)
project.write({'status': 'failed'}) |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
| access_odf_connection,odf.connection access,model_odf_connection,base.group_user,1,1,1,1 | ||
| access_odf_flow_project,odf.flow.project access,model_odf_flow_project,base.group_user,1,1,1,1 | ||
|
Comment on lines
+2
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current access control rules grant all internal users ( I suggest restricting access to a more privileged group, for example, system administrators ( |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- Main Menu --> | ||
| <menuitem | ||
| id="menu_odf_root" | ||
| name="Data Flow" | ||
| sequence="10"/> | ||
|
|
||
| <!-- Projects Menu --> | ||
| <menuitem | ||
| id="menu_odf_projects" | ||
| name="Projects" | ||
| parent="menu_odf_root" | ||
| action="action_odf_flow_project" | ||
| sequence="10"/> | ||
|
|
||
| <!-- Configuration Menu --> | ||
| <menuitem | ||
| id="menu_odf_configuration" | ||
| name="Configuration" | ||
| parent="menu_odf_root" | ||
| sequence="100"/> | ||
|
|
||
| <!-- Connections Menu --> | ||
| <menuitem | ||
| id="menu_odf_connections" | ||
| name="Connections" | ||
| parent="menu_odf_configuration" | ||
| action="action_odf_connection" | ||
| sequence="10"/> | ||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- Form View --> | ||
| <record id="view_odf_connection_form" model="ir.ui.view"> | ||
| <field name="name">odf.connection.form</field> | ||
| <field name="model">odf.connection</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="Connection"> | ||
| <header> | ||
| <button name="test_connection" type="object" string="Test Connection" class="oe_highlight"/> | ||
| </header> | ||
| <sheet> | ||
| <group> | ||
| <field name="name"/> | ||
| <field name="host"/> | ||
| <field name="port"/> | ||
| <field name="dbname"/> | ||
| <field name="user"/> | ||
| <field name="password"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Tree View --> | ||
| <record id="view_odf_connection_tree" model="ir.ui.view"> | ||
| <field name="name">odf.connection.tree</field> | ||
| <field name="model">odf.connection</field> | ||
| <field name="arch" type="xml"> | ||
| <tree string="Connections"> | ||
| <field name="name"/> | ||
| <field name="host"/> | ||
| <field name="dbname"/> | ||
| <field name="user"/> | ||
| </tree> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Action --> | ||
| <record id="action_odf_connection" model="ir.actions.act_window"> | ||
| <field name="name">Connections</field> | ||
| <field name="res_model">odf.connection</field> | ||
| <field name="view_mode">tree,form</field> | ||
| </record> | ||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- Form View --> | ||
| <record id="view_odf_flow_project_form" model="ir.ui.view"> | ||
| <field name="name">odf.flow.project.form</field> | ||
| <field name="model">odf.flow.project</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="Flow Project"> | ||
| <sheet> | ||
| <group> | ||
| <field name="name"/> | ||
| <field name="active"/> | ||
| <field name="source_connection_id"/> | ||
| <field name="destination_connection_id"/> | ||
| <field name="flow_file_path"/> | ||
| <field name="status"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Tree View --> | ||
| <record id="view_odf_flow_project_tree" model="ir.ui.view"> | ||
| <field name="name">odf.flow.project.tree</field> | ||
| <field name="model">odf.flow.project</field> | ||
| <field name="arch" type="xml"> | ||
| <tree string="Flow Projects"> | ||
| <field name="name"/> | ||
| <field name="status"/> | ||
| </tree> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Action --> | ||
| <record id="action_odf_flow_project" model="ir.actions.act_window"> | ||
| <field name="name">Flow Projects</field> | ||
| <field name="res_model">odf.flow.project</field> | ||
| <field name="view_mode">tree,form</field> | ||
| </record> | ||
| </odoo> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scheduled action is configured to run as the
rootuser (base.user_root), which has maximum privileges. This is a security risk. It's best practice to run cron jobs with a dedicated user that has only the minimum required permissions to perform its tasks.