Skip to content

Commit

Permalink
Merge pull request #7907 from OpenMined/domain_envs
Browse files Browse the repository at this point in the history
Listing Domain packages, fix request repr to show node types and owners, add owner to domain list
  • Loading branch information
koenvanderveen authored Jul 14, 2023
2 parents f212d13 + 1e51697 commit 4a8a904
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 7 deletions.
3 changes: 3 additions & 0 deletions packages/syft/src/syft/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@ def __init__(

self.post_init()

def get_env(self) -> str:
return self.api.services.metadata.get_env()

def post_init(self) -> None:
if self.metadata is None:
self._fetch_node_metadata(self.credentials)
Expand Down
21 changes: 19 additions & 2 deletions packages/syft/src/syft/node/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import hashlib
from multiprocessing import current_process
import os
import subprocess # nosec
import traceback
from typing import Any
from typing import Callable
Expand Down Expand Up @@ -52,6 +53,7 @@
from ..service.data_subject.data_subject_service import DataSubjectService
from ..service.dataset.dataset_service import DatasetService
from ..service.enclave.enclave_service import EnclaveService
from ..service.metadata.metadata_service import MetadataService
from ..service.metadata.node_metadata import NodeMetadata
from ..service.network.network_service import NetworkService
from ..service.notification.notification_service import NotificationService
Expand Down Expand Up @@ -147,6 +149,13 @@ def get_dev_mode() -> bool:
return str_to_bool(get_env("DEV_MODE", "False"))


def get_venv_packages() -> str:
res = subprocess.getoutput(
"pip list --format=freeze",
)
return res


dev_mode = get_dev_mode()

signing_key_env = get_private_key_env()
Expand All @@ -160,6 +169,7 @@ def get_dev_mode() -> bool:
class Node(AbstractNode):
signing_key: Optional[SyftSigningKey]
required_signed_calls: bool = True
packages: str

def __init__(
self,
Expand Down Expand Up @@ -187,6 +197,7 @@ def __init__(
if id is None:
id = UID()
self.id = id
self.packages = get_venv_packages()

self.signing_key = None
if signing_key_env is not None:
Expand Down Expand Up @@ -217,6 +228,7 @@ def __init__(
DataSubjectMemberService,
ProjectService,
EnclaveService,
MetadataService,
]
if services is None
else services
Expand Down Expand Up @@ -253,7 +265,7 @@ def __init__(
self.node_type = node_type

self.post_init()
self.create_initial_settings()
self.create_initial_settings(admin_email=root_email)
if not (self.is_subprocess or self.processes == 0):
self.init_queue_manager(queue_config=queue_config)

Expand Down Expand Up @@ -462,6 +474,7 @@ def _construct_services(self):
DataSubjectMemberService,
ProjectService,
EnclaveService,
MetadataService,
]

if OBLV:
Expand Down Expand Up @@ -508,6 +521,7 @@ def metadata(self) -> NodeMetadata:
on_board = False
description = ""
signup_enabled = False
admin_email = ""

settings_stash = SettingsStash(store=self.document_store)
settings = settings_stash.get_all(self.signing_key.verify_key)
Expand All @@ -519,6 +533,7 @@ def metadata(self) -> NodeMetadata:
on_board = settings_data.on_board
description = settings_data.description
signup_enabled = settings_data.signup_enabled
admin_email = settings_data.admin_email

return NodeMetadata(
name=name,
Expand All @@ -533,6 +548,7 @@ def metadata(self) -> NodeMetadata:
on_board=on_board,
node_type=self.node_type.value,
signup_enabled=signup_enabled,
admin_email=admin_email,
)

@property
Expand Down Expand Up @@ -707,7 +723,7 @@ def get_unauthed_context(
) -> NodeServiceContext:
return UnauthedServiceContext(node=self, login_credentials=login_credentials)

def create_initial_settings(self) -> Optional[NodeSettings]:
def create_initial_settings(self, admin_email: str) -> Optional[NodeSettings]:
if self.name is None:
self.name = random_name()
try:
Expand All @@ -725,6 +741,7 @@ def create_initial_settings(self) -> Optional[NodeSettings]:
name=self.name,
deployed_on=datetime.now().date().strftime("%m/%d/%Y"),
signup_enabled=flags.CAN_REGISTER,
admin_email=admin_email,
)
result = settings_stash.set(
credentials=self.signing_key.verify_key, settings=new_settings
Expand Down
33 changes: 33 additions & 0 deletions packages/syft/src/syft/service/metadata/metadata_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# third party

# relative
from ...serde.serializable import serializable
from ...store.document_store import DocumentStore
from ...util.telemetry import instrument
from ..context import AuthedServiceContext
from ..service import AbstractService
from ..service import service_method
from ..user.user_roles import GUEST_ROLE_LEVEL


@instrument
@serializable()
class MetadataService(AbstractService):
def __init__(self, store: DocumentStore) -> None:
self.store = store

@service_method(
path="metadata.get_metadata", name="get_metadata", roles=GUEST_ROLE_LEVEL
)
def get_metadata(self, context: AuthedServiceContext):
return context.node.metadata

# @service_method(path="metadata.get_admin", name="get_admin", roles=GUEST_ROLE_LEVEL)
# def get_admin(self, context: AuthedServiceContext):
# user_service = context.node.get_service("userservice")
# admin_user = user_service.get_all(context=context)[0]
# return admin_user

@service_method(path="metadata.get_env", name="get_env", roles=GUEST_ROLE_LEVEL)
def get_env(self, context: AuthedServiceContext):
return context.node.packages
3 changes: 3 additions & 0 deletions packages/syft/src/syft/service/metadata/node_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class NodeMetadataUpdate(SyftObject):
highest_object_version: Optional[int]
lowest_object_version: Optional[int]
syft_version: Optional[str]
admin_email: Optional[str]


@serializable()
Expand All @@ -75,6 +76,7 @@ class NodeMetadata(SyftObject):
on_board: bool = False
description: str = "Text"
signup_enabled: bool
admin_email: str

def check_version(self, client_version: str) -> bool:
return check_version(
Expand All @@ -99,6 +101,7 @@ class NodeMetadataJSON(BaseModel, StorableObjectType):
on_board: bool = False
description: str = "My cool domain"
signup_enabled: bool
admin_email: str

def check_version(self, client_version: str) -> bool:
return check_version(
Expand Down
2 changes: 1 addition & 1 deletion packages/syft/src/syft/service/network/network_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,5 +530,5 @@ def node_route_to_http_connection(
@transform(NodeMetadata, NodePeer)
def metadata_to_peer() -> List[Callable]:
return [
keep(["id", "name", "verify_key", "node_type"]),
keep(["id", "name", "verify_key", "node_type", "admin_email"]),
]
3 changes: 2 additions & 1 deletion packages/syft/src/syft/service/network/node_peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class NodePeer(SyftObject):

__attr_searchable__ = ["name", "node_type"]
__attr_unique__ = ["verify_key"]
__repr_attrs__ = ["name", "node_type"]
__repr_attrs__ = ["name", "node_type", "admin_email"]

id: Optional[UID]
name: str
Expand All @@ -40,6 +40,7 @@ class NodePeer(SyftObject):
vpn_auth_key: Optional[str] = None
node_routes: List[NodeRouteType] = []
node_type: NodeType
admin_email: str

def update_routes(self, new_routes: List[NodeRoute]) -> None:
add_routes = []
Expand Down
7 changes: 5 additions & 2 deletions packages/syft/src/syft/service/request/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ def _repr_html_(self) -> Any:
self.node_uid,
self.syft_client_verify_key,
)

metadata = api.services.metadata.get_metadata()
admin_email = metadata.admin_email
node_name = api.node_name.capitalize() if api.node_name is not None else ""
return f"""
<style>
.syft-request {{color: {SURFACE[options.color_theme]};}}
Expand All @@ -201,7 +203,8 @@ def _repr_html_(self) -> Any:
{updated_at_line}
<p><strong>Changes: </strong> {str_changes}</p>
<p><strong>Status: </strong>{self.status}</p>
<p><strong>Sent to Domain </strong>{api.node_name}</p>
<p><strong>Requested on: </strong> {node_name} of type <strong> \
{metadata.node_type.value.capitalize()}</strong> owned by {admin_email}</p>
</div>
"""

Expand Down
10 changes: 9 additions & 1 deletion packages/syft/src/syft/service/settings/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ class NodeSettingsUpdate(PartialSyftObject):
description: str
on_board: bool
signup_enabled: bool
admin_email: str


@serializable()
class NodeSettings(SyftObject):
__canonical_name__ = "NodeSettings"
__version__ = SYFT_OBJECT_VERSION_1
__repr_attrs__ = ["name", "organization", "deployed_on", "signup_enabled"]
__repr_attrs__ = [
"name",
"organization",
"deployed_on",
"signup_enabled",
"admin_email",
]

name: str = "Node"
deployed_on: str
organization: str = "OpenMined"
on_board: bool = True
description: str = "Text"
signup_enabled: bool
admin_email: str
19 changes: 19 additions & 0 deletions packages/syft/src/syft/service/user/user_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from ..service import SERVICE_TO_TYPES
from ..service import TYPE_TO_SERVICE
from ..service import service_method
from ..settings.settings_stash import SettingsStash
from .user import User
from .user import UserCreate
from .user import UserPrivateKey
Expand Down Expand Up @@ -175,6 +176,15 @@ def search(

return results

# @service_method(path="user.get_admin", name="get_admin", roles=GUEST_ROLE_LEVEL)
# def get_admin(self, context: AuthedServiceContext) -> UserView:
# result = self.stash.admin_user()
# if result.is_ok():
# user = result.ok()
# if user:
# return user
# return SyftError(message=str(result.err()))

@service_method(
path="user.get_current_user", name="get_current_user", roles=GUEST_ROLE_LEVEL
)
Expand Down Expand Up @@ -270,6 +280,15 @@ def update(
return SyftError(message=error_msg)

user = result.ok()
if user.role == ServiceRole.ADMIN:
settings_stash = SettingsStash(store=self.store)
settings = settings_stash.get_all(context.credentials)
if settings.is_ok() and len(settings.ok()) > 0:
settings_data = settings.ok()[0]
settings_data.admin_email = user.email
settings_stash.update(
credentials=context.credentials, settings=settings_data
)

return user.to(UserView)

Expand Down
5 changes: 5 additions & 0 deletions packages/syft/src/syft/service/user/user_stash.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def set(
def admin_verify_key(self):
return Ok(self.partition.root_verify_key)

def admin_user(self):
return self.get_by_role(
credentials=self.admin_verify_key().ok(), role=ServiceRole.ADMIN
)

def get_by_uid(
self, credentials: SyftVerifyKey, uid: UID
) -> Result[Optional[User], str]:
Expand Down
20 changes: 20 additions & 0 deletions packages/syft/src/syft/util/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# stdlib
from typing import Dict
import venv

# relative
from ..types.syft_object import SYFT_OBJECT_VERSION_1
from ..types.syft_object import SyftObject


class Env(SyftObject):
__canonical_name__ = "Env"
__version__ = SYFT_OBJECT_VERSION_1
packages_dict: Dict[str, str]

@property
def packages(self):
return [(k, v) for k, v in self.packages_dict.items()]

def create_local_env(self):
venv.EnvBuilder()
2 changes: 2 additions & 0 deletions packages/syft/tests/syft/settings/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def settings(worker, faker) -> NodeSettings:
description=faker.text(),
deployed_on=datetime.now().date().strftime("%m/%d/%Y"),
signup_enabled=False,
admin_email="[email protected]",
)


Expand All @@ -52,6 +53,7 @@ def metadata_json(faker) -> NodeMetadataJSON:
lowest_object_version=LOWEST_SYFT_OBJECT_VERSION,
syft_version=__version__,
signup_enabled=False,
admin_email="[email protected]",
)


Expand Down
2 changes: 2 additions & 0 deletions packages/syft/tests/syft/settings/settings_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ def test_settings_allow_guest_registration(
lowest_object_version=2,
syft_version=syft.__version__,
signup_enabled=False,
admin_email="[email protected]",
)

with mock.patch(
Expand Down Expand Up @@ -307,6 +308,7 @@ def get_mock_client(faker, root_client, role):
lowest_object_version=2,
syft_version=syft.__version__,
signup_enabled=False,
admin_email="[email protected]",
)

with mock.patch(
Expand Down

0 comments on commit 4a8a904

Please sign in to comment.