-
Notifications
You must be signed in to change notification settings - Fork 5
Feature: ipv4 and missing service #221
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
Merged
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
ec8e14b
Feature: base client service
1yam 16d5c43
Feature: CRN service for client
1yam 4676c39
Feature: DNS service for client
1yam 283b6df
Feature: Scheduler service for client
1yam 20c6dab
Feature: Port_forwarder service for client
1yam ac3e7a3
Feature: new settings `DNS_API` `CRN_URL_UPDATE` `CRN_LIST_URL` `CRN_…
1yam b072b3a
feature: new Exception for custom service
1yam f6da369
fix: parse_obj is deprecated need to use model_validate
1yam 2640abf
feat: utils func sanitize_url
1yam cccfbfb
feature: Utils client service
1yam c3978bc
fix: lint issue http_port_forwarder.py
1yam dcba7ee
feature: Services types
1yam 76ff159
Feature: AlephHttpClient load default service and allow new method `r…
1yam d1d931b
Feature: AuthenticatedAlephHttpClient load default service and allow …
1yam 2fc0931
feat: new unit test for client services
1yam b45816d
fix: import
1yam 87b23a8
fix: domains service not existing yet
1yam 754759f
fix: unit test
1yam 9667106
fix: remove domains for units test service
1yam b4eb1d2
refactor: No __init__ needed
1yam f2c5a8f
Refactor: renaming class / change folder struct
1yam 0a7bd47
fix: port forwarder import
1yam 475e60f
fix: linting format import
1yam 4fb796d
Feature: client.dns.get_public_dns_by_host
1yam 7a1c107
fix: this functions not used / wrong place
1yam 750a1d2
fix: linting FMT issue
1yam 36532f5
feat: use new filter on dns api ?item_hash=
1yam 4b4ebe9
fix: get_scheduler_node become get_nodes since we already on client.s…
1yam 64d91f1
fix: rename get_ports to get_address_ports, get_port to get_ports
1yam 9649260
fix: we should also ensure that the mlessage is not being removed whe…
1yam a275c89
fix: new unit test, some name change
1yam 1561982
fix: remove unit test for now will fix them
1yam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
190 changes: 190 additions & 0 deletions
190
src/aleph/sdk/client/services/authenticated_port_forwarder.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
from typing import TYPE_CHECKING, Optional, Tuple | ||
|
||
from aleph_message.models import AggregateMessage, ItemHash | ||
from aleph_message.status import MessageStatus | ||
|
||
from aleph.sdk.client.services.base import AggregateConfig | ||
from aleph.sdk.client.services.port_forwarder import PortForwarder | ||
from aleph.sdk.exceptions import MessageNotProcessed, NotAuthorize | ||
from aleph.sdk.types import AllForwarders, Ports | ||
from aleph.sdk.utils import safe_getattr | ||
|
||
if TYPE_CHECKING: | ||
from aleph.sdk.client.abstract import AuthenticatedAlephClient | ||
|
||
|
||
class AuthenticatedPortForwarder(PortForwarder): | ||
""" | ||
Authenticated Port Forwarder services with create and update capabilities | ||
""" | ||
|
||
def __init__(self, client: "AuthenticatedAlephClient"): | ||
super().__init__(client) | ||
|
||
async def _verify_status_processed_and_ownership( | ||
self, item_hash: ItemHash | ||
) -> Tuple[AggregateMessage, MessageStatus]: | ||
""" | ||
Verify that the message is well processed (and not rejected / pending), | ||
This also verify the ownership of the message | ||
""" | ||
message: AggregateMessage | ||
status: MessageStatus | ||
message, status = await self._client.get_message( | ||
item_hash=item_hash, | ||
with_status=True, | ||
) | ||
|
||
# We ensure message is not Rejected (Might not be processed yet) | ||
if status not in [MessageStatus.PROCESSED, MessageStatus.PENDING]: | ||
raise MessageNotProcessed(item_hash=item_hash, status=status) | ||
|
||
message_content = safe_getattr(message, "content") | ||
address = safe_getattr(message_content, "address") | ||
|
||
if ( | ||
not hasattr(self._client, "account") | ||
or address != self._client.account.get_address() | ||
): | ||
current_address = ( | ||
self._client.account.get_address() | ||
if hasattr(self._client, "account") | ||
else "unknown" | ||
) | ||
raise NotAuthorize( | ||
item_hash=item_hash, | ||
target_address=address, | ||
current_address=current_address, | ||
) | ||
return message, status | ||
|
||
async def get_address_ports( | ||
self, address: Optional[str] = None | ||
) -> AggregateConfig[AllForwarders]: | ||
""" | ||
Get all port forwarding configurations for an address | ||
|
||
Args: | ||
address: The address to fetch configurations for. | ||
If None, uses the authenticated client's account address. | ||
|
||
Returns: | ||
Port forwarding configurations | ||
""" | ||
if address is None: | ||
if not hasattr(self._client, "account") or not self._client.account: | ||
raise ValueError("No account provided and client is not authenticated") | ||
address = self._client.account.get_address() | ||
|
||
return await super().get_address_ports(address=address) | ||
|
||
async def get_ports( | ||
self, item_hash: ItemHash = None, address: Optional[str] = None | ||
) -> Optional[Ports]: | ||
""" | ||
Get port forwarding configuration for a specific item hash | ||
|
||
Args: | ||
address: The address to fetch configurations for. | ||
If None, uses the authenticated client's account address. | ||
item_hash: The hash of the item to get configuration for | ||
|
||
Returns: | ||
Port configuration if found, otherwise empty Ports object | ||
""" | ||
if address is None: | ||
if not hasattr(self._client, "account") or not self._client.account: | ||
raise ValueError("No account provided and client is not authenticated") | ||
address = self._client.account.get_address() | ||
|
||
if item_hash is None: | ||
raise ValueError("item_hash must be provided") | ||
|
||
return await super().get_ports(address=address, item_hash=item_hash) | ||
|
||
async def create_ports( | ||
self, item_hash: ItemHash, ports: Ports | ||
) -> Tuple[AggregateMessage, MessageStatus]: | ||
""" | ||
Create a new port forwarding configuration for an item hash | ||
|
||
Args: | ||
item_hash: The hash of the item (instance/program/IPFS website) | ||
ports: Dictionary mapping port numbers to PortFlags | ||
|
||
Returns: | ||
Dictionary with the result of the operation | ||
""" | ||
if not hasattr(self._client, "account") or not self._client.account: | ||
raise ValueError("An account is required for this operation") | ||
|
||
# Pre Check | ||
# _, _ = await self._verify_status_processed_and_ownership(item_hash=item_hash) | ||
|
||
content = {str(item_hash): ports.model_dump()} | ||
|
||
# Check if create_aggregate exists on the client | ||
return await self._client.create_aggregate( # type: ignore | ||
key=self.aggregate_key, content=content | ||
) | ||
|
||
async def update_ports( | ||
self, item_hash: ItemHash, ports: Ports | ||
) -> Tuple[AggregateMessage, MessageStatus]: | ||
""" | ||
Update an existing port forwarding configuration for an item hash | ||
|
||
Args: | ||
item_hash: The hash of the item (instance/program/IPFS website) | ||
ports: Dictionary mapping port numbers to PortFlags | ||
|
||
Returns: | ||
Dictionary with the result of the operation | ||
""" | ||
if not hasattr(self._client, "account") or not self._client.account: | ||
raise ValueError("An account is required for this operation") | ||
|
||
# Pre Check | ||
# _, _ = await self._verify_status_processed_and_ownership(item_hash=item_hash) | ||
|
||
content = {} | ||
|
||
content[str(item_hash)] = ports.model_dump() | ||
|
||
message, status = await self._client.create_aggregate( # type: ignore | ||
key=self.aggregate_key, content=content | ||
) | ||
|
||
return message, status | ||
|
||
async def delete_ports( | ||
self, item_hash: ItemHash | ||
) -> Tuple[AggregateMessage, MessageStatus]: | ||
""" | ||
Delete port forwarding configuration for an item hash | ||
|
||
Args: | ||
item_hash: The hash of the item (instance/program/IPFS website) to delete configuration for | ||
|
||
Returns: | ||
Dictionary with the result of the operation | ||
""" | ||
if not hasattr(self._client, "account") or not self._client.account: | ||
raise ValueError("An account is required for this operation") | ||
|
||
# Pre Check | ||
# _, _ = await self._verify_status_processed_and_ownership(item_hash=item_hash) | ||
|
||
# Get the Port Config of the item_hash | ||
port: Optional[Ports] = await self.get_ports(item_hash=item_hash) | ||
if not port: | ||
raise | ||
|
||
content = {} | ||
content[str(item_hash)] = port.model_dump() | ||
|
||
# Create a new aggregate with the updated content | ||
message, status = await self._client.create_aggregate( # type: ignore | ||
key=self.aggregate_key, content=content | ||
) | ||
return message, status |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from abc import ABC | ||
from typing import TYPE_CHECKING, Generic, List, Optional, Type, TypeVar | ||
|
||
from pydantic import BaseModel | ||
|
||
if TYPE_CHECKING: | ||
from aleph.sdk.client.http import AlephHttpClient | ||
|
||
|
||
T = TypeVar("T", bound=BaseModel) | ||
|
||
|
||
class AggregateConfig(BaseModel, Generic[T]): | ||
""" | ||
A generic container for "aggregate" data of type T. | ||
- `data` will be either None or a list of T-instances. | ||
""" | ||
|
||
data: Optional[List[T]] = None | ||
|
||
|
||
class BaseService(ABC, Generic[T]): | ||
aggregate_key: str | ||
model_cls: Type[T] | ||
|
||
def __init__(self, client: "AlephHttpClient"): | ||
self._client = client | ||
self.model_cls: Type[T] | ||
|
||
async def get_config(self, address: str): | ||
|
||
aggregate_data = await self._client.fetch_aggregate( | ||
address=address, key=self.aggregate_key | ||
) | ||
|
||
if aggregate_data: | ||
model_instance = self.model_cls.model_validate(aggregate_data) | ||
config = AggregateConfig[T](data=[model_instance]) | ||
else: | ||
config = AggregateConfig[T](data=None) | ||
|
||
return config |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.