# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/routes/account.ipynb.

# %% auto 0
__all__ = ['Account_GET_Error', 'get_available_data_providers', 'get_accounts', 'get_oauth_accounts', 'Account_NoMatch',
           'get_account_by_id', 'get_oauth_account_by_id', 'get_account_config', 'get_oauth_account_config',
           'Account_CRUD_Error', 'Account_CreateParams_Error', 'generate_create_account_body', 'create_account',
           'delete_account', 'generate_create_oauth_account_body', 'create_oauth_account', 'delete_oauth_account',
           'Account_Config_Error', 'update_account_config', 'update_oauth_account_config', 'update_account_name',
           'update_oauth_account_name', 'get_account_accesslist', 'get_oauth_account_accesslist', 'ShareAccount',
           'ShareAccount_V1_AccessLevel', 'ShareAccount_AccessLevel', 'Account_Share_Error',
           'Account_AlreadyShared_Error', 'share_account', 'share_oauth_account', 'share_account_v1']

# %% ../../nbs/routes/account.ipynb 3
from abc import abstractmethod
import httpx

import domolibrary.client.get_data as gd
import domolibrary.client.ResponseGetData as rgd
import domolibrary.client.DomoAuth as dmda
import domolibrary.client.DomoError as dmde
from domolibrary.client.DomoEntity import DomoEnum

# %% ../../nbs/routes/account.ipynb 8
class Account_GET_Error(dmde.RouteError):
    def __init__(
        self, res: rgd.ResponseGetData, account_id: int = None, message: str = None
    ):
        super().__init__(res=res, message=message, entity_id=account_id)

@gd.route_function
async def get_available_data_providers(
    auth: dmda.DomoAuth,
    debug_api: bool = False,
    debug_num_stacks_to_drop=1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
):
    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/providers"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if not res.is_success:
        raise Account_GET_Error(res=res)
    return res



