Skip to content

Commit

Permalink
multidest: add tables and prefix routes
Browse files Browse the repository at this point in the history
Databases changes:
  - add `bib_destinations` table and references FK
  - add `bib_entities` table and references FK
  - add "synthese" destination
  - add SYNTHESE/ALL/C to `t_permissions_available`
  - copy permissions on IMPORT/IMPORT/C to SYNTHESE/ALL/C

All backend routes are prefixed with destination.
For now, the frontend calls the route with hard-coded "synthese" destination.
  • Loading branch information
bouttier committed Oct 20, 2023
1 parent 0f7cea9 commit 1490907
Show file tree
Hide file tree
Showing 18 changed files with 763 additions and 318 deletions.
17 changes: 15 additions & 2 deletions backend/gn_module_import/blueprint.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
from flask import Blueprint
from flask import Blueprint, current_app, g

from geonature.core.gn_commons.models import TModules

from gn_module_import.models import Destination
import gn_module_import.admin # noqa: F401

blueprint = Blueprint("import", __name__, template_folder="templates")


@blueprint.url_value_preprocessor
def set_current_destination(endpoint, values):
if current_app.url_map.is_endpoint_expecting(endpoint, "destination"):
g.destination = values["destination"] = Destination.query.filter(
Destination.code == values["destination"]
).first_or_404()


from .routes import (
imports,
mappings,
fields,
)

from .commands import fix_mappings


