broadfield-dev commited on
Commit
1db56f0
Β·
verified Β·
1 Parent(s): f51b2ea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -31
app.py CHANGED
@@ -28,13 +28,14 @@ CREATOR_APP_PY_URL = f"{CREATOR_URL}/blob/main/app.py"
28
  SERVER_APP_PY_URL = f"{SERVER_URL}/blob/main/app.py"
29
 
30
  # ==============================================================================
31
- # API CALL WRAPPER FUNCTIONS (Your working versions)
32
  # ==============================================================================
33
 
34
  def get_creator_endpoints():
35
  """Fetches the list of supported endpoints by making an HTTP request to the Creator's JSON file."""
36
  status = f"Fetching endpoint list from {CREATOR_ENDPOINTS_JSON_URL}..."
37
- yield gr.Dropdown(choices=[], value=None, label="⏳ Fetching..."), status, [] # Initial state
 
38
  try:
39
  response = requests.get(CREATOR_ENDPOINTS_JSON_URL, timeout=10)
40
  response.raise_for_status()
@@ -53,56 +54,66 @@ def create_image_via_api(service_name: str, secret_data: str, available_endpoint
53
  raise gr.Error("Please select a service and provide secret data.")
54
 
55
  status = f"Looking up public key for '{service_name}'..."
56
- yield None, None, status
57
 
58
- public_key = next((e['public_key'] for e in available_endpoints if e['name'] == service_name), None)
59
- if not public_key:
60
- raise gr.Error(f"Could not find public key for '{service_name}' in the fetched configuration.")
61
-
62
- status = f"Connecting to Creator: {CREATOR_SPACE_ID}..."
63
- yield None, None, status
64
-
65
  try:
 
 
 
 
 
 
 
66
  client = Client(src=CREATOR_SPACE_ID)
67
  temp_filepath = client.predict(secret_data, public_key, api_name="/create_image")
68
 
69
- if not temp_filepath: raise gr.Error("Creator API did not return an image.")
 
70
 
71
  # --- PNG FIX ---
72
- # The API returns a path to a temp file which could be any format.
73
- # We open it, ensure it's saved as PNG, and return that path.
74
  created_image = Image.open(temp_filepath)
75
 
76
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as png_file:
77
- created_image.save(png_file.name, "PNG")
78
- png_filepath = png_file.name
79
-
80
  status = f"βœ… Success! Image created for '{service_name}'."
81
- yield created_image, png_filepath, status
82
 
83
  except Exception as e:
84
  logger.error(f"Creator API call failed: {e}", exc_info=True)
85
- yield None, None, f"❌ Error calling Creator API: {e}"
 
86
 
87
  def decrypt_image_via_api(image: Image.Image):
88
  """Calls the Server Space API to decrypt an image."""
89
- if image is None: raise gr.Error("Please upload an image to decrypt.")
 
 
90
  status = f"Connecting to Server: {SERVER_SPACE_ID}..."
91
- yield None, status
 
92
  try:
93
  client = Client(src=SERVER_SPACE_ID)
94
  with io.BytesIO() as buffer:
 
95
  image.save(buffer, format="PNG")
96
  b64_string = base64.b64encode(buffer.getvalue()).decode("utf-8")
97
 
98
  status = f"Calling API on {SERVER_SPACE_ID}..."
99
- yield None, status
 
100
  decrypted_json = client.predict(b64_string, api_name="/keylock-auth-decoder")
 
101
  status = "βœ… Success! Data decrypted by the Server."
102
- yield decrypted_json, status
 
 
 
 
 
103
  except Exception as e:
104
  logger.error(f"Server API call failed: {e}", exc_info=True)
105
- yield None, f"❌ Error calling Server API: {e}"
 
106
 
107
  def generate_rsa_keys():
108
  """Generates a new RSA key pair."""
@@ -117,7 +128,7 @@ def generate_rsa_keys():
117
  return private_pem, public_pem
118
 
119
  # ==============================================================================
120
- # GRADIO DASHBOARD INTERFACE
121
  # ==============================================================================
122
  theme = gr.themes.Base(
123
  primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.sky, neutral_hue=gr.themes.colors.slate,
@@ -142,15 +153,14 @@ with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
142
  with gr.Column(scale=2):
143
  with gr.Row():
144
  creator_service_dropdown = gr.Dropdown(label="Target Service", interactive=True, info="Select the API server you want to encrypt data for.")
145
- refresh_button = gr.Button("πŸ”„", scale=0, size="sm")
146
  creator_secret_input = gr.Textbox(lines=8, label="Secret Data to Encrypt", placeholder="API_KEY: sk-123...\nUSER: demo-user")
147
  creator_button = gr.Button("✨ Create Auth Image via API", variant="primary")
148
  with gr.Column(scale=1):
149
  creator_status = gr.Textbox(label="Status", interactive=False, lines=2)
150
- creator_image_output = gr.Image(label="Image from Creator Service", type="pil", show_download_button=False) # Download handled by gr.File
151
  # --- PNG FIX ---
152
- # Use a dedicated, visible File component for reliable PNG downloads.
153
- creator_download_output = gr.File(label="Download Image as PNG", interactive=False)
154
 
155
  with gr.TabItem("β‘‘ Client / Decoder", id=1):
156
  gr.Markdown("## Decrypt an Authentication Image")
@@ -186,6 +196,7 @@ with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
186
  gen_keys_button.click(fn=generate_rsa_keys, inputs=None, outputs=[output_private_key, output_public_key])
187
 
188
  def refresh_endpoints():
 
189
  *_, last_yield = get_creator_endpoints()
190
  return last_yield
191
 
@@ -195,9 +206,13 @@ with gr.Blocks(theme=theme, title="KeyLock Operations Dashboard") as demo:
195
  creator_button.click(
196
  fn=create_image_via_api,
197
  inputs=[creator_service_dropdown, creator_secret_input, endpoints_state],
198
- outputs=[creator_image_output, creator_download_output, creator_status] # Now outputs to the gr.File component
 
 
 
 
 
199
  )
200
- client_button.click(fn=decrypt_image_via_api, inputs=[client_image_input], outputs=[client_json_output, client_status])
201
 
202
  if __name__ == "__main__":
203
  demo.launch()
 
28
  SERVER_APP_PY_URL = f"{SERVER_URL}/blob/main/app.py"
29
 
30
  # ==============================================================================
31
+ # API CALL WRAPPER FUNCTIONS (CORRECTED)
32
  # ==============================================================================
33
 
34
  def get_creator_endpoints():
35
  """Fetches the list of supported endpoints by making an HTTP request to the Creator's JSON file."""
36
  status = f"Fetching endpoint list from {CREATOR_ENDPOINTS_JSON_URL}..."
37
+ # Using yield for streaming status updates
38
+ yield gr.Dropdown(choices=[], value=None, label="⏳ Fetching..."), status, []
39
  try:
40
  response = requests.get(CREATOR_ENDPOINTS_JSON_URL, timeout=10)
41
  response.raise_for_status()
 
54
  raise gr.Error("Please select a service and provide secret data.")
55
 
56
  status = f"Looking up public key for '{service_name}'..."
57
+ # No yield here, we'll return everything at the end.
58
 
 
 
 
 
 
 
 
59
  try:
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.")
63
+
64
+ status = f"Connecting to Creator: {CREATOR_SPACE_ID}..."
65
+ logger.info(status)
66
+
67
  client = Client(src=CREATOR_SPACE_ID)
68
  temp_filepath = client.predict(secret_data, public_key, api_name="/create_image")
69
 
70
+ if not temp_filepath:
71
+ raise gr.Error("Creator API did not return an image.")
72
 
73
  # --- PNG FIX ---
74
+ # Load the image from the temp path and return the PIL Image object directly.
75
+ # The gr.Image component's `format="png"` will handle the rest.
76
  created_image = Image.open(temp_filepath)
77
 
 
 
 
 
78
  status = f"βœ… Success! Image created for '{service_name}'."
79
+ return created_image, status
80
 
81
  except Exception as e:
82
  logger.error(f"Creator API call failed: {e}", exc_info=True)
83
+ # On error, return an empty image and the error status.
84
+ return None, f"❌ Error calling Creator API: {e}"
85
 
86
  def decrypt_image_via_api(image: Image.Image):
87
  """Calls the Server Space API to decrypt an image."""
88
+ if image is None:
89
+ raise gr.Error("Please upload an image to decrypt.")
90
+
91
  status = f"Connecting to Server: {SERVER_SPACE_ID}..."
92
+ logger.info(status)
93
+
94
  try:
95
  client = Client(src=SERVER_SPACE_ID)
96
  with io.BytesIO() as buffer:
97
+ # Explicitly save as PNG to ensure format is correct before base64 encoding
98
  image.save(buffer, format="PNG")
99
  b64_string = base64.b64encode(buffer.getvalue()).decode("utf-8")
100
 
101
  status = f"Calling API on {SERVER_SPACE_ID}..."
102
+ logger.info(status)
103
+
104
  decrypted_json = client.predict(b64_string, api_name="/keylock-auth-decoder")
105
+
106
  status = "βœ… Success! Data decrypted by the Server."
107
+ logger.info(f"Decryption successful. Data: {decrypted_json}")
108
+
109
+ # --- DECRYPTED DATA FIX ---
110
+ # Use a single, final return statement. This is more robust.
111
+ return decrypted_json, status
112
+
113
  except Exception as e:
114
  logger.error(f"Server API call failed: {e}", exc_info=True)
115
+ # Return an empty dict and the error message for a clean UI update.
116
+ return {}, f"❌ Error calling Server API: {e}"
117
 
118
  def generate_rsa_keys():
119
  """Generates a new RSA key pair."""
 
128
  return private_pem, public_pem
129
 
130
  # ==============================================================================
131
+ # GRADIO DASHBOARD INTERFACE (Corrected Layout and Components)
132
  # ==============================================================================
133
  theme = gr.themes.Base(
134
  primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.sky, neutral_hue=gr.themes.colors.slate,
 
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("πŸ”„", scale=0, size="sm", tooltip="Refresh Target Service List")
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")
159
  with gr.Column(scale=1):
160
  creator_status = gr.Textbox(label="Status", interactive=False, lines=2)
 
161
  # --- PNG FIX ---
162
+ # The format='png' argument tells the component's download button to create a PNG.
163
+ creator_image_output = gr.Image(label="Image from Creator Service", type="pil", show_download_button=True, format="png")
164
 
165
  with gr.TabItem("β‘‘ Client / Decoder", id=1):
166
  gr.Markdown("## Decrypt an Authentication Image")
 
196
  gen_keys_button.click(fn=generate_rsa_keys, inputs=None, outputs=[output_private_key, output_public_key])
197
 
198
  def refresh_endpoints():
199
+ # This is a generator function, so we need to iterate to get the last value.
200
  *_, last_yield = get_creator_endpoints()
201
  return last_yield
202
 
 
206
  creator_button.click(
207
  fn=create_image_via_api,
208
  inputs=[creator_service_dropdown, creator_secret_input, endpoints_state],
209
+ outputs=[creator_image_output, creator_status] # Removed the gr.File output
210
+ )
211
+ client_button.click(
212
+ fn=decrypt_image_via_api,
213
+ inputs=[client_image_input],
214
+ outputs=[client_json_output, client_status]
215
  )
 
216
 
217
  if __name__ == "__main__":
218
  demo.launch()