feat: introduce hashids permalink keys (#19324)

* feat: introduce hashids permalink keys

* implement dashboard permalinks

* remove shorturl notice from UPDATING.md

* lint

* fix test

* introduce KeyValueResource

* make filterState optional

* fix test

* fix resource names
This commit is contained in:
Ville Brofeldt
2022-03-24 21:53:09 +02:00
committed by GitHub
parent dc769a9a34
commit f4b71abb22
39 changed files with 344 additions and 367 deletions

View File

@@ -36,12 +36,8 @@ def test_create_id_entry(app_context: AppContext, admin: User) -> None:
from superset.key_value.commands.create import CreateKeyValueCommand
from superset.key_value.models import KeyValueEntry
key = CreateKeyValueCommand(
actor=admin, resource=RESOURCE, value=VALUE, key_type="id",
).run()
entry = (
db.session.query(KeyValueEntry).filter_by(id=int(key)).autoflush(False).one()
)
key = CreateKeyValueCommand(actor=admin, resource=RESOURCE, value=VALUE).run()
entry = db.session.query(KeyValueEntry).filter_by(id=key.id).autoflush(False).one()
assert pickle.loads(entry.value) == VALUE
assert entry.created_by_fk == admin.id
db.session.delete(entry)
@@ -52,11 +48,9 @@ def test_create_uuid_entry(app_context: AppContext, admin: User) -> None:
from superset.key_value.commands.create import CreateKeyValueCommand
from superset.key_value.models import KeyValueEntry
key = CreateKeyValueCommand(
actor=admin, resource=RESOURCE, value=VALUE, key_type="uuid",
).run()
key = CreateKeyValueCommand(actor=admin, resource=RESOURCE, value=VALUE).run()
entry = (
db.session.query(KeyValueEntry).filter_by(uuid=UUID(key)).autoflush(False).one()
db.session.query(KeyValueEntry).filter_by(uuid=key.uuid).autoflush(False).one()
)
assert pickle.loads(entry.value) == VALUE
assert entry.created_by_fk == admin.id

View File

@@ -30,8 +30,8 @@ from tests.integration_tests.key_value.commands.fixtures import admin, RESOURCE,
if TYPE_CHECKING:
from superset.key_value.models import KeyValueEntry
ID_KEY = "234"
UUID_KEY = "5aae143c-44f1-478e-9153-ae6154df333a"
ID_KEY = 234
UUID_KEY = UUID("5aae143c-44f1-478e-9153-ae6154df333a")
@pytest.fixture
@@ -39,10 +39,7 @@ def key_value_entry() -> KeyValueEntry:
from superset.key_value.models import KeyValueEntry
entry = KeyValueEntry(
id=int(ID_KEY),
uuid=UUID(UUID_KEY),
resource=RESOURCE,
value=pickle.dumps(VALUE),
id=ID_KEY, uuid=UUID_KEY, resource=RESOURCE, value=pickle.dumps(VALUE),
)
db.session.add(entry)
db.session.commit()
@@ -55,10 +52,7 @@ def test_delete_id_entry(
from superset.key_value.commands.delete import DeleteKeyValueCommand
from superset.key_value.models import KeyValueEntry
assert (
DeleteKeyValueCommand(resource=RESOURCE, key=ID_KEY, key_type="id",).run()
is True
)
assert DeleteKeyValueCommand(resource=RESOURCE, key=ID_KEY).run() is True
def test_delete_uuid_entry(
@@ -67,10 +61,7 @@ def test_delete_uuid_entry(
from superset.key_value.commands.delete import DeleteKeyValueCommand
from superset.key_value.models import KeyValueEntry
assert (
DeleteKeyValueCommand(resource=RESOURCE, key=UUID_KEY, key_type="uuid").run()
is True
)
assert DeleteKeyValueCommand(resource=RESOURCE, key=UUID_KEY).run() is True
def test_delete_entry_missing(
@@ -79,7 +70,4 @@ def test_delete_entry_missing(
from superset.key_value.commands.delete import DeleteKeyValueCommand
from superset.key_value.models import KeyValueEntry
assert (
DeleteKeyValueCommand(resource=RESOURCE, key="456", key_type="id").run()
is False
)
assert DeleteKeyValueCommand(resource=RESOURCE, key=456).run() is False

View File

@@ -26,14 +26,15 @@ from flask_appbuilder.security.sqla.models import User
from sqlalchemy.orm import Session
from superset.extensions import db
from superset.key_value.types import KeyValueResource
from tests.integration_tests.test_app import app
if TYPE_CHECKING:
from superset.key_value.models import KeyValueEntry
ID_KEY = "123"
UUID_KEY = "3e7a2ab8-bcaf-49b0-a5df-dfb432f291cc"
RESOURCE = "my_resource"
ID_KEY = 123
UUID_KEY = UUID("3e7a2ab8-bcaf-49b0-a5df-dfb432f291cc")
RESOURCE = KeyValueResource.APP
VALUE = {"foo": "bar"}
@@ -42,10 +43,7 @@ def key_value_entry() -> Generator[KeyValueEntry, None, None]:
from superset.key_value.models import KeyValueEntry
entry = KeyValueEntry(
id=int(ID_KEY),
uuid=UUID(UUID_KEY),
resource=RESOURCE,
value=pickle.dumps(VALUE),
id=ID_KEY, uuid=UUID_KEY, resource=RESOURCE, value=pickle.dumps(VALUE),
)
db.session.add(entry)
db.session.commit()

View File

@@ -39,7 +39,7 @@ if TYPE_CHECKING:
def test_get_id_entry(app_context: AppContext, key_value_entry: KeyValueEntry) -> None:
from superset.key_value.commands.get import GetKeyValueCommand
value = GetKeyValueCommand(resource=RESOURCE, key=ID_KEY, key_type="id").run()
value = GetKeyValueCommand(resource=RESOURCE, key=ID_KEY).run()
assert value == VALUE
@@ -48,7 +48,7 @@ def test_get_uuid_entry(
) -> None:
from superset.key_value.commands.get import GetKeyValueCommand
value = GetKeyValueCommand(resource=RESOURCE, key=UUID_KEY, key_type="uuid").run()
value = GetKeyValueCommand(resource=RESOURCE, key=UUID_KEY).run()
assert value == VALUE
@@ -57,7 +57,7 @@ def test_get_id_entry_missing(
) -> None:
from superset.key_value.commands.get import GetKeyValueCommand
value = GetKeyValueCommand(resource=RESOURCE, key="456", key_type="id").run()
value = GetKeyValueCommand(resource=RESOURCE, key=456).run()
assert value is None
@@ -74,7 +74,7 @@ def test_get_expired_entry(app_context: AppContext) -> None:
)
db.session.add(entry)
db.session.commit()
value = GetKeyValueCommand(resource=RESOURCE, key=ID_KEY, key_type="id").run()
value = GetKeyValueCommand(resource=RESOURCE, key=ID_KEY).run()
assert value is None
db.session.delete(entry)
db.session.commit()
@@ -94,7 +94,7 @@ def test_get_future_expiring_entry(app_context: AppContext) -> None:
)
db.session.add(entry)
db.session.commit()
value = GetKeyValueCommand(resource=RESOURCE, key=str(id_), key_type="id").run()
value = GetKeyValueCommand(resource=RESOURCE, key=id_).run()
assert value == VALUE
db.session.delete(entry)
db.session.commit()

View File

@@ -46,12 +46,10 @@ def test_update_id_entry(
from superset.key_value.models import KeyValueEntry
key = UpdateKeyValueCommand(
actor=admin, resource=RESOURCE, key=ID_KEY, value=NEW_VALUE, key_type="id",
actor=admin, resource=RESOURCE, key=ID_KEY, value=NEW_VALUE,
).run()
assert key == ID_KEY
entry = (
db.session.query(KeyValueEntry).filter_by(id=int(ID_KEY)).autoflush(False).one()
)
assert key.id == ID_KEY
entry = db.session.query(KeyValueEntry).filter_by(id=ID_KEY).autoflush(False).one()
assert pickle.loads(entry.value) == NEW_VALUE
assert entry.changed_by_fk == admin.id
@@ -63,25 +61,20 @@ def test_update_uuid_entry(
from superset.key_value.models import KeyValueEntry
key = UpdateKeyValueCommand(
actor=admin, resource=RESOURCE, key=UUID_KEY, value=NEW_VALUE, key_type="uuid",
actor=admin, resource=RESOURCE, key=UUID_KEY, value=NEW_VALUE,
).run()
assert key == UUID_KEY
assert key.uuid == UUID_KEY
entry = (
db.session.query(KeyValueEntry)
.filter_by(uuid=UUID(UUID_KEY))
.autoflush(False)
.one()
db.session.query(KeyValueEntry).filter_by(uuid=UUID_KEY).autoflush(False).one()
)
assert pickle.loads(entry.value) == NEW_VALUE
assert entry.changed_by_fk == admin.id
def test_update_missing_entry(
app_context: AppContext, admin: User, key_value_entry: KeyValueEntry,
) -> None:
def test_update_missing_entry(app_context: AppContext, admin: User) -> None:
from superset.key_value.commands.update import UpdateKeyValueCommand
key = UpdateKeyValueCommand(
actor=admin, resource=RESOURCE, key="456", value=NEW_VALUE, key_type="id",
actor=admin, resource=RESOURCE, key=456, value=NEW_VALUE,
).run()
assert key is None

View File

@@ -46,9 +46,9 @@ def test_upsert_id_entry(
from superset.key_value.models import KeyValueEntry
key = UpsertKeyValueCommand(
actor=admin, resource=RESOURCE, key=ID_KEY, value=NEW_VALUE, key_type="id",
actor=admin, resource=RESOURCE, key=ID_KEY, value=NEW_VALUE,
).run()
assert key == ID_KEY
assert key.id == ID_KEY
entry = (
db.session.query(KeyValueEntry).filter_by(id=int(ID_KEY)).autoflush(False).one()
)
@@ -63,28 +63,23 @@ def test_upsert_uuid_entry(
from superset.key_value.models import KeyValueEntry
key = UpsertKeyValueCommand(
actor=admin, resource=RESOURCE, key=UUID_KEY, value=NEW_VALUE, key_type="uuid",
actor=admin, resource=RESOURCE, key=UUID_KEY, value=NEW_VALUE,
).run()
assert key == UUID_KEY
assert key.uuid == UUID_KEY
entry = (
db.session.query(KeyValueEntry)
.filter_by(uuid=UUID(UUID_KEY))
.autoflush(False)
.one()
db.session.query(KeyValueEntry).filter_by(uuid=UUID_KEY).autoflush(False).one()
)
assert pickle.loads(entry.value) == NEW_VALUE
assert entry.changed_by_fk == admin.id
def test_upsert_missing_entry(
app_context: AppContext, admin: User, key_value_entry: KeyValueEntry,
) -> None:
def test_upsert_missing_entry(app_context: AppContext, admin: User) -> None:
from superset.key_value.commands.upsert import UpsertKeyValueCommand
from superset.key_value.models import KeyValueEntry
key = UpsertKeyValueCommand(
actor=admin, resource=RESOURCE, key="456", value=NEW_VALUE, key_type="id",
actor=admin, resource=RESOURCE, key=456, value=NEW_VALUE,
).run()
assert key == "456"
assert key.id == 456
db.session.query(KeyValueEntry).filter_by(id=456).delete()
db.session.commit()