Skip to content

Commit

Permalink
BI-5560: move RLS module to a separate package (#483)
Browse files Browse the repository at this point in the history
  • Loading branch information
MCPN authored Jun 20, 2024
1 parent 0b15a7f commit dc5c0a5
Show file tree
Hide file tree
Showing 36 changed files with 472 additions and 236 deletions.
7 changes: 4 additions & 3 deletions lib/dl_api_lib/dl_api_lib/api_common/dataset_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from dl_api_lib import exc
from dl_api_lib.dataset.utils import allow_rls_for_dataset
from dl_api_lib.service_registry.service_registry import ApiServiceRegistry
from dl_api_lib.utils.rls import FieldRLSSerializer
from dl_app_tools.profiling_base import generic_profiler
from dl_constants.exc import (
DEFAULT_ERR_CODE_API_PREFIX,
Expand All @@ -36,11 +35,13 @@
from dl_core.us_manager.local_cache import USEntryBuffer
from dl_core.us_manager.us_manager import USManagerBase
from dl_core.us_manager.us_manager_sync import SyncUSManager
import dl_rls.exc as rls_exc
from dl_rls.serializer import FieldRLSSerializer
from dl_utils.aio import await_sync


if TYPE_CHECKING:
from dl_core.rls import RLSEntry
from dl_rls.models import RLSEntry


LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -305,7 +306,7 @@ def _update_dataset_rls_from_body(self, dataset: Dataset, body: dict, allow_rls_
if rlse.field_guid == field.guid
]
if self._rls_list_to_set(saved_field_rls) != self._rls_list_to_set(rls_entries_pre):
raise exc.RLSConfigParsingError(
raise rls_exc.RLSConfigParsingError(
"For this feature to work, save dataset after editing the RLS config.", details=dict()
)
# otherwise no effective config changes (that are worth checking in preview)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
is_compeng_executable,
)
from dl_api_lib.service_registry.service_registry import ApiServiceRegistry
from dl_api_lib.utils.rls import FieldRLSSerializer
from dl_constants.enums import (
AggregationFunction,
BinaryJoinOperator,
Expand Down Expand Up @@ -61,6 +60,7 @@
StandardDialect,
from_name_and_version,
)
from dl_rls.serializer import FieldRLSSerializer


LOGGER = logging.getLogger(__name__)
Expand Down
10 changes: 5 additions & 5 deletions lib/dl_api_lib/dl_api_lib/app_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@
ConnectionType,
RLSSubjectType,
)
from dl_core.rls import (
RLS_FAILED_USER_NAME_PREFIX,
BaseSubjectResolver,
RLSSubject,
)
from dl_core.services_registry.entity_checker import EntityUsageChecker
from dl_core.services_registry.file_uploader_client_factory import FileUploaderSettings
from dl_core.services_registry.inst_specific_sr import (
Expand All @@ -48,6 +43,11 @@
)
from dl_pivot.base.transformer_factory import PivotTransformerFactory
from dl_pivot.plugin_registration import get_pivot_transformer_factory_cls
from dl_rls.models import (
RLS_FAILED_USER_NAME_PREFIX,
RLSSubject,
)
from dl_rls.subject_resolver import BaseSubjectResolver
from dl_task_processor.arq_wrapper import create_arq_redis_settings


Expand Down
4 changes: 2 additions & 2 deletions lib/dl_api_lib/dl_api_lib/error_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from dl_dashsql import exc as dashsql_exc
from dl_formula.core import exc as formula_exc
import dl_query_processing.exc
from dl_rls import exc as rls_exc


LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -56,8 +57,7 @@
common_exc.InvalidFieldError: status.BAD_REQUEST,
common_exc.FieldNotFound: status.BAD_REQUEST,
common_exc.USPermissionRequired: status.FORBIDDEN,
exc.RLSConfigParsingError: status.BAD_REQUEST,
common_exc.RLSSubjectNotFound: status.BAD_REQUEST,
rls_exc.RLSError: status.BAD_REQUEST,
exc.FeatureNotAvailable: status.BAD_REQUEST,
dl_query_processing.exc.FilterError: status.BAD_REQUEST,
exc.UnsupportedForEntityType: status.BAD_REQUEST,
Expand Down
8 changes: 0 additions & 8 deletions lib/dl_api_lib/dl_api_lib/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ class FeatureNotAvailable(DLBaseException):
err_code = DLBaseException.err_code + ["FEATURE_NOT_AVAILABLE"]


class RLSError(DLBaseException):
err_code = DLBaseException.err_code + ["RLS"]


class RLSConfigParsingError(RLSError):
err_code = RLSError.err_code + ["PARSE"]


class DatasetActionNotAllowedError(DLBaseException):
err_code = DLBaseException.err_code + ["ACTION_NOT_ALLOWED"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
DefaultQueryProcessorFactory,
TypedQueryProcessorFactory,
)
from dl_api_lib.utils.rls import BaseSubjectResolver
from dl_constants.enums import QueryProcessingMode
from dl_core.services_registry.top_level import (
DefaultServicesRegistry,
Expand All @@ -33,6 +32,7 @@
LocalizerFactory,
)
from dl_pivot.base.transformer_factory import PivotTransformerFactory
from dl_rls.subject_resolver import BaseSubjectResolver


if TYPE_CHECKING:
Expand Down
4 changes: 0 additions & 4 deletions lib/dl_api_lib/dl_api_lib/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from __future__ import annotations

from .base import ( # ...
chunks,
need_permission,
need_permission_on_entry,
profile_stats,
query_execution_context,
Expand All @@ -19,7 +17,5 @@
__all__ = (
"query_execution_context",
"profile_stats",
"need_permission",
"need_permission_on_entry",
"chunks",
)
65 changes: 0 additions & 65 deletions lib/dl_api_lib/dl_api_lib/utils/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,13 @@
import os
from typing import (
TYPE_CHECKING,
Any,
Iterable,
Iterator,
Optional,
)
import uuid

from dl_api_lib.enums import USPermissionKind
from dl_app_tools.profiling_base import GenericProfiler
import dl_core.exc as common_exc
from dl_core.flask_utils.us_manager_middleware import USManagerFlaskMiddleware


# noinspection PyUnresolvedReferences


if TYPE_CHECKING:
Expand Down Expand Up @@ -73,66 +66,8 @@ def profile_stats(stats_dir: Optional[str] = None) -> Iterator[None]:
pr.dump_stats(filename)


def need_permission(us_entry_id: str, permission: USPermissionKind) -> None:
usm_user = USManagerFlaskMiddleware.get_request_us_manager()
entry = usm_user.get_by_id(us_entry_id)
need_permission_on_entry(entry, permission)


def need_permission_on_entry(us_entry: USEntry, permission: USPermissionKind) -> None:
assert us_entry.permissions is not None
assert us_entry.uuid is not None
if not us_entry.permissions[permission.name]:
raise common_exc.USPermissionRequired(us_entry.uuid, permission.name)


def chunks(lst: list[Any], size: int) -> Iterable[list[Any]]:
"""Yield successive chunks from lst. No padding."""
for idx in range(0, len(lst), size):
yield lst[idx : idx + size]


def split_by_quoted_quote(value: str, quote: str = "'") -> tuple[str, str]:
"""
Parse out a quoted value at the beginning,
where quotes are quoted by doubling (CSV-like).
>>> split_by_quoted_quote("'abc'de")
('abc', 'de')
>>> split_by_quoted_quote("'ab''c'''de")
("ab'c'", 'de')
>>> split_by_quoted_quote("'ab''c'''")
("ab'c'", '')
"""
ql = len(quote)
if not value.startswith(quote):
raise ValueError("Value does not start with quote")
value = value[ql:]
result = []
while True:
try:
next_quote = value.index(quote)
except ValueError as e:
raise ValueError("Unclosed quote") from e
value_piece = value[:next_quote]
result.append(value_piece)
value = value[next_quote + ql :]
if value.startswith(quote):
result.append(quote)
value = value[ql:]
else: # some other text, or end-of-line.
break

return "".join(result), value


def quote_by_quote(value: str, quote: str = "'") -> str:
"""
...
>>> quote_by_quote("a'b'")
"'a''b'''"
>>> split_by_quoted_quote(quote_by_quote("a'b'") + "and 'stuff'")
("a'b'", "and 'stuff'")
"""
return "{}{}{}".format(quote, value.replace(quote, quote + quote), quote)
4 changes: 2 additions & 2 deletions lib/dl_api_lib/dl_api_lib_tests/unit/test_rls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pytest

from dl_api_lib.utils.rls import FieldRLSSerializer
from dl_api_lib_testing.rls import (
RLS_CONFIG_CASES,
config_to_comparable,
)
from dl_constants.enums import RLSSubjectType
from dl_core.rls import RLSSubject
from dl_rls.models import RLSSubject
from dl_rls.serializer import FieldRLSSerializer


def test_group_names_by_account_type():
Expand Down
2 changes: 1 addition & 1 deletion lib/dl_api_lib/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ flask-marshmallow = ">=1.1.0"
flask-restx = ">=1.1.0"
marshmallow = ">=3.19.0"
marshmallow-oneofschema = ">=3.0.1"
more-itertools = ">=9.1.0"
python = ">=3.10, <3.13"
werkzeug = ">=2.2.3"
statcommons = {path = "../statcommons"}
Expand All @@ -37,6 +36,7 @@ datalens-dashsql = {path = "../../lib/dl_dashsql"}
datalens-pivot = {path = "../dl_pivot"}
datalens-pivot-pandas = {path = "../dl_pivot_pandas"}
datalens-cache-engine = {path = "../dl_cache_engine"}
datalens-rls = {path = "../dl_rls"}

[tool.poetry.group.tests.dependencies]
pytest = ">=7.2.2"
Expand Down
10 changes: 5 additions & 5 deletions lib/dl_api_lib_testing/dl_api_lib_testing/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@
)
from dl_core.aio.middlewares.services_registry import services_registry_middleware
from dl_core.aio.middlewares.us_manager import service_us_manager_middleware
from dl_core.rls import (
RLS_FAILED_USER_NAME_PREFIX,
BaseSubjectResolver,
RLSSubject,
)
from dl_core.services_registry import ServicesRegistry
from dl_core.services_registry.entity_checker import EntityUsageChecker
from dl_core.services_registry.env_manager_factory_base import EnvManagerFactory
Expand All @@ -53,6 +48,11 @@
from dl_core.utils import FutureRef
from dl_core_testing.app_test_workarounds import TestEnvManagerFactory
from dl_core_testing.fixture_server_runner import WSGIRunner
from dl_rls.models import (
RLS_FAILED_USER_NAME_PREFIX,
RLSSubject,
)
from dl_rls.subject_resolver import BaseSubjectResolver
from dl_testing.utils import get_root_certificates


Expand Down
6 changes: 3 additions & 3 deletions lib/dl_api_lib_testing/dl_api_lib_testing/rls.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import json
import pkgutil

from dl_api_lib.utils.rls import FieldRLSSerializer
import dl_api_lib_testing.test_data
from dl_constants.enums import RLSSubjectType
from dl_core.rls import (
BaseSubjectResolver,
from dl_rls.models import (
RLSEntry,
RLSPatternType,
RLSSubject,
)
from dl_rls.serializer import FieldRLSSerializer
from dl_rls.subject_resolver import BaseSubjectResolver


def load_rls_config(name: str) -> str:
Expand Down
1 change: 1 addition & 0 deletions lib/dl_api_lib_testing/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ datalens-pivot-pandas = {path = "../dl_pivot_pandas"}
datalens-query-processing = {path = "../dl_query_processing"}
datalens-testing = {path = "../dl_testing"}
datalens-cache-engine = {path = "../dl_cache_engine"}
datalens-rls = {path = "../dl_rls"}

[build-system]
build-backend = "poetry.core.masonry.api"
Expand Down
4 changes: 0 additions & 4 deletions lib/dl_core/dl_core/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,3 @@ def message(self) -> str:

class DataSourceMigrationImpossible(DLBaseException):
err_code = DLBaseException.err_code + ["DSRC_MIGRATION_IMPOSSIBLE"]


class RLSSubjectNotFound(DLBaseException):
err_code = DLBaseException.err_code + ["RLS_SUBJECT_NOT_FOUND"]
2 changes: 1 addition & 1 deletion lib/dl_core/dl_core/services_registry/inst_specific_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

import attr

from dl_core.rls import BaseSubjectResolver
from dl_core.utils import FutureRef
from dl_rls.subject_resolver import BaseSubjectResolver


if TYPE_CHECKING:
Expand Down
2 changes: 1 addition & 1 deletion lib/dl_core/dl_core/us_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
DirectCalculationSpec,
ResultSchema,
)
from dl_core.rls import RLS
from dl_core.us_entry import (
BaseAttrsDataModel,
USEntry,
)
from dl_rls.rls import RLS


if TYPE_CHECKING:
Expand Down
12 changes: 8 additions & 4 deletions lib/dl_core/dl_core/us_manager/storage_schemas/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
WhereClauseOperation,
)
from dl_core import multisource
from dl_core import rls as rls_module
from dl_core.base_models import (
DefaultWhereClause,
ObligatoryFilter,
Expand Down Expand Up @@ -75,6 +74,11 @@
TreeStrValue,
UuidValue,
)
from dl_rls.models import (
RLSEntry,
RLSSubject,
)
from dl_rls.rls import RLS


