giswqs commited on
Commit
484f16c
·
unverified ·
1 Parent(s): 41dfe63

Fix authentication error (#5)

Browse files
Files changed (1) hide show
  1. main.py +147 -9
main.py CHANGED
@@ -7,15 +7,119 @@ from fastapi import FastAPI, HTTPException
7
  from pydantic import BaseModel
8
  from geemap.ee_tile_layers import _get_tile_url_format, _validate_palette
9
  from starlette.middleware.cors import CORSMiddleware
 
10
 
11
- # Earth Engine auth
12
- if "EARTHENGINE_TOKEN" not in os.environ:
13
- raise RuntimeError("EARTHENGINE_TOKEN environment variable not found")
14
 
15
- try:
16
- geemap.ee_initialize()
17
- except Exception as e:
18
- raise RuntimeError(f"Earth Engine authentication failed: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
 
21
  # ---- Shared Tile Logic ----
@@ -90,6 +194,8 @@ def get_tile(asset_id, vis_params=None, start_date=None, end_date=None, bbox=Non
90
  return f"Error: {str(e)}"
91
 
92
 
 
 
93
  # ---- FastAPI ----
94
  app = FastAPI()
95
  app.add_middleware(
@@ -116,18 +222,50 @@ def get_tile_api(req: TileRequest):
116
 
117
 
118
  # ---- Gradio UI ----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  gradio_ui = gr.Interface(
120
- fn=get_tile,
121
  inputs=[
122
  gr.Textbox(label="Earth Engine Asset ID", placeholder="e.g., USGS/SRTMGL1_003"),
123
  gr.Textbox(
124
  label="Visualization Parameters (JSON)",
125
  placeholder='{"min":0,"max":5000,"palette":"terrain"}',
126
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  ],
128
  outputs="text",
129
  title="Earth Engine Tile URL Generator",
130
- description="Supports ee.Image, ee.ImageCollection, ee.FeatureCollection. Tile URL is suitable for basemap usage.",
131
  )
132
 
133
  app = gr.mount_gradio_app(app, gradio_ui, path="/")
 
7
  from pydantic import BaseModel
8
  from geemap.ee_tile_layers import _get_tile_url_format, _validate_palette
9
  from starlette.middleware.cors import CORSMiddleware
10
+ from typing import Any, Dict, List, Optional, Tuple, Union
11
 
12
+ # # Earth Engine auth
13
+ # if "EARTHENGINE_TOKEN" not in os.environ:
14
+ # raise RuntimeError("EARTHENGINE_TOKEN environment variable not found")
15
 
16
+ # try:
17
+ # geemap.ee_initialize()
18
+ # except Exception as e:
19
+ # raise RuntimeError(f"Earth Engine authentication failed: {e}")
20
+
21
+
22
+ def get_env_var(key: str) -> Optional[str]:
23
+ """Retrieves an environment variable or Colab secret for the given key.
24
+
25
+ Colab secrets have precedence over environment variables.
26
+
27
+ Args:
28
+ key (str): The key that's used to fetch the environment variable.
29
+
30
+ Returns:
31
+ Optional[str]: The retrieved key, or None if no environment variable was found.
32
+ """
33
+ if not key:
34
+ return None
35
+
36
+ return os.environ.get(key)
37
+
38
+
39
+ def ee_initialize(
40
+ token_name: str = "EARTHENGINE_TOKEN",
41
+ auth_mode: Optional[str] = None,
42
+ auth_args: Optional[Dict[str, Any]] = None,
43
+ project: Optional[str] = None,
44
+ **kwargs: Any,
45
+ ) -> None:
46
+ """Authenticates Earth Engine and initialize an Earth Engine session
47
+
48
+ Args:
49
+ token_name (str, optional): The name of the Earth Engine token.
50
+ Defaults to "EARTHENGINE_TOKEN". In Colab, you can also set a secret
51
+ named "EE_PROJECT_ID" to initialize Earth Engine.
52
+ auth_mode (str, optional): The authentication mode, can be one of colab,
53
+ notebook, localhost, or gcloud.
54
+ See https://developers.google.com/earth-engine/guides/auth for more
55
+ details. Defaults to None.
56
+ auth_args (dict, optional): Additional authentication parameters for
57
+ aa.Authenticate(). Defaults to {}.
58
+ user_agent_prefix (str, optional): If set, the prefix (version-less)
59
+ value used for setting the user-agent string. Defaults to "geemap".
60
+ project (str, optional): The Google cloud project ID for Earth Engine.
61
+ Defaults to None.
62
+ kwargs (dict, optional): Additional parameters for ee.Initialize().
63
+ For example, opt_url='https://earthengine-highvolume.googleapis.com'
64
+ to use the Earth Engine High-Volume platform. Defaults to {}.
65
+ """
66
+ import google.oauth2.credentials
67
+
68
+ # pylint: disable-next=protected-access
69
+ if ee.data._get_state().credentials is not None:
70
+ return
71
+
72
+ if get_env_var("EE_SERVICE_ACCOUNT") is not None:
73
+
74
+ key_data = get_env_var("EE_SERVICE_ACCOUNT")
75
+
76
+ try:
77
+ email = json.loads(key_data)["client_email"]
78
+ except json.JSONDecodeError as e:
79
+ raise ValueError(f"Invalid JSON for key_data: {e}")
80
+ except KeyError:
81
+ raise ValueError("key_data JSON does not contain 'client_email'")
82
+ credentials = ee.ServiceAccountCredentials(email=email, key_data=key_data)
83
+ ee.Initialize(credentials)
84
+ return
85
+
86
+ ee_token = get_env_var(token_name)
87
+ if ee_token is not None:
88
+
89
+ stored = json.loads(ee_token)
90
+ credentials = google.oauth2.credentials.Credentials(
91
+ None,
92
+ token_uri="https://oauth2.googleapis.com/token",
93
+ client_id=stored["client_id"],
94
+ client_secret=stored["client_secret"],
95
+ refresh_token=stored["refresh_token"],
96
+ quota_project_id=stored["project"],
97
+ )
98
+
99
+ ee.Initialize(credentials=credentials, **kwargs)
100
+ return
101
+
102
+ if auth_args is None:
103
+ auth_args = {}
104
+
105
+ if project is None:
106
+ kwargs["project"] = get_env_var("EE_PROJECT_ID")
107
+ else:
108
+ kwargs["project"] = project
109
+
110
+ if auth_mode is None:
111
+ # pylint: disable-next=protected-access
112
+ if ee.data._get_state().credentials is None:
113
+ ee.Authenticate()
114
+ ee.Initialize(**kwargs)
115
+ return
116
+ else:
117
+ auth_mode = "notebook"
118
+
119
+ auth_args["auth_mode"] = auth_mode
120
+
121
+ ee.Authenticate(**auth_args)
122
+ ee.Initialize(**kwargs)
123
 
124
 
125
  # ---- Shared Tile Logic ----
 
194
  return f"Error: {str(e)}"
195
 
196
 
197
+ ee_initialize()
198
+
199
  # ---- FastAPI ----
200
  app = FastAPI()
201
  app.add_middleware(
 
222
 
223
 
224
  # ---- Gradio UI ----
225
+ def get_tile_gradio(asset_id, vis_params, start_date, end_date, bbox_str):
226
+ """Wrapper for Gradio that converts string inputs to proper types."""
227
+ # Convert empty strings to None
228
+ start_date = start_date.strip() if start_date and start_date.strip() else None
229
+ end_date = end_date.strip() if end_date and end_date.strip() else None
230
+
231
+ # Convert bbox string to list
232
+ bbox = None
233
+ if bbox_str and bbox_str.strip():
234
+ try:
235
+ bbox = [float(x.strip()) for x in bbox_str.split(",")]
236
+ except ValueError:
237
+ return "Error: bbox must be comma-separated numbers (west,south,east,north)"
238
+
239
+ return get_tile(asset_id, vis_params, start_date, end_date, bbox)
240
+
241
+
242
  gradio_ui = gr.Interface(
243
+ fn=get_tile_gradio,
244
  inputs=[
245
  gr.Textbox(label="Earth Engine Asset ID", placeholder="e.g., USGS/SRTMGL1_003"),
246
  gr.Textbox(
247
  label="Visualization Parameters (JSON)",
248
  placeholder='{"min":0,"max":5000,"palette":"terrain"}',
249
  ),
250
+ gr.Textbox(
251
+ label="Start Date (Optional)",
252
+ placeholder="e.g., 2023-01-01",
253
+ value="",
254
+ ),
255
+ gr.Textbox(
256
+ label="End Date (Optional)",
257
+ placeholder="e.g., 2023-12-31",
258
+ value="",
259
+ ),
260
+ gr.Textbox(
261
+ label="Bounding Box (Optional)",
262
+ placeholder="e.g., -122.5,37.5,-122.0,38.0 (west,south,east,north)",
263
+ value="",
264
+ ),
265
  ],
266
  outputs="text",
267
  title="Earth Engine Tile URL Generator",
268
+ description="Supports ee.Image, ee.ImageCollection, ee.FeatureCollection with optional date range and bbox filtering. Tile URL is suitable for basemap usage.",
269
  )
270
 
271
  app = gr.mount_gradio_app(app, gradio_ui, path="/")