broadfield-dev commited on
Commit
2a5b992
Β·
verified Β·
1 Parent(s): d6c9e2a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -50
app.py CHANGED
@@ -5,6 +5,7 @@ import base64
5
  import io
6
  import json
7
  import logging
 
8
  from cryptography.hazmat.primitives import serialization
9
  from cryptography.hazmat.primitives.asymmetric import rsa
10
 
@@ -18,6 +19,10 @@ logger = logging.getLogger(__name__)
18
  CREATOR_SPACE_ID = "broadfield-dev/KeyLock-Auth-Creator"
19
  SERVER_SPACE_ID = "broadfield-dev/KeyLock-Auth-Server"
20
 
 
 
 
 
21
  # Construct URLs for linking in documentation
22
  BASE_HF_URL = "https://huggingface.co/spaces/"
23
  CREATOR_URL = f"{BASE_HF_URL}{CREATOR_SPACE_ID}"
@@ -30,23 +35,23 @@ SERVER_APP_PY_URL = f"{SERVER_URL}/blob/main/app.py"
30
  # ==============================================================================
31
 
32
  def get_creator_endpoints():
33
- """Calls the Creator space to get its list of supported endpoints."""
34
- status = f"Fetching endpoint list from {CREATOR_SPACE_ID}..."
35
- yield gr.Dropdown(choices=[], value=None, label="⏳ Fetching..."), status
36
  try:
37
- client = Client(src=CREATOR_SPACE_ID)
38
- json_string = client.predict(api_name="/get_endpoints")
39
 
40
- endpoints = json.loads(json_string)
41
  endpoint_names = [e['name'] for e in endpoints]
42
 
43
  status = f"βœ… Success! Found {len(endpoint_names)} endpoints."
44
  # Return the full list to the state, and the updated dropdown
45
- yield gr.Dropdown(choices=endpoint_names, value=endpoint_names[0] if endpoint_names else None, label="Target Service"), status
46
  except Exception as e:
47
- logger.error(f"Failed to get endpoints from creator: {e}", exc_info=True)
48
- status = f"❌ Error: Could not fetch endpoints from Creator space. Check if it's running. Details: {e}"
49
- yield gr.Dropdown(choices=[], value=None, label="Error fetching services"), status
50
 
51
  def create_image_via_api(service_name: str, secret_data: str, available_endpoints: list):
52
  """Calls the Creator Space API to generate an encrypted image for a selected service."""
