Ejemplo n.º 1
0
def test_graph_client_uses_same_session():
    """
    Test graph client is a singleton class and uses the same session
    """
    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential)

    client2 = GraphClient(credential=credential)
    assert client is client2
def test_graph_client_with_custom_settings():
    """
    Test that the graph client works with user provided configuration
    """
    credential = _CustomTokenCredential()
    client = GraphClient(api_version=APIVersion.beta, credential=credential)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me'
    )
    assert response.status_code == 200
def test_graph_client_with_default_middleware():
    """
    Test that a graph client uses default middleware if none are provided
    """
    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me'
    )
    assert response.status_code == 200
def test_graph_client_with_user_provided_session():
    """
    Test that the graph client works with a user provided session object
    """

    session = Session()
    credential = _CustomTokenCredential()
    client = GraphClient(session=session, credential=credential)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me'
    )
    assert response.status_code == 200
Ejemplo n.º 5
0
def test_graph_client_builds_graph_urls():
    """
    Test that the graph client builds full urls if supplied with partial
    """
    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential)
    graph_url = client.graph_session.base_url + '/me'

    responses.add(responses.GET, graph_url, status=200)

    client.get('/me', headers={})
    assert graph_url == responses.calls[0].request.url
Ejemplo n.º 6
0
def test_does_not_build_graph_urls_for_full_urls():
    """
    Test that the graph client builds full urls if supplied with partial
    """
    other_url = 'https://microsoft.com/'
    responses.add(responses.GET, other_url, status=200)

    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential)
    client.get(other_url, headers={})
    request_url = responses.calls[0].request.url
    assert other_url == request_url
def test_graph_client_adds_context_to_request():
    """
    Test the graph client adds a context object to a request
    """
    credential = _CustomTokenCredential()
    scopes = ['User.Read.All']
    client = GraphClient(credential=credential)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me',
        scopes=scopes
    )
    assert response.status_code == 200
    assert hasattr(response.request, 'context')
def test_graph_client_with_custom_middleware():
    """
    Test client factory works with user provided middleware
    """
    credential = _CustomTokenCredential()
    middleware = [
        AuthorizationHandler(credential),
    ]
    client = GraphClient(middleware=middleware)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me'
    )
    assert response.status_code == 200
def test_graph_client_picks_options_from_kwargs():
    """
    Test the graph client picks middleware options from kwargs and sets them in the context
    """
    credential = _CustomTokenCredential()
    scopes = ['User.Read.All']
    client = GraphClient(credential=credential)
    response = client.get(
        'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0/me',
        scopes=scopes
    )
    assert response.status_code == 200
    assert 'scopes' in response.request.context.middleware_control.keys()
    assert response.request.context.middleware_control['scopes'] == scopes
Ejemplo n.º 10
0
def client_with_custom_middleware():
    """Sample client with a custom middleware chain"""
    middleware = [
        CustomAuthorizationHandler(),
        MyCustomMiddleware(),
    ]

    my_client = GraphClient(credential=browser_credential,
                            middleware=middleware)
    result = my_client.get(
        'https://graph.microsoft.com/v1.0/users',
        params={
            '$select': 'displayName',
            '$top': '10'
        },
    )
    pprint(result.json())
Ejemplo n.º 11
0
def client_with_custom_settings_sample():
    """
    Sample client that makes requests against the beta api on a specified cloud endpoint
    """
    my_client = GraphClient(
        credential=browser_credential,
        api_version=APIVersion.beta,
        cloud=NationalClouds.Germany,
    )
    result = my_client.get(
        '/users',
        params={
            '$select': 'displayName',
            '$top': '10'
        },
    )
    pprint(result.json())
Ejemplo n.º 12
0
def delete_current_user_app_registrations(contains: str) -> None:
    if not contains:
        raise Exception("Contains string must be set to a valid string")

    cred = AzCliMsGraphAuth()
    client = GraphClient(credential=cred)

    result = client.get("/me")
    result = client.get(f'/users/{result.json()["id"]}/ownedObjects')

    my_apps = []

    for x in result.json()["value"]:
        if (x["@odata.type"] == "#microsoft.graph.application"
                and contains in x["displayName"]):
            my_apps.append((x["displayName"], x["id"]))

    for (name, id) in my_apps:
        print("Deleting: %s (%s)" % (name, id))
        result = client.delete(f"/applications/{id}")
        if not result.ok:
            print("Failed to delete: %s (%s) due to : %s" %
                  (name, id, result.reason))

        result = client.get(f"/directory/deletedItems/{id}")
        if result.ok:
            deleted_app = result.json()
            if deleted_app["id"] == id:
                result = client.delete("/directory/deleteditems/%s" % id)
                if result.ok:
                    print("Permanently deleted: %s (%s)" % (name, id))
                else:
                    print("Failed to permanently delete: %s (%s) due to : %s" %
                          (name, id, result.reason))
