LogicGoInfotechSpaces commited on
Commit
c85fec3
·
1 Parent(s): e8ae712

Add Firebase email/password authentication endpoints - Add /auth/register endpoint for user registration - Add /auth/login endpoint with Firebase REST API integration - Add /auth/me endpoint to get current user info - Add /auth/refresh endpoint for token refresh - Integrate with existing Firebase App Check - Add httpx and email-validator dependencies

Browse files
Files changed (4) hide show
  1. app/config.py +1 -0
  2. app/main_sdxl.py +222 -4
  3. postman_collection.json +283 -256
  4. requirements.txt +3 -1
app/config.py CHANGED
@@ -13,6 +13,7 @@ class Settings(BaseSettings):
13
  "FIREBASE_CREDENTIALS_PATH",
14
  "/data/firebase-adminsdk.json"
15
  )
 
16
 
17
  # API settings
18
  BASE_URL: str = os.getenv("BASE_URL", "http://localhost:8000")
 
13
  "FIREBASE_CREDENTIALS_PATH",
14
  "/data/firebase-adminsdk.json"
15
  )
16
+ FIREBASE_API_KEY: str = os.getenv("FIREBASE_API_KEY", "")
17
 
18
  # API settings
19
  BASE_URL: str = os.getenv("BASE_URL", "http://localhost:8000")
app/main_sdxl.py CHANGED
@@ -9,7 +9,7 @@ import logging
9
  from pathlib import Path
10
  from typing import Optional, Tuple
11
 
12
- from fastapi import FastAPI, UploadFile, File, HTTPException, Depends, Request
13
  from fastapi.responses import FileResponse, JSONResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
  from fastapi.staticfiles import StaticFiles
@@ -18,6 +18,8 @@ from firebase_admin import credentials, app_check, auth as firebase_auth
18
  from PIL import Image
19
  import uvicorn
20
  import gradio as gr
 
 
21
 
22
  # Hugging Face Inference API
23
  from huggingface_hub import InferenceClient
@@ -188,6 +190,24 @@ async def shutdown_event():
188
  logger.info("Application shutdown")
189
 
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  # ========== Authentication ==========
192
 
193
  def _extract_bearer_token(authorization_header: str | None) -> str | None:
@@ -229,6 +249,194 @@ async def verify_request(request: Request):
229
  return True
230
 
231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  # ========== API Endpoints ==========
233
 
234
  @app.get("/api")