@@ -56,7 +61,6 @@ def create_image_via_api(service_name: str, secret_data: str, available_endpoint
56
  status = f"Looking up public key for '{service_name}'..."
57
  yield None, None, status
58
 
59
- # Find the public key from the list we fetched earlier
60
  public_key = next((e['public_key'] for e in available_endpoints if e['name'] == service_name), None)
61
  if not public_key:
62
  raise gr.Error(f"Could not find public key for '{service_name}' in the fetched configuration.")
@@ -120,7 +124,7 @@ theme = gr.themes.Base(
120
  neutral_hue=gr.themes.colors.slate,
121
  font=(gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"),
122
  ).set(
123
- body_background_fill="#F1F5F9", # Light grey
124
  panel_background_fill="white",
125
  block_background_fill="white",
126
  block_border_width="1px",
@@ -130,7 +134,6 @@ theme = gr.themes.Base(
130
  )
131
 
132
  with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
133
- # This State component will hold the list of dicts fetched from the Creator
134
  endpoints_state = gr.State([])
135
 
136
  gr.Markdown("# πŸ”‘ KeyLock Operations Dashboard")
@@ -153,7 +156,7 @@ with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
153
  with gr.Column(scale=2):
154
  with gr.Row():
155
  creator_service_dropdown = gr.Dropdown(label="Target Service", interactive=True, info="Select the API server you want to encrypt data for.")
156
- refresh_button = gr.Button("Refresh List", icon="πŸ”„", scale=0)
157
  creator_secret_input = gr.Textbox(lines=8, label="Secret Data to Encrypt", placeholder="API_KEY: sk-123...\nUSER: demo-user")
158
  creator_button = gr.Button("Create Auth Image via API", variant="primary", icon="✨")
159
  with gr.Column(scale=1):
@@ -173,49 +176,24 @@ with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
173
 
174
  with gr.TabItem("ℹ️ Service Information", id=3):
175
  gr.Markdown("## Ecosystem Architecture")
176
- gr.Markdown(
177
- """
178
- This dashboard coordinates separate Hugging Face Spaces to demonstrate a secure, decoupled workflow. Each service has a specific role.
179
- """
180
- )
181
  with gr.Row():
182
  with gr.Column():
183
- gr.Markdown(f"""
184
- ### 🏭 Auth Creator Service
185
- - **Space:** [{CREATOR_SPACE_ID}]({CREATOR_URL})
186
- - **Role:** Provides a UI and an API to encrypt data into PNG images for various targets. It reads a public configuration file (`endpoints.json`) to know which public keys it can use.
187
- - **Source Code:** [app.py]({CREATOR_APP_PY_URL})
188
- """)
189
  with gr.Column():
190
- gr.Markdown(f"""
191
- ### πŸ“‘ Decoder Server
192
- - **Space:** [{SERVER_SPACE_ID}]({SERVER_URL})
193
- - **Role:** The trusted authority. It holds a **secret private key** and provides a secure API to decrypt images. This is the only component that can read the secret data.
194
- - **Source Code:** [app.py]({SERVER_APP_PY_URL})
195
- """)
196
 
197
  # --- Wire up the component logic ---
198
  gen_keys_button.click(fn=generate_rsa_keys, inputs=None, outputs=[output_private_key, output_public_key])
199
 
200
- # Logic for fetching and populating the dropdown
201
- load_event = demo.load(
202
- fn=get_creator_endpoints,
203
- inputs=None,
204
- outputs=[creator_service_dropdown, creator_status]
205
- ).then(
206
- lambda data: data, # Pass the full data to the state
207
- js="(data) => data.choices",
208
- outputs=[endpoints_state]
209
- )
210
- refresh_button.click(
211
- fn=get_creator_endpoints,
212
- inputs=None,
213
- outputs=[creator_service_dropdown, creator_status]
214
- ).then(
215
- lambda data: data,
216
- js="(data) => data.choices",
217
- outputs=[endpoints_state]
218
- )
219
 
220
  # Logic for the Creator and Client tabs
221
  creator_button.click(fn=create_image_via_api, inputs=[creator_service_dropdown, creator_secret_input, endpoints_state], outputs=[creator_image_output, gr.File(visible=False), creator_status])
 
5
  import io
6
  import json
7
  import logging
8
+ import requests # Use requests to fetch the remote JSON file
9
  from cryptography.hazmat.primitives import serialization
10
  from cryptography.hazmat.primitives.asymmetric import rsa
11
 
 
19
  CREATOR_SPACE_ID = "broadfield-dev/KeyLock-Auth-Creator"
20
  SERVER_SPACE_ID = "broadfield-dev/KeyLock-Auth-Server"
21
 
22
+ # URL to the raw JSON file containing the list of public keys and services.
23
+ # This makes the Creator's configuration publicly readable.
24
+ CREATOR_ENDPOINTS_JSON_URL = "https://huggingface.co/spaces/broadfield-dev/KeyLock-Auth-Creator/raw/main/endpoints.json"
25
+
26
  # Construct URLs for linking in documentation
27
  BASE_HF_URL = "https://huggingface.co/spaces/"
28
  CREATOR_URL = f"{BASE_HF_URL}{CREATOR_SPACE_ID}"
 
35
  # ==============================================================================
36
 
37
  def get_creator_endpoints():
38
+ """Fetches the list of supported endpoints by making an HTTP request to the Creator's JSON file."""
39
+ status = f"Fetching endpoint list from {CREATOR_ENDPOINTS_JSON_URL}..."
40
+ yield gr.Dropdown(choices=[], value=None, label="⏳ Fetching..."), status, [] # Initial state
41
  try:
42
+ response = requests.get(CREATOR_ENDPOINTS_JSON_URL, timeout=10)
43
+ response.raise_for_status() # Raise an exception for bad status codes
44
 
45
+ endpoints = response.json()
46
  endpoint_names = [e['name'] for e in endpoints]
47
 
48
  status = f"βœ… Success! Found {len(endpoint_names)} endpoints."
49
  # Return the full list to the state, and the updated dropdown
50
+ yield gr.Dropdown(choices=endpoint_names, value=endpoint_names[0] if endpoint_names else None, label="Target Service"), status, endpoints
51
  except Exception as e:
52
+ logger.error(f"Failed to get endpoints from creator's JSON file: {e}", exc_info=True)
53
+ status = f"❌ Error: Could not fetch configuration. Check the URL and if the 'endpoints.json' file is public. Details: {e}"
54
+ yield gr.Dropdown(choices=[], value=None, label="Error fetching services"), status, []
55
 
56
  def create_image_via_api(service_name: str, secret_data: str, available_endpoints: list):
57
  """Calls the Creator Space API to generate an encrypted image for a selected service."""
 
61
  status = f"Looking up public key for '{service_name}'..."
62
  yield None, None, status
63
 
 
64
  public_key = next((e['public_key'] for e in available_endpoints if e['name'] == service_name), None)
65
  if not public_key:
66
  raise gr.Error(f"Could not find public key for '{service_name}' in the fetched configuration.")
 
124
  neutral_hue=gr.themes.colors.slate,
125
  font=(gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"),
126
  ).set(
127
+ body_background_fill="#F1F5F9",
128
  panel_background_fill="white",
129
  block_background_fill="white",
130
  block_border_width="1px",
 
134
  )
135
 
136
  with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
 
137
  endpoints_state = gr.State([])
138
 
139
  gr.Markdown("# πŸ”‘ KeyLock Operations Dashboard")
 
156
  with gr.Column(scale=2):
157
  with gr.Row():
158
  creator_service_dropdown = gr.Dropdown(label="Target Service", interactive=True, info="Select the API server you want to encrypt data for.")
159
+ refresh_button = gr.Button("Refresh List", icon="πŸ”„", scale=0, size="sm")
160
  creator_secret_input = gr.Textbox(lines=8, label="Secret Data to Encrypt", placeholder="API_KEY: sk-123...\nUSER: demo-user")
161
  creator_button = gr.Button("Create Auth Image via API", variant="primary", icon="✨")
162
  with gr.Column(scale=1):
 
176
 
177
  with gr.TabItem("ℹ️ Service Information", id=3):
178
  gr.Markdown("## Ecosystem Architecture")
179
+ gr.Markdown("This dashboard coordinates separate Hugging Face Spaces to demonstrate a secure, decoupled workflow. Each service has a specific role.")
 
 
 
 
180
  with gr.Row():
181
  with gr.Column():
182
+ gr.Markdown(f"### 🏭 Auth Creator Service\n- **Space:** [{CREATOR_SPACE_ID}]({CREATOR_URL})\n- **Role:** Provides an API to encrypt data for various targets defined in its `endpoints.json` file.\n- **Source Code:** [app.py]({CREATOR_APP_PY_URL})")
 
 
 
 
 
183
  with gr.Column():
184
+ gr.Markdown(f"### πŸ“‘ Decoder Server\n- **Space:** [{SERVER_SPACE_ID}]({SERVER_URL})\n- **Role:** The trusted authority. It holds a secret private key and provides a secure API to decrypt images.\n- **Source Code:** [app.py]({SERVER_APP_PY_URL})")
 
 
 
 
 
185
 
186
  # --- Wire up the component logic ---
187
  gen_keys_button.click(fn=generate_rsa_keys, inputs=None, outputs=[output_private_key, output_public_key])
188
 
189
+ # Event handler for loading the page or refreshing the endpoint list
190
+ def refresh_endpoints():
191
+ # This is a generator function, so we need to iterate to get the last value.
192
+ *_, last_yield = get_creator_endpoints()
193
+ return last_yield
194
+
195
+ refresh_button.click(fn=refresh_endpoints, outputs=[creator_service_dropdown, creator_status, endpoints_state])
196
+ demo.load(fn=refresh_endpoints, outputs=[creator_service_dropdown, creator_status, endpoints_state])
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  # Logic for the Creator and Client tabs
199
  creator_button.click(fn=create_image_via_api, inputs=[creator_service_dropdown, creator_secret_input, endpoints_state], outputs=[creator_image_output, gr.File(visible=False), creator_status])