Ejemplo n.º 13
0
class AzUsers(object):
    def __init__(self, credential):
        self.graph_client = GraphClient(credential=credential)

    def get_azure_user_id(self, netid):
        username = '******'.format(netid, settings.USERNAME_EMAIL_HOST)
        response = self.graph_client.get('/users/' + username)
        response.raise_for_status()
        return response.json()["id"]
Ejemplo n.º 14
0
def test_graph_client_with_custom_configuration():
    """
    Test creating a graph client with custom middleware works as expected
    """
    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential,
                         api_version=APIVersion.beta,
                         cloud=NationalClouds.China)

    assert client.graph_session.base_url == NationalClouds.China + '/' + APIVersion.beta
Ejemplo n.º 15
0
def test_graph_client_with_default_middleware():
    """
    Test creating a graph client with default middleware works as expected
    """
    credential = _CustomTokenCredential()
    client = GraphClient(credential=credential)

    assert isinstance(client.graph_session, Session)
    assert isinstance(client.graph_session.get_adapter('https://'),
                      HTTPAdapter)
    assert client.graph_session.base_url == NationalClouds.Global + '/' + APIVersion.v1
Ejemplo n.º 16
0
 def __init__(self, auth_method: str, mailbox: str, client_id: str,
              client_secret: str, username: str, password: str,
              tenant_id: str, token_file: str):
     token_path = Path(token_file)
     credential = _generate_credential(auth_method,
                                       client_id=client_id,
                                       client_secret=client_secret,
                                       username=username,
                                       password=password,
                                       tenant_id=tenant_id,
                                       token_path=token_path)
     scopes = ['Mail.ReadWrite']
     # Detect if mailbox is shared
     if mailbox and username != mailbox:
         scopes = ['Mail.ReadWrite.Shared']
     if not isinstance(credential, ClientSecretCredential):
         auth_record = credential.authenticate(scopes=scopes)
         _cache_auth_record(auth_record, token_path)
     self._client = GraphClient(credential=credential)
     self.mailbox_name = mailbox
Ejemplo n.º 17
0
def test_graph_client_with_custom_middleware():
    """
    Test creating a graph client with custom middleware works as expected
    """
    credential = _CustomTokenCredential()
    middleware = [
        AuthorizationHandler(credential),
    ]
    client = GraphClient(middleware=middleware)

    assert isinstance(client.graph_session, Session)
    assert isinstance(client.graph_session.get_adapter('https://'),
                      HTTPAdapter)
    assert client.graph_session.base_url == NationalClouds.Global + '/' + APIVersion.v1