@@ -237,9 +445,19 @@ async def api_info():
237
  return {
238
  "app": "Text-Guided Image Colorization API",
239
  "version": "1.0.0",
240
- "health": "/health",
241
- "colorize": "/colorize",
242
- "gradio": "/"
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
 
 
9
  from pathlib import Path
10
  from typing import Optional, Tuple
11
 
12
+ from fastapi import FastAPI, UploadFile, File, HTTPException, Depends, Request, Body
13
  from fastapi.responses import FileResponse, JSONResponse
14
  from fastapi.middleware.cors import CORSMiddleware
15
  from fastapi.staticfiles import StaticFiles
 
18
  from PIL import Image
19
  import uvicorn
20
  import gradio as gr
21
+ import httpx
22
+ from pydantic import BaseModel, EmailStr
23
 
24
  # Hugging Face Inference API
25
  from huggingface_hub import InferenceClient
 
190
  logger.info("Application shutdown")
191
 
192
 
193
+ # ========== Authentication Models ==========
194
+
195
+ class RegisterRequest(BaseModel):
196
+ email: EmailStr
197
+ password: str
198
+ display_name: Optional[str] = None
199
+
200
+ class LoginRequest(BaseModel):
201
+ email: EmailStr
202
+ password: str
203
+
204
+ class TokenResponse(BaseModel):
205
+ id_token: str
206
+ refresh_token: Optional[str] = None
207
+ expires_in: int
208
+ token_type: str = "Bearer"
209
+ user: dict
210
+
211
  # ========== Authentication ==========
212
 
213
  def _extract_bearer_token(authorization_header: str | None) -> str | None:
 
249
  return True
250
 
251
 
252
+ # ========== Auth Endpoints ==========
253
+
254
+ @app.post("/auth/register", response_model=TokenResponse)
255
+ async def register_user(user_data: RegisterRequest):
256
+ """
257
+ Register a new user with email and password.
258
+ Returns Firebase ID token for immediate use.
259
+ """
260
+ if not firebase_admin._apps:
261
+ raise HTTPException(status_code=503, detail="Firebase not initialized")
262
+
263
+ try:
264
+ # Create user using Firebase Admin SDK
265
+ user_record = firebase_auth.create_user(
266
+ email=user_data.email,
267
+ password=user_data.password,
268
+ display_name=user_data.display_name,
269
+ email_verified=False
270
+ )
271
+
272
+ # Generate custom token that client can exchange for ID token
273
+ custom_token = firebase_auth.create_custom_token(user_record.uid)
274
+
275
+ logger.info("User registered: %s (uid: %s)", user_data.email, user_record.uid)
276
+
277
+ return TokenResponse(
278
+ id_token=custom_token.decode('utf-8'), # Custom token (client should exchange)
279
+ token_type="Bearer",
280
+ expires_in=3600,
281
+ user={
282
+ "uid": user_record.uid,
283
+ "email": user_record.email,
284
+ "display_name": user_record.display_name,
285
+ "email_verified": user_record.email_verified
286
+ }
287
+ )
288
+ except firebase_auth.EmailAlreadyExistsError:
289
+ raise HTTPException(status_code=400, detail="Email already registered")
290
+ except ValueError as e:
291
+ raise HTTPException(status_code=400, detail=f"Invalid input: {str(e)}")
292
+ except Exception as e:
293
+ logger.error("Registration error: %s", str(e))
294
+ raise HTTPException(status_code=500, detail=f"Registration failed: {str(e)}")
295
+
296
+
297
+ @app.post("/auth/login", response_model=TokenResponse)
298
+ async def login_user(credentials: LoginRequest):
299
+ """
300
+ Login with email and password.
301
+ Uses Firebase REST API to authenticate and get ID token.
302
+ """
303
+ if not firebase_admin._apps:
304
+ raise HTTPException(status_code=503, detail="Firebase not initialized")
305
+
306
+ # Firebase REST API endpoint for email/password authentication
307
+ firebase_api_key = os.getenv("FIREBASE_API_KEY") or settings.FIREBASE_API_KEY
308
+ if not firebase_api_key:
309
+ # Fallback: verify user exists and return custom token
310
+ try:
311
+ user_record = firebase_auth.get_user_by_email(credentials.email)
312
+ custom_token = firebase_auth.create_custom_token(user_record.uid)
313
+
314
+ logger.info("User login: %s (uid: %s)", credentials.email, user_record.uid)
315
+
316
+ return TokenResponse(
317
+ id_token=custom_token.decode('utf-8'),
318
+ token_type="Bearer",
319
+ expires_in=3600,
320
+ user={
321
+ "uid": user_record.uid,
322
+ "email": user_record.email,
323
+ "display_name": user_record.display_name,
324
+ "email_verified": user_record.email_verified
325
+ }
326
+ )
327
+ except firebase_auth.UserNotFoundError:
328
+ raise HTTPException(status_code=401, detail="Invalid email or password")
329
+ except Exception as e:
330
+ logger.error("Login error: %s", str(e))
331
+ raise HTTPException(status_code=500, detail=f"Login failed: {str(e)}")
332
+
333
+ # Use Firebase REST API for proper authentication
334
+ try:
335
+ async with httpx.AsyncClient() as client:
336
+ response = await client.post(
337
+ f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={firebase_api_key}",
338
+ json={
339
+ "email": credentials.email,
340
+ "password": credentials.password,
341
+ "returnSecureToken": True
342
+ }
343
+ )
344
+
345
+ if response.status_code != 200:
346
+ error_data = response.json()
347
+ error_msg = error_data.get("error", {}).get("message", "Authentication failed")
348
+ raise HTTPException(status_code=401, detail=error_msg)
349
+
350
+ data = response.json()
351
+ logger.info("User login successful: %s", credentials.email)
352
+
353
+ # Get user details from Admin SDK
354
+ user_record = firebase_auth.get_user(data["localId"])
355
+
356
+ return TokenResponse(
357
+ id_token=data["idToken"],
358
+ refresh_token=data.get("refreshToken"),
359
+ expires_in=int(data.get("expiresIn", 3600)),
360
+ token_type="Bearer",
361
+ user={
362
+ "uid": user_record.uid,
363
+ "email": user_record.email,
364
+ "display_name": user_record.display_name,
365
+ "email_verified": user_record.email_verified
366
+ }
367
+ )
368
+ except httpx.HTTPError as e:
369
+ logger.error("HTTP error during login: %s", str(e))
370
+ raise HTTPException(status_code=500, detail="Authentication service unavailable")
371
+ except Exception as e:
372
+ logger.error("Login error: %s", str(e))
373
+ raise HTTPException(status_code=500, detail=f"Login failed: {str(e)}")
374
+
375
+
376
+ @app.get("/auth/me")
377
+ async def get_current_user(request: Request, verified: bool = Depends(verify_request)):
378
+ """Get current authenticated user information"""
379
+ if not firebase_admin._apps:
380
+ raise HTTPException(status_code=503, detail="Firebase not initialized")
381
+
382
+ # Get user from request state (set by verify_request)
383
+ if hasattr(request, 'state') and hasattr(request.state, 'user'):
384
+ user_data = request.state.user
385
+ uid = user_data.get("uid")
386
+
387
+ try:
388
+ user_record = firebase_auth.get_user(uid)
389
+ return {
390
+ "uid": user_record.uid,
391
+ "email": user_record.email,
392
+ "display_name": user_record.display_name,
393
+ "email_verified": user_record.email_verified,
394
+ "created_at": user_record.user_metadata.creation_timestamp,
395
+ }
396
+ except Exception as e:
397
+ logger.error("Error getting user: %s", str(e))
398
+ raise HTTPException(status_code=404, detail="User not found")
399
+
400
+ raise HTTPException(status_code=401, detail="Not authenticated")
401
+
402
+
403
+ @app.post("/auth/refresh")
404
+ async def refresh_token(refresh_token: str = Body(..., embed=True)):
405
+ """Refresh Firebase ID token using refresh token"""
406
+ firebase_api_key = os.getenv("FIREBASE_API_KEY") or settings.FIREBASE_API_KEY
407
+ if not firebase_api_key:
408
+ raise HTTPException(status_code=503, detail="Firebase API key not configured")
409
+
410
+ try:
411
+ async with httpx.AsyncClient() as client:
412
+ response = await client.post(
413
+ f"https://securetoken.googleapis.com/v1/token?key={firebase_api_key}",
414
+ json={
415
+ "grant_type": "refresh_token",
416
+ "refresh_token": refresh_token
417
+ }
418
+ )
419
+
420
+ if response.status_code != 200:
421
+ error_data = response.json()
422
+ error_msg = error_data.get("error", {}).get("message", "Token refresh failed")
423
+ raise HTTPException(status_code=401, detail=error_msg)
424
+
425
+ data = response.json()
426
+ return {
427
+ "id_token": data["id_token"],
428
+ "refresh_token": data.get("refresh_token"),
429
+ "expires_in": int(data.get("expires_in", 3600)),
430
+ "token_type": "Bearer"
431
+ }
432
+ except httpx.HTTPError as e:
433
+ logger.error("HTTP error during token refresh: %s", str(e))
434
+ raise HTTPException(status_code=500, detail="Token refresh service unavailable")
435
+ except Exception as e:
436
+ logger.error("Token refresh error: %s", str(e))
437
+ raise HTTPException(status_code=500, detail=f"Token refresh failed: {str(e)}")
438
+
439
+
440
  # ========== API Endpoints ==========
441
 
442
  @app.get("/api")
 
445
  return {
446
  "app": "Text-Guided Image Colorization API",
447
  "version": "1.0.0",
448
+ "endpoints": {
449
+ "health": "/health",
450
+ "auth": {
451
+ "register": "/auth/register",
452
+ "login": "/auth/login",
453
+ "me": "/auth/me",
454
+ "refresh": "/auth/refresh"
455
+ },
456
+ "colorize": "/colorize",
457
+ "download": "/download/{file_id}",
458
+ "results": "/results/{filename}",
459
+ "gradio": "/"
460
+ }
461
  }
462
 
463
 
postman_collection.json CHANGED
@@ -1,258 +1,285 @@
1
  {
2
- "info": {
3
- "name": "Colorize API",
4
- "_postman_id": "f3f5d3cc-6a2b-4d2e-9b1e-collection-colorize",
5
- "description": "Postman collection for the Colorize Image API (FastAPI). Import this file into Postman.",
6
- "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7
- },
8
- "item": [
9
- {
10
- "name": "Authentication",
11
- "item": [
12
- {
13
- "name": "Login (Firebase Auth - email/password)",
14
- "event": [
15
- {
16
- "listen": "test",
17
- "script": {
18
- "type": "text/javascript",
19
- "exec": [
20
- "try {",
21
- " const res = pm.response.json();",
22
- " if (res.idToken) pm.collectionVariables.set('id_token', res.idToken);",
23
- " if (res.refreshToken) pm.collectionVariables.set('refresh_token', res.refreshToken);",
24
- " if (res.localId) pm.collectionVariables.set('local_id', res.localId);",
25
- "} catch (e) {",
26
- " console.log('Failed to parse login response', e);",
27
- "}"
28
- ]
29
- }
30
- }
31
- ],
32
- "request": {
33
- "method": "POST",
34
- "header": [
35
- {
36
- "key": "Content-Type",
37
- "value": "application/json"
38
- }
39
- ],
40
- "body": {
41
- "mode": "raw",
42
- "raw": "{\n \"email\": \"{{email}}\",\n \"password\": \"{{password}}\",\n \"returnSecureToken\": true\n}"
43
- },
44
- "url": {
45
- "raw": "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={{firebase_api_key}}",
46
- "protocol": "https",
47
- "host": [
48
- "identitytoolkit",
49
- "googleapis",
50
- "com"
51
- ],
52
- "path": [
53
- "v1",
54
- "accounts:signInWithPassword"
55
- ],
56
- "query": [
57
- {
58
- "key": "key",
59
- "value": "{{firebase_api_key}}"
60
- }
61
- ]
62
- },
63
- "description": "Obtain Firebase Auth id_token using email/password. Stores id_token in collection variable {{id_token}}."
64
- }
65
- }
66
- ]
67
- },
68
- {
69
- "name": "Health",
70
- "request": {
71
- "method": "GET",
72
- "header": [],
73
- "url": {
74
- "raw": "{{base_url}}/health",
75
- "host": [
76
- "{{base_url}}"
77
- ],
78
- "path": [
79
- "health"
80
- ]
81
- }
82
- }
83
- },
84
- {
85
- "name": "Upload Image",
86
- "request": {
87
- "method": "POST",
88
- "header": [
89
- {
90
- "key": "Authorization",
91
- "value": "Bearer {{id_token}}",
92
- "type": "text"
93
- },
94
- {
95
- "key": "X-Firebase-AppCheck",
96
- "value": "{{app_check_token}}",
97
- "type": "text"
98
- }
99
- ],
100
- "body": {
101
- "mode": "formdata",
102
- "formdata": [
103
- {
104
- "key": "file",
105
- "type": "file",
106
- "src": []
107
- }
108
- ]
109
- },
110
- "url": {
111
- "raw": "{{base_url}}/upload",
112
- "host": [
113
- "{{base_url}}"
114
- ],
115
- "path": [
116
- "upload"
117
- ]
118
- },
119
- "description": "Choose an image file in form-data 'file'. Returns image_url and filename."
120
- }
121
- },
122
- {
123
- "name": "Colorize Image",
124
- "request": {
125
- "method": "POST",
126
- "header": [
127
- {
128
- "key": "Authorization",
129
- "value": "Bearer {{id_token}}",
130
- "type": "text"
131
- },
132
- {
133
- "key": "X-Firebase-AppCheck",
134
- "value": "{{app_check_token}}",
135
- "type": "text"
136
- }
137
- ],
138
- "body": {
139
- "mode": "formdata",
140
- "formdata": [
141
- {
142
- "key": "file",
143
- "type": "file",
144
- "src": []
145
- }
146
- ]
147
- },
148
- "url": {
149
- "raw": "{{base_url}}/colorize",
150
- "host": [
151
- "{{base_url}}"
152
- ],
153
- "path": [
154
- "colorize"
155
- ]
156
- },
157
- "description": "Choose a grayscale (or any) image file in form-data 'file'. Returns download_url and result_id."
158
- }
159
- },
160
- {
161
- "name": "Download Result (by result_id)",
162
- "request": {
163
- "method": "GET",
164
- "header": [
165
- {
166
- "key": "Authorization",
167
- "value": "Bearer {{id_token}}",
168
- "type": "text"
169
- },
170
- {
171
- "key": "X-Firebase-AppCheck",
172
- "value": "{{app_check_token}}",
173
- "type": "text"
174
- }
175
- ],
176
- "url": {
177
- "raw": "{{base_url}}/download/{{result_id}}",
178
- "host": [
179
- "{{base_url}}"
180
- ],
181
- "path": [
182
- "download",
183
- "{{result_id}}"
184
- ]
185
- },
186
- "description": "Uses the result_id returned by the Colorize Image request."
187
- }
188
- },
189
- {
190
- "name": "Get Result (public by filename)",
191
- "request": {
192
- "method": "GET",
193
- "header": [],
194
- "url": {
195
- "raw": "{{base_url}}/results/{{filename}}",
196
- "host": [
197
- "{{base_url}}"
198
- ],
199
- "path": [
200
- "results",
201
- "{{filename}}"
202
- ]
203
- },
204
- "description": "Direct public URL to image file; no auth required."
205
- }
206
- }
207
- ,
208
- {
209
- "name": "Get Uploaded (public by filename)",
210
- "request": {
211
- "method": "GET",
212
- "header": [],
213
- "url": {
214
- "raw": "{{base_url}}/uploads/{{filename}}",
215
- "host": [
216
- "{{base_url}}"
217
- ],
218
- "path": [
219
- "uploads",
220
- "{{filename}}"
221
- ]
222
- },
223
- "description": "Direct public URL to uploaded image file; no auth required."
224
- }
225
- }
226
- ],
227
- "variable": [
228
- {
229
- "key": "base_url",
230
- "value": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space"
231
- },
232
- {
233
- "key": "firebase_api_key",
234
- "value": "AIzaSyBIB6rcfyyqy5niERTXWvVD714Ter4Vx68"
235
- },
236
- {
237
- "key": "email",
238
- "value": "itisha.logico@gmail.com"
239
- },
240
- {
241
- "key": "password",
242
- "value": "123456"
243
- },
244
- {
245
- "key": "app_check_token",
246
- "value": ""
247
- },
248
- {
249
- "key": "result_id",
250
- "value": ""
251
- },
252
- {
253
- "key": "filename",
254
- "value": ""
255
- }
256
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
-
 
1
  {
2
+ "info": {
3
+ "_postman_id": "image-colorization-api",
4
+ "name": "Image Colorization API",
5
+ "description": "API collection for Text-Guided Image Colorization using Hugging Face Inference API",
6
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7
+ },
8
+ "item": [
9
+ {
10
+ "name": "Health Check",
11
+ "request": {
12
+ "method": "GET",
13
+ "header": [],
14
+ "url": {
15
+ "raw": "{{base_url}}/health",
16
+ "host": [
17
+ "{{base_url}}"
18
+ ],
19
+ "path": [
20
+ "health"
21
+ ]
22
+ },
23
+ "description": "Check if the API is running and models are loaded"
24
+ },
25
+ "response": []
26
+ },
27
+ {
28
+ "name": "API Info",
29
+ "request": {
30
+ "method": "GET",
31
+ "header": [],
32
+ "url": {
33
+ "raw": "{{base_url}}/api",
34
+ "host": [
35
+ "{{base_url}}"
36
+ ],
37
+ "path": [
38
+ "api"
39
+ ]
40
+ },
41
+ "description": "Get API information and available endpoints"
42
+ },
43
+ "response": []
44
+ },
45
+ {
46
+ "name": "Colorize Image - Basic",
47
+ "request": {
48
+ "method": "POST",
49
+ "header": [
50
+ {
51
+ "key": "Authorization",
52
+ "value": "Bearer {{firebase_token}}",
53
+ "type": "text"
54
+ }
55
+ ],
56
+ "body": {
57
+ "mode": "formdata",
58
+ "formdata": [
59
+ {
60
+ "key": "file",
61
+ "type": "file",
62
+ "src": [],
63
+ "description": "Image file to colorize"
64
+ }
65
+ ]
66
+ },
67
+ "url": {
68
+ "raw": "{{base_url}}/colorize",
69
+ "host": [
70
+ "{{base_url}}"
71
+ ],
72
+ "path": [
73
+ "colorize"
74
+ ]
75
+ },
76
+ "description": "Colorize an image with default settings"
77
+ },
78
+ "response": []
79
+ },
80
+ {
81
+ "name": "Colorize Image - With Prompt",
82
+ "request": {
83
+ "method": "POST",
84
+ "header": [
85
+ {
86
+ "key": "Authorization",
87
+ "value": "Bearer {{firebase_token}}",
88
+ "type": "text"
89
+ }
90
+ ],
91
+ "body": {
92
+ "mode": "formdata",
93
+ "formdata": [
94
+ {
95
+ "key": "file",
96
+ "type": "file",
97
+ "src": [],
98
+ "description": "Image file to colorize"
99
+ },
100
+ {
101
+ "key": "positive_prompt",
102
+ "value": "vibrant natural colors, high quality photo",
103
+ "type": "text",
104
+ "description": "Additional descriptive text to enhance the caption"
105
+ }
106
+ ]
107
+ },
108
+ "url": {
109
+ "raw": "{{base_url}}/colorize",
110
+ "host": [
111
+ "{{base_url}}"
112
+ ],
113
+ "path": [
114
+ "colorize"
115
+ ]
116
+ },
117
+ "description": "Colorize an image with custom positive prompt"
118
+ },
119
+ "response": []
120
+ },
121
+ {
122
+ "name": "Colorize Image - Full Options",
123
+ "request": {
124
+ "method": "POST",
125
+ "header": [
126
+ {
127
+ "key": "Authorization",
128
+ "value": "Bearer {{firebase_token}}",
129
+ "type": "text"
130
+ }
131
+ ],
132
+ "body": {
133
+ "mode": "formdata",
134
+ "formdata": [
135
+ {
136
+ "key": "file",
137
+ "type": "file",
138
+ "src": [],
139
+ "description": "Image file to colorize"
140
+ },
141
+ {
142
+ "key": "positive_prompt",
143
+ "value": "vibrant natural colors, high quality photo, detailed lighting",
144
+ "type": "text",
145
+ "description": "Additional descriptive text to enhance the caption"
146
+ },
147
+ {
148
+ "key": "negative_prompt",
149
+ "value": "low quality, monochrome, blurry, grainy",
150
+ "type": "text",
151
+ "description": "Words or phrases to avoid during generation"
152
+ },
153
+ {
154
+ "key": "seed",
155
+ "value": "123",
156
+ "type": "text",
157
+ "description": "Random seed for reproducible generation"
158
+ },
159
+ {
160
+ "key": "num_inference_steps",
161
+ "value": "8",
162
+ "type": "text",
163
+ "description": "Number of inference steps"
164
+ }
165
+ ]
166
+ },
167
+ "url": {
168
+ "raw": "{{base_url}}/colorize",
169
+ "host": [
170
+ "{{base_url}}"
171
+ ],
172
+ "path": [
173
+ "colorize"
174
+ ]
175
+ },
176
+ "description": "Colorize an image with all available options"
177
+ },
178
+ "response": []
179
+ },
180
+ {
181
+ "name": "Download Result",
182
+ "request": {
183
+ "method": "GET",
184
+ "header": [
185
+ {
186
+ "key": "Authorization",
187
+ "value": "Bearer {{firebase_token}}",
188
+ "type": "text"
189
+ }
190
+ ],
191
+ "url": {
192
+ "raw": "{{base_url}}/download/{{result_id}}",
193
+ "host": [
194
+ "{{base_url}}"
195
+ ],
196
+ "path": [
197
+ "download",
198
+ "{{result_id}}"
199
+ ]
200
+ },
201
+ "description": "Download colorized image by result ID (requires authentication)"
202
+ },
203
+ "response": []
204
+ },
205
+ {
206
+ "name": "Get Result (Public)",
207
+ "request": {
208
+ "method": "GET",
209
+ "header": [],
210
+ "url": {
211
+ "raw": "{{base_url}}/results/{{filename}}",
212
+ "host": [
213
+ "{{base_url}}"
214
+ ],
215
+ "path": [
216
+ "results",
217
+ "{{filename}}"
218
+ ]
219
+ },
220
+ "description": "Public endpoint to access colorized images by filename"
221
+ },
222
+ "response": []
223
+ },
224
+ {
225
+ "name": "Colorize Image - Without Auth",
226
+ "request": {
227
+ "method": "POST",
228
+ "header": [],
229
+ "body": {
230
+ "mode": "formdata",
231
+ "formdata": [
232
+ {
233
+ "key": "file",
234
+ "type": "file",
235
+ "src": [],
236
+ "description": "Image file to colorize"
237
+ },
238
+ {
239
+ "key": "positive_prompt",
240
+ "value": "colorize this image with vibrant colors",
241
+ "type": "text"
242
+ }
243
+ ]
244
+ },
245
+ "url": {
246
+ "raw": "{{base_url}}/colorize",
247
+ "host": [
248
+ "{{base_url}}"
249
+ ],
250
+ "path": [
251
+ "colorize"
252
+ ]
253
+ },
254
+ "description": "Colorize image without authentication (only works if DISABLE_AUTH=true)"
255
+ },
256
+ "response": []
257
+ }
258
+ ],
259
+ "variable": [
260
+ {
261
+ "key": "base_url",
262
+ "value": "https://YOUR_SPACE_URL",
263
+ "type": "string",
264
+ "description": "Base URL of your Hugging Face Space or local server"
265
+ },
266
+ {
267
+ "key": "firebase_token",
268
+ "value": "YOUR_FIREBASE_ID_TOKEN",
269
+ "type": "string",
270
+ "description": "Firebase authentication token"
271
+ },
272
+ {
273
+ "key": "result_id",
274
+ "value": "",
275
+ "type": "string",
276
+ "description": "Result ID from colorize response"
277
+ },
278
+ {
279
+ "key": "filename",
280
+ "value": "",
281
+ "type": "string",
282
+ "description": "Filename from colorize response (e.g., uuid.png)"
283
+ }
284
+ ]
285
  }
 
requirements.txt CHANGED
@@ -14,4 +14,6 @@ accelerate
14
  transformers
15
  diffusers
16
  safetensors
17
- ftfy
 
 
 
14
  transformers
15
  diffusers
16
  safetensors
17
+ ftfy
18
+ httpx
19
+ email-validator