/workspace/bulkmailer/static/gmail-accounts.html-33-
/workspace/bulkmailer/static/gmail-accounts.html-34- Upload the client_secret_*.json file from Google Cloud Console → APIs & Services → Credentials.
/workspace/bulkmailer/static/gmail-accounts.html-35- The file is validated, encrypted, and stored locally; the secret is never echoed back.
/workspace/bulkmailer/static/gmail-accounts.html:36: Redirect URI for this app: /auth/google/callback
/workspace/bulkmailer/static/gmail-accounts.html-37-
/workspace/bulkmailer/static/gmail-accounts.html-38-
/workspace/bulkmailer/static/gmail-accounts.html-42-
--
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-80- const fd = new FormData(); fd.append("file", f);
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-81- try {
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-82- const d = await api("/gmail/accounts/import-config", { method: "POST", body: fd });
/workspace/bulkmailer/static/js/pages/gmail-accounts.js:83: $("#cfgRedirect").textContent = d.redirect_uri;
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-84- toast(`Configuration imported (project: ${d.project_id}). You can now connect accounts.`, "ok");
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-85- $("#cfgForm").reset();
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-86- } catch (err) { toast("Import failed: " + err.message, "err"); }
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-87- });
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-88-
/workspace/bulkmailer/static/js/pages/gmail-accounts.js-89- // ---- Clear all ----
---endpoint---
192- {"count": len(rows), "revoked_at_google": revoked},
193- request.client.host if request else None)
194- return {"ok": True, "removed": len(rows), "revoked_at_google": revoked}
195-
196-
197:@router.post("/accounts/import-config")
198-async def import_client_config(file: UploadFile = File(...),
199- user: User = Depends(get_current_user_csrf),
200- db: AsyncSession = Depends(get_db), request: Request = None):
201- """Import & validate a Google OAuth client_secret JSON (never echoed back)."""
202- from app.core.config import settings
203- content = await file.read()
204- if len(content) > 1024 * 512:
205- raise HTTPException(413, "File too large (max 512 KB)")
206- if not file.filename.lower().endswith(".json"):
207- raise HTTPException(400, "Only .json configuration files are accepted")
208- try:
209- parsed = gmail_service.parse_client_json(content)
210- except gmail_service.GmailOauthError as e:
211- raise HTTPException(400, str(e))
212- row = OAuthClientConfig(
213- name=parsed["project_id"] or file.filename[:100],
214- user_id=user.id,
215- client_id=parsed["client_id"],
216- client_secret=parsed["client_secret"], # encrypted via property setter
217- project_id=parsed["project_id"],
218- redirect_uri=f"{settings.BASE_URL}/auth/google/callback",
219- )
220- db.add(row)
221- await db.commit()
222- await log_audit(db, user.id, "oauth_config.imported", "oauth_client_config", row.id,
223- {"project": parsed["project_id"]}, request.client.host if request else None)
224- return {"ok": True, "id": row.id, "project_id": parsed["project_id"],
225- "client_id_preview": parsed["client_id"][:12] + "…",
226- "redirect_uri": row.redirect_uri}
227-