@gd.route_function
async def get_accounts(
    auth: dmda.DomoAuth,
    debug_api: bool = False,
    debug_num_stacks_to_drop=1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:
    """retrieve a list of all the accounts the user has read access to.  Note users with "Manage all accounts" will retrieve all account objects"""

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if not res.is_success:
        raise Account_GET_Error(res=res)
    return res


@gd.route_function
async def get_oauth_accounts(
    auth: dmda.DomoAuth,
    debug_api: bool = False,
    debug_num_stacks_to_drop=1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/templates/user/extended"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if not res.is_success:
        raise Account_GET_Error(res=res)
    return res

# %% ../../nbs/routes/account.ipynb 13
class Account_NoMatch(dmde.RouteError):
    def __init__(
        self,
        res: rgd.ResponseGetData,
        account_id=None,
        message=f"Account not found --  has it been shared with the user?",
    ):

        super().__init__(
            message=message,
            res=res,
            entity_id=account_id,
        )


@gd.route_function
async def get_account_by_id(
    auth: dmda.DomoAuth,
    account_id: int,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
    is_unmask: bool = False
) -> rgd.ResponseGetData:
    """retrieves metadata about an account"""

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        session=session,
        timeout=20,  # occasionally this API has a long response time
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        params = {"unmask" : is_unmask}
    )

    if not res.is_success and (
        res.response == "Forbidden" or res.response == "Not Found"
    ):
        raise Account_NoMatch(account_id=account_id, res=res)

    if not res.is_success:
        raise Account_GET_Error(res=res)

    return res


@gd.route_function
async def get_oauth_account_by_id(
    auth: dmda.DomoAuth,
    account_id: int,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
    return_raw: bool = False,
) -> rgd.ResponseGetData:
    """
    retrieves all_oauth_accounts and filters to the selected one.
    There does not appear to be an API implementation of retrieving one OAuth Account
    """

    res = await get_oauth_accounts(
        auth=auth,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
        parent_class=parent_class,
        session=session,
    )

    if return_raw:
        return res

    res.response = next((obj for obj in res.response if obj["id"] == account_id), None)

    if not res.response:
        raise Account_NoMatch(res=res, account_id=account_id)

    return res

# %% ../../nbs/routes/account.ipynb 18
# class Account_NoConfigRetrieved(dmde.RouteError):
#     def __init__(
#         self,
#         res: rgd.ResponseGetData,
#         account_id=None,
#         message: str = f"account did not return a config.  update `DomoAccount_Config` if it uses OAuth, otherwise this is probably an error",
#     ):
#         super().__init__(message=message, res=res, entity_id=account_id)


@gd.route_function
async def get_account_config(
    auth: dmda.DomoAuth,
    account_id: int,
    data_provider_type: str = None,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
    is_unmask :bool = True # unmasks encrypted values IF config allows
) -> rgd.ResponseGetData:

    if not data_provider_type:
        res = await get_account_by_id(
            auth = auth,
            account_id=account_id,
            debug_api=debug_api,
            session=session,
            parent_class=parent_class,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
        )

        data_provider_type = res.response["dataProviderType"]

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/providers/{data_provider_type}/account/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        session=session,
        params = {"unmask" : is_unmask},
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if return_raw:
        return res

    if not res.is_success and (
        res.response == "Forbidden" or res.response == "Not Found"
    ):
        raise Account_NoMatch(account_id=account_id, res=res)

    if not res.is_success:
        raise Account_GET_Error(res=res)

    res.response.update(
        {
            "_search_metadata": {
                "account_id": account_id,
                "data_provider_type": data_provider_type,
            }
        }
    )

    return res


@gd.route_function
async def get_oauth_account_config(
    auth: dmda.DomoAuth,
    account_id: int,
    data_provider_type: str,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:
    """retrieves metadata about an account"""

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/providers/{data_provider_type}/template/{account_id}?unmask=true"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        session=session,
        timeout=20,  # occasionally this API has a long response time
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
    )

    if return_raw:
        return res

    if not res.is_success and (
        res.response == "Forbidden" or res.response == "Not Found"
    ):
        raise Account_NoMatch(account_id=account_id, res=res)

    if not res.is_success:
        raise Account_GET_Error(res=res)

    res.response.update(
        {
            "_search_metadata": {
                "account_id": account_id,
                "data_provider_type": data_provider_type,
            }
        }
    )

    return res

# %% ../../nbs/routes/account.ipynb 23
class Account_CRUD_Error(dmde.RouteError):
    def __init__(
        self,
        res: rgd.ResponseGetData,
        account_id=None,
        message: str = None,
    ):
        message = message or f"unable to update account - {res.response}"

        super().__init__(message=message, entity_id=account_id, res=res)


class Account_CreateParams_Error(dmde.DomoError):
    def __init__(
        self,
        message: str,
    ):
        super().__init__(message=message)


def generate_create_account_body(account_name, data_provider_type, config_body):
    return {
        "displayName": account_name,
        "dataProviderType": data_provider_type,
        "name": account_name,
        "configurations": config_body,
    }

import json
@gd.route_function
async def create_account(
    auth: dmda.DomoAuth,
    account_name: str = None,
    data_provider_type: str = None,
    config_body: dict = None, # properly formatted AccountConfig 
    payload: dict = None, # final payload
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    parent_class: str = None,
    debug_num_stacks_to_drop=1,
) -> rgd.ResponseGetData:

    
    payload = payload or generate_create_account_body(
        account_name=account_name,
        data_provider_type=data_provider_type,
        config_body=config_body,
    )
    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="POST",
        body=payload,
        debug_api=debug_api,
        session=session,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            res=res,
            account_id=account_name,
            message=f"error creating account - {res.response}",
        )

    return res


@gd.route_function
async def delete_account(
    auth: dmda.DomoAuth,
    account_id: str,
    debug_api: bool = False,
    debug_num_stacks_to_drop=1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="DELETE",
        debug_api=debug_api,
        session=session,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            account_id=account_id,
            res=res,
            message=f"unable to delete account",
        )

    return res


def generate_create_oauth_account_body(
    account_name, data_provider_type, origin, config
):
    return {
        "name": account_name,
        "displayName": account_name,
        "dataProviderType": data_provider_type,
        "origin": origin,
        "configurations": config,
    }


@gd.route_function
async def create_oauth_account(
    auth: dmda.DomoAuth,
    account_name: str = None,
    data_provider_type: str = None,
    origin: str = "OAUTH_CONFIGURATION",
    config: dict = None,
    create_body: dict = None,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    parent_class: str = None,
    debug_num_stacks_to_drop=1,
) -> rgd.ResponseGetData:

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/templates"

    if not create_body and not (
        account_name and data_provider_type and origin and config
    ):
        raise Account_CreateParams_Error(
            message="if not passing complete create_body must pass account_name,data_provider_type, origin, and config"
        )

    create_body = create_body or generate_create_oauth_account_body(
        account_name=account_name,
        data_provider_type=data_provider_type,
        origin=origin,
        config=config,
    )

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="POST",
        body=create_body,
        debug_api=debug_api,
        session=session,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            res=res,
            account_id=create_body.get("displayName"),
            message=f"error creating account - {res.response}",
        )

    return res


