awacke1 commited on
Commit
9489b43
Β·
verified Β·
1 Parent(s): 12778c3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ import requests
4
+ import msal
5
+ import urllib.parse
6
+ import base64
7
+ import hashlib
8
+ import secrets
9
+
10
+ # Configuration
11
+ APPLICATION_ID_KEY = os.getenv('APPLICATION_ID_KEY')
12
+ CLIENT_SECRET_KEY = os.getenv('CLIENT_SECRET_KEY')
13
+ AUTHORITY_URL = 'https://login.microsoftonline.com/common'
14
+ REDIRECT_URI = 'https://huggingface.co/spaces/awacke1/MSGraphAPI'
15
+
16
+ # Define product to scope mapping
17
+ PRODUCT_SCOPES = {
18
+ "πŸ“§ Outlook": ['Mail.Read', 'Mail.Send', 'Calendars.ReadWrite'],
19
+ "πŸ“’ OneNote": ['Notes.Read', 'Notes.Create'],
20
+ "πŸ“Š Excel": ['Files.ReadWrite.All'],
21
+ "πŸ“„ Word": ['Files.ReadWrite.All'],
22
+ "πŸ—ƒοΈ SharePoint": ['Sites.Read.All', 'Sites.ReadWrite.All'],
23
+ "πŸ“… Teams": ['Team.ReadBasic.All', 'Channel.ReadBasic.All'],
24
+ "πŸ’¬ Viva": ['Analytics.Read'],
25
+ "πŸš€ Power Platform": ['Flow.Read.All'],
26
+ "🧠 Copilot": ['Cognitive.Read'],
27
+ "πŸ—‚οΈ OneDrive": ['Files.ReadWrite.All'],
28
+ "πŸ’‘ PowerPoint": ['Files.ReadWrite.All'],
29
+ "πŸ“š Microsoft Bookings": ['Bookings.Read.All', 'Bookings.ReadWrite.All'],
30
+ "πŸ““ Loop": ['Files.ReadWrite.All'],
31
+ "πŸ—£οΈ Translator": ['Translation.Read'],
32
+ "πŸ“‹ To Do & Planner": ['Tasks.ReadWrite'],
33
+ "πŸ”— Azure OpenAI Service": ['AzureAIServices.ReadWrite.All']
34
+ }
35
+
36
+ # Base scopes (non-reserved)
37
+ BASE_SCOPES = ['User.Read']
38
+
39
+ def generate_pkce_codes():
40
+ code_verifier = secrets.token_urlsafe(128)[:128]
41
+ code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).decode().rstrip('=')
42
+ return code_verifier, code_challenge
43
+
44
+ def get_msal_app():
45
+ return msal.PublicClientApplication(
46
+ client_id=APPLICATION_ID_KEY,
47
+ authority=AUTHORITY_URL
48
+ )
49
+
50
+ def get_access_token(code, code_verifier):
51
+ client_instance = get_msal_app()
52
+
53
+ try:
54
+ result = client_instance.acquire_token_by_authorization_code(
55
+ code=code,
56
+ scopes=st.session_state.get('request_scopes', BASE_SCOPES),
57
+ redirect_uri=REDIRECT_URI,
58
+ code_verifier=code_verifier
59
+ )
60
+
61
+ if 'access_token' in result:
62
+ return result['access_token']
63
+ else:
64
+ error_description = result.get('error_description', 'No error description provided')
65
+ raise Exception(f"Error acquiring token: {error_description}")
66
+ except Exception as e:
67
+ st.error(f"Exception in get_access_token: {str(e)}")
68
+ raise
69
+
70
+ def main():
71
+ st.title("πŸ¦„ MS Graph API with AI & Cloud Integration for M365")
72
+
73
+ st.sidebar.title("πŸ“ M365 Products")
74
+ st.sidebar.write("Select products to integrate:")
75
+
76
+ selected_products = {}
77
+ for product in PRODUCT_SCOPES.keys():
78
+ selected = st.sidebar.checkbox(product)
79
+ if selected:
80
+ selected_products[product] = True
81
+
82
+ # Dynamically build scopes based on selected products
83
+ request_scopes = BASE_SCOPES.copy()
84
+ for product in selected_products:
85
+ request_scopes.extend(PRODUCT_SCOPES[product])
86
+ request_scopes = list(set(request_scopes)) # Remove duplicates
87
+
88
+ # Store request scopes in session state
89
+ st.session_state['request_scopes'] = request_scopes
90
+
91
+ if 'access_token' not in st.session_state:
92
+ if 'code_verifier' not in st.session_state:
93
+ code_verifier, code_challenge = generate_pkce_codes()
94
+ st.session_state['code_verifier'] = code_verifier
95
+ else:
96
+ code_verifier = st.session_state['code_verifier']
97
+ code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).decode().rstrip('=')
98
+
99
+ client_instance = get_msal_app()
100
+ auth_url = client_instance.get_authorization_request_url(
101
+ scopes=request_scopes,
102
+ redirect_uri=REDIRECT_URI,
103
+ code_challenge=code_challenge,
104
+ code_challenge_method="S256"
105
+ )
106
+ st.write('πŸ‘‹ Please [click here]({}) to log in and authorize the app.'.format(auth_url))
107
+
108
+ query_params = st.query_params
109
+ if 'code' in query_params:
110
+ code = query_params.get('code')
111
+ st.write('πŸ”‘ Authorization Code Obtained:', code[:10] + '...')
112
+
113
+ try:
114
+ access_token = get_access_token(code, code_verifier)
115
+ st.session_state['access_token'] = access_token
116
+ st.success("Access token acquired successfully!")
117
+ st.rerun()
118
+ except Exception as e:
119
+ st.error(f"Error acquiring access token: {str(e)}")
120
+ st.stop()
121
+ else:
122
+ access_token = st.session_state['access_token']
123
+
124
+ user_info = get_user_info(access_token)
125
+ if user_info:
126
+ st.sidebar.write(f"πŸ‘‹ Hello, {user_info.get('displayName', 'User')}!")
127
+
128
+ if selected_products:
129
+ st.header("🧩 M365 Product Integrations")
130
+ for product in selected_products:
131
+ st.subheader(f"{product}")
132
+ handle_product_integration(access_token, product)
133
+ else:
134
+ st.write("No products selected. Please select products from the sidebar.")
135
+
136
+ def get_user_info(access_token):
137
+ headers = {'Authorization': f'Bearer {access_token}'}
138
+ response = requests.get('https://graph.microsoft.com/v1.0/me', headers=headers)
139
+ if response.status_code == 200:
140
+ return response.json()
141
+ else:
142
+ st.error('Failed to fetch user info.')
143
+ return None
144
+
145
+ def handle_product_integration(access_token, product):
146
+ st.write(f"Integrating {product}...")
147
+ # Implement product-specific API calls here
148
+
149
+ if __name__ == "__main__":
150
+ main()