nlbone 0.7.24__tar.gz → 0.7.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nlbone-0.7.24 → nlbone-0.7.25}/PKG-INFO +1 -1
- {nlbone-0.7.24 → nlbone-0.7.25}/pyproject.toml +1 -1
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/domain/models.py +31 -1
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/auth.py +8 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/exceptions.py +9 -4
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/middleware/authentication.py +5 -1
- {nlbone-0.7.24 → nlbone-0.7.25}/.gitignore +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/LICENSE +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/README.md +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/auth/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/auth/auth_service.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/auth/keycloak.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/auth/token_provider.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/cache/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/cache/async_redis.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/cache/memory.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/cache/pubsub_listener.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/cache/redis.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/audit.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/base.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/engine.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/query_builder.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/repository.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/schema.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/types.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/postgres/uow.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/redis/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/db/redis/client.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/pricing/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/pricing/pricing_service.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/uploadchi/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/uploadchi/uploadchi.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/uploadchi/uploadchi_async.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/i18n/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/i18n/engine.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/i18n/loaders.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/i18n/locales/fa.json +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/messaging/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/messaging/event_bus.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/messaging/rabbitmq.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/outbox/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/outbox/outbox_consumer.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/outbox/outbox_repo.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/percolation/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/percolation/connection.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/repositories/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/snowflake.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/ticketing/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/ticketing/client.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/config/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/config/logging.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/config/settings.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/container.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/base_worker.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/bus.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/di.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/registry.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/services/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/application/use_case.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/domain/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/domain/base.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/auth.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/cache.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/event_bus.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/files.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/outbox.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/repository.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/translation.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/core/ports/uow.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/assembler.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/default_field_rules/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/default_field_rules/image_field_rules.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/field_registry.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/resolver.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/async_auth.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/client_credential.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/db.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/dependencies/uow.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/exception_handlers.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/middleware/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/middleware/access_log.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/middleware/add_request_context.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/pagination/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/pagination/offset_base.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/routers.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/schema/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/schema/adaptive_schema.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/schema/base_response_model.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/schemas.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/cli/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/cli/crypto.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/cli/init_db.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/cli/main.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/cli/ticket.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/jobs/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/jobs/dispatch_outbox.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/jobs/sync_tokens.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/types.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/__init__.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/cache.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/cache_keys.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/cache_registry.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/context.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/crypto.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/flatten_sqlalchemy_result.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/http.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/normalize_mobile.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/redactor.py +0 -0
- {nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/utils/time.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
import uuid
|
|
3
|
+
from dataclasses import dataclass
|
|
3
4
|
from datetime import datetime, timedelta, timezone
|
|
4
|
-
from typing import Any, Dict, Optional
|
|
5
|
+
from typing import Any, Dict, Optional, List
|
|
5
6
|
|
|
6
7
|
from sqlalchemy import JSON, DateTime, Index, Integer, String, Text
|
|
7
8
|
from sqlalchemy import JSON as SA_JSON
|
|
@@ -22,6 +23,35 @@ except Exception:
|
|
|
22
23
|
UUIDType = String(36)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@dataclass
|
|
27
|
+
class CurrentUserData:
|
|
28
|
+
active: bool
|
|
29
|
+
id: int
|
|
30
|
+
email: str
|
|
31
|
+
exp: int
|
|
32
|
+
iat: int
|
|
33
|
+
preferred_username: str
|
|
34
|
+
name: str
|
|
35
|
+
phone_number: str
|
|
36
|
+
verifications: List[str]
|
|
37
|
+
allowed_permissions: List[str]
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_dict(cls, data: dict) -> "CurrentUserData":
|
|
41
|
+
return cls(
|
|
42
|
+
active=data.get("active"),
|
|
43
|
+
id=data.get("sub"),
|
|
44
|
+
email=data.get("email"),
|
|
45
|
+
exp=data.get("exp"),
|
|
46
|
+
iat=data.get("iat"),
|
|
47
|
+
preferred_username=data.get("preferred_username"),
|
|
48
|
+
name=data.get("name"),
|
|
49
|
+
phone_number=data.get("phone_number"),
|
|
50
|
+
verifications=data.get("verifications", []),
|
|
51
|
+
allowed_permissions=data.get("allowed_permissions", []),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
25
55
|
class AuditLog(Base):
|
|
26
56
|
__tablename__ = "audit_logs"
|
|
27
57
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
|
|
3
|
+
from nlbone.core.domain.models import CurrentUserData
|
|
3
4
|
from nlbone.adapters.auth import KeycloakAuthService
|
|
4
5
|
from nlbone.adapters.auth.keycloak import get_auth_service
|
|
5
6
|
from nlbone.config.settings import get_settings
|
|
@@ -21,6 +22,13 @@ def current_user_id() -> int:
|
|
|
21
22
|
raise UnauthorizedException()
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
def current_user() -> CurrentUserData:
|
|
26
|
+
user = current_request().state.user
|
|
27
|
+
if user.id is None:
|
|
28
|
+
raise UnauthorizedException()
|
|
29
|
+
return user
|
|
30
|
+
|
|
31
|
+
|
|
24
32
|
def current_client_id() -> str:
|
|
25
33
|
request = current_request()
|
|
26
34
|
if client_id := KeycloakAuthService().get_client_id(request.state.token):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Iterable
|
|
1
|
+
from typing import Any, Iterable, Dict, List
|
|
2
2
|
|
|
3
3
|
from fastapi import HTTPException, status
|
|
4
4
|
|
|
@@ -83,9 +83,14 @@ class UnprocessableEntityException(BaseHttpException):
|
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
class LogicalValidationException(
|
|
87
|
-
def __init__(self, detail: str, loc: Iterable[Any] | None = None, type_: str = "logical_error"
|
|
88
|
-
|
|
86
|
+
class LogicalValidationException(HTTPException):
|
|
87
|
+
def __init__(self, detail: str = None, loc: Iterable[Any] | None = None, type_: str = "logical_error",
|
|
88
|
+
errors: List[Dict[str, Any]] = None):
|
|
89
|
+
self.errors = errors
|
|
90
|
+
if errors:
|
|
91
|
+
super().__init__(detail=errors, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,)
|
|
92
|
+
else:
|
|
93
|
+
super().__init__(detail=_errors(loc, detail, type_), status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
|
|
89
94
|
|
|
90
95
|
|
|
91
96
|
class GoneException(BaseHttpException):
|
|
@@ -3,6 +3,7 @@ from typing import Callable, Optional, Union
|
|
|
3
3
|
from fastapi import Request
|
|
4
4
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
5
5
|
|
|
6
|
+
from nlbone.core.domain.models import CurrentUserData
|
|
6
7
|
from nlbone.adapters.auth.auth_service import AuthService
|
|
7
8
|
from nlbone.config.settings import get_settings
|
|
8
9
|
|
|
@@ -53,7 +54,8 @@ def authenticate_admin_user(request, auth_service):
|
|
|
53
54
|
|
|
54
55
|
def authenticate_user(request):
|
|
55
56
|
token = (
|
|
56
|
-
|
|
57
|
+
request.cookies.get("access_token") or request.cookies.get("j_token") or request.headers.get(
|
|
58
|
+
"Authorization")
|
|
57
59
|
)
|
|
58
60
|
if request.headers.get("Authorization"):
|
|
59
61
|
scheme, token = request.headers.get("Authorization").split(" ", 1)
|
|
@@ -64,6 +66,7 @@ def authenticate_user(request):
|
|
|
64
66
|
service: BaseAuthService = AuthService()
|
|
65
67
|
data = service.verify_token(token)
|
|
66
68
|
if data:
|
|
69
|
+
request.state.user = CurrentUserData.from_dict(data)
|
|
67
70
|
request.state.user_id = data.get("sub")
|
|
68
71
|
except Exception:
|
|
69
72
|
pass
|
|
@@ -78,6 +81,7 @@ class AuthenticationMiddleware(BaseHTTPMiddleware):
|
|
|
78
81
|
request.state.client_id = None
|
|
79
82
|
request.state.user_id = None
|
|
80
83
|
request.state.token = None
|
|
84
|
+
request.state.user = None
|
|
81
85
|
if request.headers.get("X-Client-Id") and request.headers.get("X-Api-Key"):
|
|
82
86
|
if request.headers.get("X-Api-Key") == get_settings().PRICING_API_SECRET:
|
|
83
87
|
request.state.client_id = request.headers.get("X-Client-Id")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/adapters/http_clients/uploadchi/uploadchi_async.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nlbone-0.7.24 → nlbone-0.7.25}/src/nlbone/interfaces/api/additional_filed/field_registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|