@gd.route_function
async def delete_oauth_account(
    auth: dmda.DomoAuth,
    account_id: str,
    debug_api: bool = False,
    debug_num_stacks_to_drop=1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/templates/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="DELETE",
        debug_api=debug_api,
        session=session,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            account_id=account_id, res=res, message="error deleting account"
        )

    res.response = f"deleted account {account_id}"
    return res

# %% ../../nbs/routes/account.ipynb 27
class Account_Config_Error(dmde.RouteError):
    def __init__(
        self,
        res: rgd.ResponseGetData,
        account_id=None,
        message: str = None,
    ):
        message = message or f"unable to update account - {res.response}"

        super().__init__(message=message, entity_id=account_id, res=res)


@gd.route_function
async def update_account_config(
    auth: dmda.DomoAuth,
    account_id: int,
    config_body: dict,
    data_provider_type: str = None,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:

    # get the data_provider_type, which is necessare for updating the config setting
    if not data_provider_type:
        res = await get_account_by_id(
            auth=auth,
            account_id=account_id,
            debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=parent_class,
            session=session,
        )
        data_provider_type = res.response.get("dataProviderType")

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/providers/{data_provider_type}/account/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=config_body,
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if res.status == 400 and res.response == "Bad Request":
        raise Account_Config_Error(
            res=res,
            message=f"error updating config | use debug_api = True {res.response}",
            account_id=account_id,
        )

    if not res.is_success:
        raise Account_CRUD_Error(res=res, account_id=account_id)

    return res

@gd.route_function
async def update_oauth_account_config(
    auth: dmda.DomoAuth,
    account_id: int,
    config_body: dict,
    data_provider_type: str = None,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:

    # get the data_provider_type, which is necessare for updating the config setting
    if not data_provider_type:
        res = await get_oauth_account_by_id(
            auth=auth,
            account_id=account_id,
            # debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=parent_class,
            session=session,
        )
        data_provider_type = res.response.get("dataProviderType")

    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/providers/{data_provider_type}/template/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=config_body,
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if res.status == 400 and res.response == "Bad Request":
        raise Account_Config_Error(
            res=res,
            message=f"error updating config | use debug_api = True {res.response}",
            account_id=account_id,
        )

    if not res.is_success:
        raise Account_CRUD_Error(res=res, account_id=account_id)

    return res



# %% ../../nbs/routes/account.ipynb 31
@gd.route_function
async def update_account_name(
    auth: dmda.DomoAuth,
    account_id: int,
    account_name: str,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:
    url = (
        f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/{account_id}/name"
    )

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=account_name,
        content_type="text/plain",
        debug_api=debug_api,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        session=session,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            res=res,
            account_id=account_id,
            message="error updating account_name",
        )

    return res


@gd.route_function
async def update_oauth_account_name(
    auth: dmda.DomoAuth,
    account_id: int,
    account_name: str,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
) -> rgd.ResponseGetData:
    url = (
        f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/templates/{account_id}/name"
    )

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=account_name,
        content_type="text/plain",
        debug_api=debug_api,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        session=session,
    )

    if not res.is_success:
        raise Account_CRUD_Error(
            res=res,
            account_id=account_id,
            message="error updating account_name",
        )

    return res
    

# %% ../../nbs/routes/account.ipynb 36
@gd.route_function
async def get_account_accesslist(
    auth: dmda.DomoAuth,
    account_id: str,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
    return_raw: bool = False
):
    url = (
        f"https://{auth.domo_instance}.domo.com/api/data/v2/accounts/share/{account_id}"
    )

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if not res.is_success:
        raise Account_GET_Error(
            res=res,
            account_id=account_id,
            message=f"unable to get accesslist - {res.response}",
        )

    if return_raw:
        return res
    
    res.response = res.response['list']

    return res


@gd.route_function
async def get_oauth_account_accesslist(
    auth: dmda.DomoAuth,
    account_id: str,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
):
    url = f"https://{auth.domo_instance}.domo.com/api/data/v2/accounts/templates/share/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="GET",
        debug_api=debug_api,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        session=session,
    )

    if not res.is_success:
        raise Account_GET_Error(
            res=res,
            account_id=account_id,
            message=f"unable to get accesslist - {res.response}",
        )

    if return_raw:
        return res
    
    res.response = res.response['list']

    return res

# %% ../../nbs/routes/account.ipynb 39
class ShareAccount(DomoEnum):
    @abstractmethod
    def generate_payload(self):
        pass


