From 8399c8ccd46846d7eb02afa379f8740e4cd8a19d Mon Sep 17 00:00:00 2001 From: Shimao Zheng Date: Fri, 20 Sep 2024 20:58:18 -0700 Subject: [PATCH] A lightweight user management kit definitions (#84) * A lightweight user management kit definitions --- flux_sdk/flux_core/data_models.py | 7 ++ flux_sdk/user_management/api/base_api.py | 35 --------- .../{api => capabilities}/__init__.py | 0 .../user_lifecycle_management/__init__.py | 0 .../user_lifecycle_management/interface.py | 40 +++++++++++ .../user_management/data_models/base_types.py | 11 --- .../data_models/data_models.py | 71 +++++++++++++++++++ 7 files changed, 118 insertions(+), 46 deletions(-) delete mode 100644 flux_sdk/user_management/api/base_api.py rename flux_sdk/user_management/{api => capabilities}/__init__.py (100%) create mode 100644 flux_sdk/user_management/capabilities/user_lifecycle_management/__init__.py create mode 100644 flux_sdk/user_management/capabilities/user_lifecycle_management/interface.py delete mode 100644 flux_sdk/user_management/data_models/base_types.py create mode 100644 flux_sdk/user_management/data_models/data_models.py diff --git a/flux_sdk/flux_core/data_models.py b/flux_sdk/flux_core/data_models.py index 3267a0b0..929d4734 100644 --- a/flux_sdk/flux_core/data_models.py +++ b/flux_sdk/flux_core/data_models.py @@ -271,4 +271,11 @@ class TerminationType(Enum): OFFER_DECLINE = 5 RESCIND = 6 RENEGE = 7 + + +class AppDisconnectedError(Exception): + """ + This exception is raised when the app is disconnected from the third-party system. + """ + pass \ No newline at end of file diff --git a/flux_sdk/user_management/api/base_api.py b/flux_sdk/user_management/api/base_api.py deleted file mode 100644 index 82fc7934..00000000 --- a/flux_sdk/user_management/api/base_api.py +++ /dev/null @@ -1,35 +0,0 @@ -from abc import ABC -from typing import List, Optional - -from flux_sdk.user_management.data_models.base_types import User - - -class UserManagementInterface(ABC): - def get_users(self) -> List[User]: - """ - :return: list of all users present in the app. - """ - raise NotImplementedError - - def create_user_if_not_exist(self, user: User, force_reset_password: bool = False) -> User: - """ - :param user: the user to be created/invited - :param bool force_reset_password: whether we force reset the password on user creation - :return: User object if actual user get created/invited - """ - raise NotImplementedError - - def delete_user_if_exist(self, user: User) -> Optional[bool]: - """ - :param user: the user to be deleted/suspended - :return: return True if deletion/suspension is successful. - """ - raise NotImplementedError - - def get_user_by_id(self, id: str) -> Optional[User]: - """ - user object fetched from spoke if present, None otherwise. - :param str id: unique identifier of the user - :rtype User: the user fetched from third party - """ - raise NotImplementedError \ No newline at end of file diff --git a/flux_sdk/user_management/api/__init__.py b/flux_sdk/user_management/capabilities/__init__.py similarity index 100% rename from flux_sdk/user_management/api/__init__.py rename to flux_sdk/user_management/capabilities/__init__.py diff --git a/flux_sdk/user_management/capabilities/user_lifecycle_management/__init__.py b/flux_sdk/user_management/capabilities/user_lifecycle_management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/flux_sdk/user_management/capabilities/user_lifecycle_management/interface.py b/flux_sdk/user_management/capabilities/user_lifecycle_management/interface.py new file mode 100644 index 00000000..10c4636f --- /dev/null +++ b/flux_sdk/user_management/capabilities/user_lifecycle_management/interface.py @@ -0,0 +1,40 @@ +from abc import ABC, abstractmethod + +from flux_sdk.user_management.data_models.data_models import ( + GetOrganizationsRequest, + GetOrganizationsResponse, + GetUsersRequest, + GetUsersResponse, +) + + +class UserLifecycleManagement(ABC): + """ + This class represents the "user_lifecycle_management" capability. + This capability is used to manage the lifecycle of users in the third-party system with supports including: + - Getting user's organizations from the third-party system + - Getting users from the third-party system + """ + + @abstractmethod + def get_users(self, request: GetUsersRequest) -> GetUsersResponse: + """ + A function that get users from the third-party system. + + Use this hook fetch users from the third-party system so that they can be matched with employees in Rippling. + :param request: The request to get users from the third-party system. This request may contain the + organizations to get users from. + :return: The response containing the users from the third-party system. + """ + + + @abstractmethod + def get_organizations(self, request: GetOrganizationsRequest) -> GetOrganizationsResponse: + """ + A function that get organizations from the third-party system. + + Use this hook to fetch organizations from the third-party system so that the organization information can be + used to get users from the third-party system. + :param request: The request to get organizations from the third-party system. + :return: The response containing the organizations from the third-party system. + """ diff --git a/flux_sdk/user_management/data_models/base_types.py b/flux_sdk/user_management/data_models/base_types.py deleted file mode 100644 index 0bf2df1e..00000000 --- a/flux_sdk/user_management/data_models/base_types.py +++ /dev/null @@ -1,11 +0,0 @@ -class User: - id: str - first_name: str - last_name: str - primary_email: str - - def __init__(self, id: str, first_name: str, last_name: str, primary_email: str) -> None: - self.id = id - self.first_name = first_name - self.last_name = last_name - self.primary_email = primary_email \ No newline at end of file diff --git a/flux_sdk/user_management/data_models/data_models.py b/flux_sdk/user_management/data_models/data_models.py new file mode 100644 index 00000000..7873691f --- /dev/null +++ b/flux_sdk/user_management/data_models/data_models.py @@ -0,0 +1,71 @@ +from dataclasses import dataclass +from typing import Optional + + +@dataclass(kw_only=True) +class Organization: + """ + This represents an organization in the third party system. + An organization is used to group users in the third party system. + Different third party systems may have different names of organizations: + Github calls it "Organization", while Google Workspace calls it "Domain". + """ + + id: str + """The unique identifier of the organization in the third party system.""" + + name: Optional[str] = None + """The name of the organization in the third party system.""" + + +@dataclass(kw_only=True) +class User: + """This represents a user in the third party system.""" + + id: Optional[str] = None + """The unique identifier of the user in the third party system. + This field is required when getting users from the third party system.""" + + first_name: Optional[str] = None + """The first name of the user.""" + + middle_name: Optional[str] = None + """The middle name of the user.""" + + last_name: Optional[str] = None + """The last name of the user.""" + + email: Optional[str] = None + """The email address of the user.""" + + +@dataclass(kw_only=True) +class GetUsersRequest: + """This represents a request to get users from the third party system.""" + + organizations: Optional[list[Organization]] = None + """The organizations to get users from. If this field is not provided, + the users from all organizations should be returned.""" + + +@dataclass(kw_only=True) +class GetUsersResponse: + """This represents a response containing the users from the third party system.""" + + users: list[User] + """The users from the third party system.""" + + +@dataclass(kw_only=True) +class GetOrganizationsRequest: + """This represents a request to get organizations from the third party system.""" + + pass + + +@dataclass(kw_only=True) +class GetOrganizationsResponse: + """This represents a response containing the organizations from the third party system.""" + + organizations: list[Organization] + """The organizations from the third party system.""" \ No newline at end of file