class SourceAvatarSchema(DefaultStorageSchema):
Expand Down Expand Up @@ -145,13 +149,13 @@ class JoinConditionSchema(DefaultStorageSchema):


class RLSSchema(DefaultStorageSchema):
TARGET_CLS = rls_module.RLS
TARGET_CLS = RLS

class RLSEntrySchema(DefaultStorageSchema):
TARGET_CLS = rls_module.RLSEntry
TARGET_CLS = RLSEntry

class RLSSubjectSchema(DefaultStorageSchema):
TARGET_CLS = rls_module.RLSSubject
TARGET_CLS = RLSSubject

subject_type = ma_fields.Enum(RLSSubjectType)
subject_id = ma_fields.String()
Expand Down
4 changes: 2 additions & 2 deletions lib/dl_core/dl_core_tests/db/components/test_rls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
RLSSubjectType,
)
from dl_core.fields import BIField
from dl_core.rls import (
from dl_core_tests.db.base import DefaultCoreTestClass
from dl_rls.models import (
RLSEntry,
RLSSubject,
)
from dl_core_tests.db.base import DefaultCoreTestClass


class TestRLS(DefaultCoreTestClass):
Expand Down
1 change: 1 addition & 0 deletions lib/dl_core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ datalens-model-tools = {path = "../dl_model_tools"}
datalens-task-processor = {path = "../dl_task_processor"}
datalens-dashsql = {path = "../../lib/dl_dashsql"}
datalens-cache-engine = {path = "../dl_cache_engine"}
datalens-rls = {path = "../dl_rls"}

[tool.poetry.group.tests.dependencies]
flaky = "==3.8.1"
Expand Down
Loading

0 comments on commit dc5c0a5

Please sign in to comment.