Ejemplo n.º 18
0
class MSGraphConnection(MailboxConnection):
    def __init__(self, auth_method: str, mailbox: str, client_id: str,
                 client_secret: str, username: str, password: str,
                 tenant_id: str, token_file: str):
        token_path = Path(token_file)
        credential = _generate_credential(auth_method,
                                          client_id=client_id,
                                          client_secret=client_secret,
                                          username=username,
                                          password=password,
                                          tenant_id=tenant_id,
                                          token_path=token_path)
        scopes = ['Mail.ReadWrite']
        # Detect if mailbox is shared
        if mailbox and username != mailbox:
            scopes = ['Mail.ReadWrite.Shared']
        if not isinstance(credential, ClientSecretCredential):
            auth_record = credential.authenticate(scopes=scopes)
            _cache_auth_record(auth_record, token_path)
        self._client = GraphClient(credential=credential)
        self.mailbox_name = mailbox

    def create_folder(self, folder_name: str):
        sub_url = ''
        path_parts = folder_name.split('/')
        if len(path_parts) > 1:  # Folder is a subFolder
            parent_folder_id = None
            for folder in path_parts[:-1]:
                parent_folder_id = self._find_folder_id_with_parent(
                    folder, parent_folder_id)
            sub_url = f'/{parent_folder_id}/childFolders'
            folder_name = path_parts[-1]

        request_body = {'displayName': folder_name}
        request_url = f'/users/{self.mailbox_name}/mailFolders{sub_url}'
        resp = self._client.post(request_url, json=request_body)
        if resp.status_code == 409:
            logger.debug(f'Folder {folder_name} already exists, '
                         f'skipping creation')
        elif resp.status_code == 201:
            logger.debug(f'Created folder {folder_name}')
        else:
            logger.warning(f'Unknown response '
                           f'{resp.status_code} {resp.json()}')

    def fetch_messages(self, folder_name: str, **kwargs) -> List[str]:
        """ Returns a list of message UIDs in the specified folder """
        folder_id = self._find_folder_id_from_folder_path(folder_name)
        batch_size = kwargs.get('batch_size', 10)
        url = f'/users/{self.mailbox_name}/mailFolders/' \
              f'{folder_id}/messages?$select=id&$top={batch_size}'
        result = self._client.get(url)
        emails = result.json()['value']
        return [email['id'] for email in emails]

    def mark_message_read(self, message_id: str):
        """Marks a message as read"""
        url = f'/users/{self.mailbox_name}/messages/{message_id}'
        resp = self._client.patch(url, json={"isRead": "true"})
        if resp.status_code != 200:
            raise RuntimeWarning(f"Failed to mark message read"
                                 f"{resp.status_code}: {resp.json()}")

    def fetch_message(self, message_id: str):
        url = f'/users/{self.mailbox_name}/messages/{message_id}/$value'
        result = self._client.get(url)
        self.mark_message_read(message_id)
        return result.text

    def delete_message(self, message_id: str):
        url = f'/users/{self.mailbox_name}/messages/{message_id}'
        resp = self._client.delete(url)
        if resp.status_code != 204:
            raise RuntimeWarning(f"Failed to delete message "
                                 f"{resp.status_code}: {resp.json()}")

    def move_message(self, message_id: str, folder_name: str):
        folder_id = self._find_folder_id_from_folder_path(folder_name)
        request_body = {'destinationId': folder_id}
        url = f'/users/{self.mailbox_name}/messages/{message_id}/move'
        resp = self._client.post(url, json=request_body)
        if resp.status_code != 201:
            raise RuntimeWarning(f"Failed to move message "
                                 f"{resp.status_code}: {resp.json()}")

    def keepalive(self):
        # Not needed
        pass

    def watch(self, check_callback, check_timeout):
        """ Checks the mailbox for new messages every n seconds"""
        while True:
            sleep(check_timeout)
            check_callback(self)

    @lru_cache(maxsize=10)
    def _find_folder_id_from_folder_path(self, folder_name: str) -> str:
        path_parts = folder_name.split('/')
        parent_folder_id = None
        if len(path_parts) > 1:
            for folder in path_parts[:-1]:
                folder_id = self._find_folder_id_with_parent(
                    folder, parent_folder_id)
                parent_folder_id = folder_id
            return self._find_folder_id_with_parent(path_parts[-1],
                                                    parent_folder_id)
        else:
            return self._find_folder_id_with_parent(folder_name, None)

    def _find_folder_id_with_parent(self, folder_name: str,
                                    parent_folder_id: Optional[str]):
        sub_url = ''
        if parent_folder_id is not None:
            sub_url = f'/{parent_folder_id}/childFolders'
        url = f'/users/{self.mailbox_name}/mailFolders{sub_url}'
        folders_resp = self._client.get(url)
        folders = folders_resp.json()['value']
        matched_folders = [
            folder for folder in folders
            if folder['displayName'] == folder_name
        ]
        if len(matched_folders) == 0:
            raise RuntimeError(f"folder {folder_name} not found")
        selected_folder = matched_folders[0]
        return selected_folder['id']
Ejemplo n.º 19
0
def client_with_custom_session_sample():
    """Sample client with a custom Session object"""
    session = Session()
    my_client = GraphClient(credential=browser_credential, session=session)
    result = my_client.get('/me')
    pprint(result.json())
Ejemplo n.º 20
0
# ------------------------------------
#pylint: disable=undefined-variable
"""Demonstrates using the GraphClient to make HTTP Requests to Microsoft Graph"""
import json
from pprint import pprint

# This sample uses InteractiveBrowserCredential only for demonstration.
# Any azure-identity TokenCredential class will work the same.
from azure.identity import InteractiveBrowserCredential
from requests import Session

from msgraph.core import APIVersion, GraphClient, NationalClouds

scopes = ['user.read']
browser_credential = InteractiveBrowserCredential(client_id='YOUR_CLIENT_ID')
client = GraphClient(credential=browser_credential)


def get_sample():
    """Sample HTTP GET request using the GraphClient"""
    result = client.get('/me/messages', scopes=['mail.read'])
    pprint(result.json())


def post_sample():
    """Sample HTTP POST request using the GraphClient"""
    body = {
        'message': {
            'subject':
            'Python SDK Meet for lunch?',
            'body': {
Ejemplo n.º 21
0
 def __init__(self, credential):
     self.graph_client = GraphClient(credential=credential)