-
Notifications
You must be signed in to change notification settings - Fork 0
Сached get_base_directories #889
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: dev
Are you sure you want to change the base?
Changes from all commits
c70a8a2
6e41433
97a9824
ded6d9d
097e5f9
1ded88e
1f1e034
4ddfab9
36caf00
5803347
86b2778
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,80 @@ | ||
| """Module for dtos.""" | ||
|
|
||
| import uuid | ||
| from dataclasses import dataclass | ||
| from datetime import datetime | ||
| from typing import ClassVar | ||
|
|
||
| from adaptix.conversion import get_converter | ||
|
|
||
| from entities import Directory, DistinguishedNamePrefix | ||
|
|
||
|
|
||
| @dataclass | ||
| class DirectoryDTO: | ||
TheMihMih marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| id: int | ||
| name: str | ||
| is_system: bool | ||
| object_sid: str | ||
| object_guid: uuid.UUID | ||
| parent_id: int | None | ||
| entity_type_id: int | None | ||
| object_class: str | ||
| rdname: str | ||
| created_at: datetime | None | ||
| updated_at: datetime | None | ||
| depth: int | ||
| path: list[str] | ||
|
|
||
| search_fields: ClassVar[dict[str, str]] = { | ||
| "name": "name", | ||
| "objectguid": "objectGUID", | ||
| "objectsid": "objectSid", | ||
| } | ||
| ro_fields: ClassVar[set[str]] = { | ||
| "uid", | ||
| "whencreated", | ||
| "lastlogon", | ||
| "authtimestamp", | ||
| "objectguid", | ||
| "objectsid", | ||
| "entitytypename", | ||
| } | ||
|
|
||
| def get_dn_prefix(self) -> DistinguishedNamePrefix: | ||
| return { | ||
| "organizationalUnit": "ou", | ||
| "domain": "dc", | ||
| "container": "cn", | ||
| }.get( | ||
| self.object_class, | ||
| "cn", | ||
| ) # type: ignore | ||
|
|
||
| def get_dn(self, dn: str = "cn") -> str: | ||
| return f"{dn}={self.name}" | ||
|
|
||
| @property | ||
| def is_domain(self) -> bool: | ||
| return not self.parent_id and self.object_class == "domain" | ||
|
|
||
| @property | ||
| def host_principal(self) -> str: | ||
| return f"host/{self.name}" | ||
|
|
||
| @property | ||
| def path_dn(self) -> str: | ||
| return ",".join(reversed(self.path)) | ||
|
|
||
| @property | ||
| def relative_id(self) -> str: | ||
| """Get RID from objectSid. | ||
| Relative Identifier (RID) is the last sub-authority value of a SID. | ||
| """ | ||
| if "-" in self.object_sid: | ||
| return self.object_sid.split("-")[-1] | ||
| return "" | ||
|
|
||
|
|
||
| _directory_sqla_obj_to_dto = get_converter(Directory, DirectoryDTO) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,11 +11,13 @@ | |||||||||||||
| from sqlalchemy import exists, select | ||||||||||||||
| from sqlalchemy.ext.asyncio import AsyncSession | ||||||||||||||
|
|
||||||||||||||
| from dtos import DirectoryDTO | ||||||||||||||
TheMihMih marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
| from entities import Attribute, Directory, Group, NetworkPolicy, User | ||||||||||||||
| from ldap_protocol.ldap_schema.attribute_value_validator import ( | ||||||||||||||
| AttributeValueValidator, | ||||||||||||||
| ) | ||||||||||||||
| from ldap_protocol.ldap_schema.entity_type_dao import EntityTypeDAO | ||||||||||||||
| from ldap_protocol.utils.async_cache import base_directories_cache | ||||||||||||||
| from ldap_protocol.utils.helpers import create_object_sid, generate_domain_sid | ||||||||||||||
| from ldap_protocol.utils.queries import get_domain_object_class | ||||||||||||||
| from password_utils import PasswordUtils | ||||||||||||||
|
|
@@ -113,6 +115,7 @@ async def setup_enviroment( | |||||||||||||
| domain=domain, | ||||||||||||||
| parent=domain, | ||||||||||||||
| ) | ||||||||||||||
| base_directories_cache.clear() | ||||||||||||||
|
|
||||||||||||||
| except Exception: | ||||||||||||||
| import traceback | ||||||||||||||
|
|
@@ -124,21 +127,22 @@ async def create_dir( | |||||||||||||
| self, | ||||||||||||||
| data: dict, | ||||||||||||||
| is_system: bool, | ||||||||||||||
| domain: Directory, | ||||||||||||||
| parent: Directory | None = None, | ||||||||||||||
| domain: Directory | DirectoryDTO, | ||||||||||||||
TheMihMih marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
| parent: Directory | DirectoryDTO | None = None, | ||||||||||||||
| ) -> None: | ||||||||||||||
| """Create data recursively.""" | ||||||||||||||
| dir_ = Directory( | ||||||||||||||
| is_system=is_system, | ||||||||||||||
| object_class=data["object_class"], | ||||||||||||||
| name=data["name"], | ||||||||||||||
| parent=parent, | ||||||||||||||
| ) | ||||||||||||||
| dir_.groups = [] | ||||||||||||||
| dir_.create_path(parent, dir_.get_dn_prefix()) | ||||||||||||||
| path = parent.path if parent else [] | ||||||||||||||
| dir_.create_path(path, dir_.get_dn_prefix()) | ||||||||||||||
|
|
||||||||||||||
| self._session.add(dir_) | ||||||||||||||
| await self._session.flush() | ||||||||||||||
| dir_.parent_id = parent.id if parent else None | ||||||||||||||
|
Comment on lines
140
to
+145
|
||||||||||||||
| self._session.add(dir_) | |
| await self._session.flush() | |
| dir_.parent_id = parent.id if parent else None | |
| dir_.parent_id = parent.id if parent else None | |
| self._session.add(dir_) | |
| await self._session.flush() |
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.
Почему то в таком случае parent_id не сохраняется
TheMihMih marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| """Async cache implementation.""" | ||
|
|
||
| import time | ||
| from functools import wraps | ||
| from typing import Callable, Generic, TypeVar | ||
|
|
||
| from dtos import DirectoryDTO | ||
|
|
||
| T = TypeVar("T") | ||
| DEFAULT_CACHE_TIME = 5 * 60 # 5 minutes | ||
|
|
||
|
|
||
| class AsyncTTLCache(Generic[T]): | ||
| def __init__(self, ttl: int | None = DEFAULT_CACHE_TIME) -> None: | ||
| self._ttl = ttl | ||
| self._value: T | None = None | ||
| self._expires_at: float | None = None | ||
|
|
||
| def clear(self) -> None: | ||
| self._value = None | ||
| self._expires_at = None | ||
|
|
||
| def __call__(self, func: Callable) -> Callable: | ||
| @wraps(func) | ||
| async def wrapper(*args: tuple, **kwargs: dict) -> T: | ||
| if self._value is not None: | ||
| if not self._expires_at or self._expires_at > time.monotonic(): | ||
| return self._value | ||
| self.clear() | ||
|
|
||
| result = await func(*args, **kwargs) | ||
|
|
||
| self._value = result | ||
| self._expires_at = ( | ||
| time.monotonic() + self._ttl if self._ttl else None | ||
| ) | ||
|
|
||
| return result | ||
|
|
||
| return wrapper | ||
|
|
||
|
|
||
| base_directories_cache = AsyncTTLCache[list[DirectoryDTO]]() |
|
Collaborator
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. @rimu-stack, что скажешь насчет расположения этого модуля ?
Collaborator
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. комментарий должен был быть к dtos.py
Collaborator
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. удОлить |
Uh oh!
There was an error while loading. Please reload this page.