blueprint.cli.add_command(fix_mappings)
239 changes: 239 additions & 0 deletions backend/gn_module_import/migrations/2b0b3bd0248c_multidest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
"""multidest
Revision ID: 2b0b3bd0248c
Revises: 2896cf965dd6
Create Date: 2023-10-20 09:05:49.973738
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.schema import Table, MetaData


# revision identifiers, used by Alembic.
revision = "2b0b3bd0248c"
down_revision = "2896cf965dd6"
branch_labels = None
depends_on = None


def upgrade():
meta = MetaData(bind=op.get_bind())
module = Table("t_modules", meta, autoload=True, schema="gn_commons")
destination = op.create_table(
"bib_destinations",
sa.Column("id_destination", sa.Integer, primary_key=True),
sa.Column(
"id_module",
sa.Integer,
sa.ForeignKey("gn_commons.t_modules.id_module", ondelete="CASCADE"),
),
sa.Column("code", sa.String(64), unique=True),
sa.Column("label", sa.String(128)),
sa.Column("table_name", sa.String(64)),
schema="gn_imports",
)
id_synthese_module = (
op.get_bind()
.execute(sa.select([module.c.id_module]).where(module.c.module_code == "SYNTHESE"))
.scalar()
)
op.bulk_insert(
destination,
[
{
"id_module": id_synthese_module,
"code": "synthese",
"label": "synthèse",
"table_name": "t_imports_synthese",
},
],
)
id_synthese_dest = (
op.get_bind()
.execute(
sa.select([destination.c.id_destination]).where(
destination.c.id_module == id_synthese_module
)
)
.scalar()
)
op.add_column(
"bib_fields",
sa.Column(
"id_destination",
sa.Integer,
sa.ForeignKey("gn_imports.bib_destinations.id_destination"),
nullable=True,
),
schema="gn_imports",
)
field = Table("bib_fields", meta, autoload=True, schema="gn_imports")
op.execute(field.update().values({"id_destination": id_synthese_dest}))
op.alter_column(
table_name="bib_fields", column_name="id_destination", nullable=False, schema="gn_imports"
)
op.add_column(
"t_imports",
sa.Column(
"id_destination",
sa.Integer,
sa.ForeignKey("gn_imports.bib_destinations.id_destination"),
nullable=True,
),
schema="gn_imports",
)
imprt = Table("t_imports", meta, autoload=True, schema="gn_imports")
op.execute(imprt.update().values({"id_destination": id_synthese_dest}))
op.alter_column(
table_name="t_imports", column_name="id_destination", nullable=False, schema="gn_imports"
)
op.add_column(
"t_mappings",
sa.Column(
"id_destination",
sa.Integer,
sa.ForeignKey("gn_imports.bib_destinations.id_destination"),
nullable=True,
),
schema="gn_imports",
)
mapping = Table("t_mappings", meta, autoload=True, schema="gn_imports")
op.execute(mapping.update().values({"id_destination": id_synthese_dest}))
op.alter_column(
table_name="t_mappings", column_name="id_destination", nullable=False, schema="gn_imports"
)
entity = op.create_table(
"bib_entities",
sa.Column("id_entity", sa.Integer, primary_key=True),
sa.Column("id_destination", sa.Integer, sa.ForeignKey(destination.c.id_destination)),
sa.Column("label", sa.String(64)),
sa.Column("order", sa.Integer),
sa.Column("validity_column", sa.String(64)),
schema="gn_imports",
)
op.bulk_insert(
entity,
[
{
"id_destination": id_synthese_dest,
"label": "Observations",
"order": 1,
"validity_column": "gn_is_valid",
},
],
)
op.create_table(
"cor_entity_field",
sa.Column(
"id_entity",
sa.Integer,
sa.ForeignKey("gn_imports.bib_entities.id_entity", ondelete="CASCADE"),
primary_key=True,
),
sa.Column(
"id_field",
sa.Integer,
sa.ForeignKey("gn_imports.bib_fields.id_field", ondelete="CASCADE"),
primary_key=True,
),
schema="gn_imports",
)
op.execute(
"""
INSERT INTO
gn_imports.cor_entity_field (id_entity, id_field)
SELECT
e.id_entity,
f.id_field
FROM
gn_commons.t_modules m
JOIN
gn_imports.bib_destinations d ON d.id_module = m.id_module
JOIN
gn_imports.bib_entities e ON e.id_destination = d.id_destination
JOIN
gn_imports.bib_fields f ON f.id_destination = d.id_destination
WHERE m.module_code = 'SYNTHESE';
"""
)
op.execute(
"""
INSERT INTO
gn_permissions.t_permissions_available (id_module, id_object, id_action, label, scope_filter)
SELECT
m.id_module, o.id_object, a.id_action, 'Importer des observations', TRUE
FROM
gn_commons.t_modules m,
gn_permissions.t_objects o,
gn_permissions.bib_actions a
WHERE
m.module_code = 'SYNTHESE'
AND
o.code_object = 'ALL'
AND
a.code_action = 'C'
"""
)
op.execute(
"""
INSERT INTO
gn_permissions.t_permissions (id_role, id_module, id_object, id_action, scope_value)
SELECT
p.id_role, new_module.id_module, new_object.id_object, p.id_action, p.scope_value
FROM
gn_permissions.t_permissions p
JOIN gn_permissions.bib_actions a USING(id_action)
JOIN gn_commons.t_modules m USING(id_module)
JOIN gn_permissions.t_objects o USING(id_object)
JOIN utilisateurs.t_roles r USING(id_role),
gn_commons.t_modules new_module,
gn_permissions.t_objects new_object
WHERE
a.code_action = 'C' AND m.module_code = 'IMPORT' AND o.code_object = 'IMPORT'
AND
new_module.module_code = 'SYNTHESE' AND new_object.code_object = 'ALL';
"""
)
# TODO unique constraint


def downgrade():
op.execute(
"""
DELETE FROM
gn_permissions.t_permissions p
USING
gn_permissions.bib_actions a,
gn_commons.t_modules m,
gn_permissions.t_objects o
WHERE
p.id_action = a.id_action AND a.code_action = 'C'
AND
p.id_module = m.id_module AND m.module_code = 'SYNTHESE'
AND
p.id_object = o.id_object AND o.code_object = 'ALL';
"""
)
op.execute(
"""
DELETE FROM
gn_permissions.t_permissions_available pa
USING
gn_permissions.bib_actions a,
gn_commons.t_modules m,
gn_permissions.t_objects o
WHERE
pa.id_action = a.id_action AND a.code_action = 'C'
AND
pa.id_module = m.id_module AND m.module_code = 'SYNTHESE'
AND
pa.id_object = o.id_object AND o.code_object = 'ALL';
"""
)
op.drop_table("cor_entity_field", schema="gn_imports")
op.drop_table("bib_entities", schema="gn_imports")
op.drop_column(schema="gn_imports", table_name="bib_fields", column_name="id_destination")
op.drop_column(schema="gn_imports", table_name="t_mappings", column_name="id_destination")
op.drop_column(schema="gn_imports", table_name="t_imports", column_name="id_destination")
op.drop_table("bib_destinations", schema="gn_imports")
58 changes: 56 additions & 2 deletions backend/gn_module_import/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,52 @@ def __str__(self):
return f"<ImportError import={self.id_import},type={self.type.name},rows={self.rows}>"


class Destination(db.Model):
__tablename__ = "bib_destinations"
__table_args__ = {"schema": "gn_imports"}

id_destination = db.Column(db.Integer, primary_key=True, autoincrement=True)
id_module = db.Column(db.Integer, ForeignKey(TModules.id_module), nullable=True)
code = db.Column(db.String(64), unique=True)
label = db.Column(db.String(128))
table_name = db.Column(db.String(64))

module = relationship(TModules)


cor_entity_field = db.Table(
"cor_entity_field",
db.Column(
"id_entity",
db.Integer,
db.ForeignKey("gn_imports.bib_entities.id_entity"),
primary_key=True,
),
db.Column(
"id_field",
db.Integer,
db.ForeignKey("gn_imports.bib_fields.id_field"),
primary_key=True,
),
schema="gn_imports",
)


@serializable
class Entity(db.Model):
__tablename__ = "bib_entities"
__table_args__ = {"schema": "gn_imports"}

id_entity = db.Column(db.Integer, primary_key=True, autoincrement=True)
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination))
destination = relationship(Destination)
label = db.Column(db.String(64))
order = db.Column(db.Integer)
validity_column = db.Column(db.String(64))

fields = relationship("BibFields", secondary=cor_entity_field)


class InstancePermissionMixin:
def get_instance_permissions(self, scopes, user=None):
if user is None:
Expand Down Expand Up @@ -167,6 +213,8 @@ class TImports(InstancePermissionMixin, db.Model):
AVAILABLE_SEPARATORS = [",", ";"]

id_import = db.Column(db.Integer, primary_key=True, autoincrement=True)
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination))
destination = relationship(Destination)
format_source_file = db.Column(db.Unicode, nullable=True)
srid = db.Column(db.Integer, nullable=True)
separator = db.Column(db.Unicode, nullable=True)
Expand Down Expand Up @@ -531,6 +579,8 @@ class BibFields(db.Model):
__table_args__ = {"schema": "gn_imports"}

id_field = db.Column(db.Integer, primary_key=True)
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination))
destination = relationship(Destination)
name_field = db.Column(db.Unicode, nullable=False, unique=True)
source_field = db.Column(db.Unicode, unique=True)
synthese_field = db.Column(db.Unicode, unique=True)
Expand Down Expand Up @@ -602,6 +652,8 @@ class MappingTemplate(db.Model):
query_class = MappingQuery

id = db.Column(db.Integer, primary_key=True)
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination))
destination = relationship(Destination)
label = db.Column(db.Unicode(255), nullable=False)
type = db.Column(db.Unicode(10), nullable=False)
active = db.Column(db.Boolean, nullable=False, default=True, server_default="true")
Expand Down Expand Up @@ -655,7 +707,7 @@ class FieldMapping(MappingTemplate):
@staticmethod
def validate_values(values):
fields = (
BibFields.query.filter_by(display=True)
BibFields.query.filter_by(destination=g.destination, display=True)
.with_entities(
BibFields.name_field,
BibFields.autogenerated,
Expand Down Expand Up @@ -698,7 +750,9 @@ class ContentMapping(MappingTemplate):
@staticmethod
def validate_values(values):
nomenclature_fields = (
BibFields.query.filter(BibFields.nomenclature_type != None)
BibFields.query.filter(
BibFields.destination == g.destination, BibFields.nomenclature_type != None
)
.options(
joinedload(BibFields.nomenclature_type).joinedload(
BibNomenclaturesTypes.nomenclatures
Expand Down
Loading

0 comments on commit 1490907

Please sign in to comment.