feat: allow assets to be managed externally (#18093)

* feat: allow assets to be managed externally

* Use server_default
This commit is contained in:
Beto Dealmeida 2022-01-24 11:03:01 -08:00 committed by GitHub
parent c77d24cda3
commit 1c0b141e2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 2 deletions

View File

@ -110,6 +110,8 @@ class BaseDatasource(
params = Column(String(1000))
perm = Column(String(1000))
schema_perm = Column(String(1000))
is_managed_externally = Column(Boolean, nullable=False, default=False)
external_url = Column(Text, nullable=True)
sql: Optional[str] = None
owners: List[User]

View File

@ -0,0 +1,105 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Add columns for external management
Revision ID: 5fd49410a97a
Revises: c53bae8f08dd
Create Date: 2022-01-19 07:34:20.594786
"""
# revision identifiers, used by Alembic.
revision = "5fd49410a97a"
down_revision = "c53bae8f08dd"
import sqlalchemy as sa
from alembic import op
def upgrade():
with op.batch_alter_table("dashboards") as batch_op:
batch_op.add_column(
sa.Column(
"is_managed_externally",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.add_column(sa.Column("external_url", sa.Text(), nullable=True))
with op.batch_alter_table("datasources") as batch_op:
batch_op.add_column(
sa.Column(
"is_managed_externally",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.add_column(sa.Column("external_url", sa.Text(), nullable=True))
with op.batch_alter_table("dbs") as batch_op:
batch_op.add_column(
sa.Column(
"is_managed_externally",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.add_column(sa.Column("external_url", sa.Text(), nullable=True))
with op.batch_alter_table("slices") as batch_op:
batch_op.add_column(
sa.Column(
"is_managed_externally",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.add_column(sa.Column("external_url", sa.Text(), nullable=True))
with op.batch_alter_table("tables") as batch_op:
batch_op.add_column(
sa.Column(
"is_managed_externally",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.add_column(sa.Column("external_url", sa.Text(), nullable=True))
def downgrade():
with op.batch_alter_table("tables") as batch_op:
batch_op.drop_column("external_url")
batch_op.drop_column("is_managed_externally")
with op.batch_alter_table("slices") as batch_op:
batch_op.drop_column("external_url")
batch_op.drop_column("is_managed_externally")
with op.batch_alter_table("dbs") as batch_op:
batch_op.drop_column("external_url")
batch_op.drop_column("is_managed_externally")
with op.batch_alter_table("datasources") as batch_op:
batch_op.drop_column("external_url")
batch_op.drop_column("is_managed_externally")
with op.batch_alter_table("dashboards") as batch_op:
batch_op.drop_column("external_url")
batch_op.drop_column("is_managed_externally")

View File

@ -151,6 +151,9 @@ class Database(
encrypted_extra = Column(encrypted_field_factory.create(Text), nullable=True)
impersonate_user = Column(Boolean, default=False)
server_cert = Column(encrypted_field_factory.create(Text), nullable=True)
is_managed_externally = Column(Boolean, nullable=False, default=False)
external_url = Column(Text, nullable=True)
export_fields = [
"database_name",
"sqlalchemy_uri",

View File

@ -149,6 +149,8 @@ class Dashboard(Model, AuditMixinNullable, ImportExportMixin):
slices = relationship(Slice, secondary=dashboard_slices, backref="dashboards")
owners = relationship(security_manager.user_model, secondary=dashboard_user)
published = Column(Boolean, default=False)
is_managed_externally = Column(Boolean, nullable=False, default=False)
external_url = Column(Text, nullable=True)
roles = relationship(security_manager.role_model, secondary=DashboardRoles)
_filter_sets = relationship(
"FilterSet", back_populates="dashboard", cascade="all, delete"

View File

@ -341,7 +341,7 @@ class ImportExportMixin:
self.params = json.dumps(params)
def reset_ownership(self) -> None:
""" object will belong to the user the current user """
"""object will belong to the user the current user"""
# make sure the object doesn't have relations to a user
# it will be filled by appbuilder on save
self.created_by = None

View File

@ -25,7 +25,16 @@ import sqlalchemy as sqla
from flask_appbuilder import Model
from flask_appbuilder.models.decorators import renders
from markupsafe import escape, Markup
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Table, Text
from sqlalchemy import (
Boolean,
Column,
DateTime,
ForeignKey,
Integer,
String,
Table,
Text,
)
from sqlalchemy.engine.base import Connection
from sqlalchemy.orm import relationship
from sqlalchemy.orm.mapper import Mapper
@ -83,6 +92,8 @@ class Slice( # pylint: disable=too-many-public-methods
last_saved_by_fk = Column(Integer, ForeignKey("ab_user.id"), nullable=True)
certified_by = Column(Text)
certification_details = Column(Text)
is_managed_externally = Column(Boolean, nullable=False, default=False)
external_url = Column(Text, nullable=True)
last_saved_by = relationship(
security_manager.user_model, foreign_keys=[last_saved_by_fk]
)