class ShareAccount_V1_AccessLevel(ShareAccount):
    CAN_VIEW = "READ"
    CAN_EDIT = "WRITE"
    OWNER = "OWNER"
    default = "READ"

    def generate_payload(self, user_id: int, **kwargs):

        return {"type": "USER", "id": int(user_id), "permissions": [self.value]}


class ShareAccount_AccessLevel(ShareAccount):
    """Enum that correlates to the v2 API which should also be the current version"""

    CAN_VIEW = "CAN_VIEW"
    CAN_EDIT = "CAN_EDIT"
    CAN_SHARE = "CAN_SHARE"
    OWNER = "OWNER"
    NO_ACCESS = "NONE"
    default = "CAN_VIEW"

    
    def generate_payload(self, user_id: int = None, group_id: int = None, **kwargs):
        if user_id:
            return {"type": "USER", "id": str(user_id), "accessLevel": self.value}

        if group_id:
            return {"type": "GROUP", "id": str(group_id), "accessLevel": self.value}

# %% ../../nbs/routes/account.ipynb 41
class Account_Share_Error(dmde.RouteError):
    def __init__(
        self, res: rgd.ResponseGetData, account_id: int = None, message: str = None
    ):
        super().__init__(res=res, message=message, entity_id=account_id)


class Account_AlreadyShared_Error(dmde.DomoError):
    def __init__(
        self, res: rgd.ResponseGetData, account_id: int = None, message: str = None
    ):
        super().__init__(res=res, message=message, entity_id=account_id)


@gd.route_function
async def share_account(
    auth: dmda.DomoAuth,
    account_id: str,
    share_payload: dict,
    debug_api: bool = False,
    parent_class: str = None,
    debug_num_stacks_to_drop=1,
    session: httpx.AsyncClient = None,
):
    """for simplicity, this is the v2 api which should have been deployed to all Domo instances as of DP24"""

    url = (
        f"https://{auth.domo_instance}.domo.com/api/data/v2/accounts/share/{account_id}"
    )

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=share_payload,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        debug_api=debug_api,
        session=session,
    )

    if res.status == 500 and res.response == "Internal Server Error":
        raise Account_AlreadyShared_Error(
            account_id=account_id,
            messagae=f"{res.response} - User may already have access to account",
            res=res,
        )

    if not res.is_success:
        raise Account_Share_Error(
            account_id=account_id,
            res=res,
        )

    return res


ShareAccount_AccessLevel.share = staticmethod(share_account)


@gd.route_function
async def share_oauth_account(
    auth: dmda.DomoAuth,
    account_id: str,
    share_payload: dict,
    debug_api: bool = False,
    parent_class: str = None,
    debug_num_stacks_to_drop=1,
    session: httpx.AsyncClient = None,
):
    url = f"https://{auth.domo_instance}.domo.com/api/data/v2/accounts/templates/share/{account_id}"

    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=share_payload,
        parent_class=parent_class,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        debug_api=debug_api,
        session=session,
    )

    # does not appear to throw 500 error if user already has access
    # if res.status == 500 and res.response == "Internal Server Error":
    #     raise Account_AlreadyShared_Error(
    #         account_id=account_id,
    #         messagae=f"{res.response} - User may already have access to account",
    #         res=res,
    #     )

    if not res.is_success:
        raise Account_Share_Error(
            account_id=account_id,
            res=res,
        )

    return res

# %% ../../nbs/routes/account.ipynb 43
# v1 may have been deprecated.  used to be tied to group beta
@gd.route_function
async def share_account_v1(
    auth: dmda.DomoAuth,
    account_id: str,
    share_payload: dict,
    debug_api: bool = False,
    debug_num_stacks_to_drop: int = 1,
    parent_class: str = None,
    session: httpx.AsyncClient = None,
):
    """V1 API allows sharing with users ONLY.  it does not support sharing with groups and has a more limited set of share rights (owner or read) see ShareAccount_V1_AccessLevel vs v2"""
    
    url = f"https://{auth.domo_instance}.domo.com/api/data/v1/accounts/{account_id}/share"
    
    res = await gd.get_data(
        auth=auth,
        url=url,
        method="PUT",
        body=share_payload,
        num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=parent_class,
        debug_api=debug_api,
        session=session,
    )

    if res.status == 500 and res.response == "Internal Server Error":
        raise Account_AlreadyShared_Error(
            account_id=account_id,
            messagae=f"{res.response} - User may already have access to account",
            res=res,
        )

    if not res.is_success:
        raise Account_Share_Error(
            account_id=account_id,
            res=res,
        )

    return res

ShareAccount_V1_AccessLevel.share = staticmethod(share_account_v1)
