cursorflow 2.7.7__py3-none-any.whl → 2.7.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cursorflow/cli.py CHANGED
@@ -1116,6 +1116,203 @@ def sessions(subcommand, name):
1116
1116
  else:
1117
1117
  console.print(f"[yellow]⚠️ Session not found: {name}[/yellow]")
1118
1118
 
1119
+ @main.command()
1120
+ @click.option('--base-url', '-u', required=True, help='Base URL of your application')
1121
+ @click.option('--path', '-p', default='/', help='Path to navigate to after login (e.g., /dashboard)')
1122
+ @click.option('--output', '-o', default='auth-capture.json', help='Output file for captured auth state')
1123
+ @click.option('--wait', type=int, default=60, help='Seconds to wait for manual login (default: 60)')
1124
+ @click.option('--browser', type=click.Choice(['chromium', 'chrome', 'firefox']), default='chromium', help='Browser to use (default: chromium)')
1125
+ def capture_auth(base_url, path, output, wait, browser):
1126
+ """
1127
+ Capture authentication state after manual SSO/OAuth login
1128
+
1129
+ Opens a browser, waits for you to complete SSO login manually,
1130
+ then captures all cookies, localStorage, and sessionStorage.
1131
+ Perfect for Google/Microsoft/Okta SSO authentication.
1132
+
1133
+ \b
1134
+ Process:
1135
+ 1. Browser opens to your app
1136
+ 2. Complete SSO login manually (Google, Microsoft, Okta, etc.)
1137
+ 3. Navigate to a protected page (e.g., /dashboard)
1138
+ 4. CursorFlow captures all auth state
1139
+ 5. Auth state saved to JSON file
1140
+ 6. Use in .cursorflow/config.json as cookie authentication
1141
+
1142
+ \b
1143
+ Examples:
1144
+ # Capture Google SSO auth
1145
+ cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
1146
+
1147
+ # Use system Chrome (more visible on macOS)
1148
+ cursorflow capture-auth -u http://localhost:3000 --browser chrome
1149
+
1150
+ # Capture with custom wait time
1151
+ cursorflow capture-auth -u http://localhost:3000 -p /dashboard --wait 120
1152
+
1153
+ # Save to custom file
1154
+ cursorflow capture-auth -u http://localhost:3000 --output google-sso.json
1155
+ """
1156
+ console.print(f"\n🔐 [bold]SSO Authentication Capture[/bold]")
1157
+ console.print(f"📍 Base URL: [cyan]{base_url}[/cyan]")
1158
+ console.print(f"🎯 Target path: [cyan]{path}[/cyan]")
1159
+ console.print(f"⏱️ Wait time: [yellow]{wait}[/yellow] seconds")
1160
+ console.print(f"📄 Output file: [green]{output}[/green]\n")
1161
+
1162
+ console.print("📋 [bold yellow]Instructions:[/bold yellow]")
1163
+ console.print(" 1. [bold]A Chromium browser window will open[/bold]")
1164
+ console.print(" 2. [yellow]Complete SSO login manually[/yellow] in that browser window")
1165
+ console.print(" 3. Navigate to a protected page (e.g., /dashboard)")
1166
+ console.print(" 4. Return here and [green]press Enter[/green] when fully logged in")
1167
+ console.print(" 5. CursorFlow will capture all auth state\n")
1168
+
1169
+ console.print("[bold red]⚠️ Look for the browser window - it may open behind other windows![/bold red]\n")
1170
+
1171
+ input("Press Enter to open browser and start capture...")
1172
+
1173
+ try:
1174
+ from playwright.async_api import async_playwright
1175
+ import json
1176
+
1177
+ async def capture_process():
1178
+ console.print("\n🚀 Starting Playwright...")
1179
+ async with async_playwright() as p:
1180
+ # Select browser based on user choice
1181
+ if browser == 'chrome':
1182
+ browser_type = p.chromium
1183
+ channel = 'chrome' # Use system Chrome if available
1184
+ elif browser == 'firefox':
1185
+ browser_type = p.firefox
1186
+ channel = None
1187
+ else: # chromium
1188
+ browser_type = p.chromium
1189
+ channel = None
1190
+
1191
+ # Launch browser in HEADED mode (user needs to interact)
1192
+ console.print(f"🌐 Launching [bold]{browser}[/bold] browser (headed mode)...")
1193
+ console.print("[yellow]👀 Watch for browser window - it should appear shortly...[/yellow]")
1194
+
1195
+ try:
1196
+ launch_options = {
1197
+ 'headless': False,
1198
+ 'slow_mo': 50,
1199
+ 'args': ['--start-maximized']
1200
+ }
1201
+ if channel:
1202
+ launch_options['channel'] = channel
1203
+
1204
+ browser_instance = await browser_type.launch(**launch_options)
1205
+ except Exception as e:
1206
+ console.print(f"[red]❌ Failed to launch browser: {e}[/red]")
1207
+ console.print("\n💡 Try installing Chromium:")
1208
+ console.print(" [cyan]playwright install chromium[/cyan]")
1209
+ raise
1210
+
1211
+ # Create context with viewport to ensure it's visible
1212
+ context = await browser_instance.new_context(
1213
+ viewport={'width': 1280, 'height': 720}
1214
+ )
1215
+ page = await context.new_page()
1216
+
1217
+ # Bring page to front
1218
+ await page.bring_to_front()
1219
+
1220
+ console.print(f"\n✅ [bold green]Browser window opened![/bold green]")
1221
+ console.print(f" 👉 [bold]If you don't see it, check behind other windows or different desktop spaces[/bold]")
1222
+ console.print(f"\n🌐 Navigating to: [cyan]{base_url}[/cyan]...")
1223
+ await page.goto(base_url)
1224
+ console.print(f"✅ Page loaded!")
1225
+
1226
+ console.print(f"\n⏳ [yellow]Complete your SSO login in the browser...[/yellow]")
1227
+ console.print(f" Waiting up to {wait} seconds...")
1228
+ console.print(f" [bold]Press Enter in this terminal when logged in and on {path}[/bold]\n")
1229
+
1230
+ # Wait for user to complete login
1231
+ import sys
1232
+ import select
1233
+
1234
+ # Simple blocking wait for Enter key
1235
+ input("Press Enter after completing login... ")
1236
+
1237
+ # Navigate to target path to ensure we're at the right place
1238
+ if path != '/':
1239
+ console.print(f"📍 Navigating to: [cyan]{path}[/cyan]")
1240
+ await page.goto(f"{base_url.rstrip('/')}{path}")
1241
+ await page.wait_for_load_state("networkidle")
1242
+
1243
+ console.print("\n📸 Capturing authentication state...")
1244
+
1245
+ # Capture all authentication data
1246
+ storage_state = await context.storage_state()
1247
+
1248
+ # Get localStorage
1249
+ local_storage = await page.evaluate("""
1250
+ () => {
1251
+ const storage = {};
1252
+ for (let i = 0; i < localStorage.length; i++) {
1253
+ const key = localStorage.key(i);
1254
+ storage[key] = localStorage.getItem(key);
1255
+ }
1256
+ return storage;
1257
+ }
1258
+ """)
1259
+
1260
+ # Get sessionStorage
1261
+ session_storage = await page.evaluate("""
1262
+ () => {
1263
+ const storage = {};
1264
+ for (let i = 0; i < sessionStorage.length; i++) {
1265
+ const key = sessionStorage.key(i);
1266
+ storage[key] = sessionStorage.getItem(key);
1267
+ }
1268
+ return storage;
1269
+ }
1270
+ """)
1271
+
1272
+ # Organize captured data
1273
+ auth_data = {
1274
+ "captured_at": time.strftime("%Y-%m-%d %H:%M:%S"),
1275
+ "base_url": base_url,
1276
+ "current_url": page.url,
1277
+ "method": "cookies",
1278
+ "cookies": storage_state.get("cookies", []),
1279
+ "localStorage": local_storage,
1280
+ "sessionStorage": session_storage,
1281
+ "usage_instructions": {
1282
+ "1": "Copy the 'cookies' array below",
1283
+ "2": "Add to .cursorflow/config.json under auth.cookies",
1284
+ "3": "Set auth.method to 'cookies'",
1285
+ "4": "Use with: cursorflow test --use-session <name>"
1286
+ }
1287
+ }
1288
+
1289
+ # Save to file
1290
+ output_path = Path(output)
1291
+ with open(output_path, 'w') as f:
1292
+ json.dump(auth_data, f, indent=2)
1293
+
1294
+ console.print(f"\n✅ Authentication state captured!")
1295
+ console.print(f"📄 Saved to: [green]{output_path.absolute()}[/green]")
1296
+ console.print(f"🍪 Captured {len(auth_data['cookies'])} cookies")
1297
+ console.print(f"💾 localStorage: {len(local_storage)} items")
1298
+ console.print(f"💾 sessionStorage: {len(session_storage)} items")
1299
+
1300
+ console.print(f"\n📋 [bold]Next steps:[/bold]")
1301
+ console.print(f" 1. Open: [cyan]{output}[/cyan]")
1302
+ console.print(f" 2. Copy the 'cookies' array")
1303
+ console.print(f" 3. Add to .cursorflow/config.json:")
1304
+ console.print(f'\n {{\n "auth": {{\n "method": "cookies",\n "cookies": [... paste here ...]\n }}\n }}\n')
1305
+ console.print(f" 4. Test with: [cyan]cursorflow test --use-session sso-user[/cyan]\n")
1306
+
1307
+ await browser_instance.close()
1308
+
1309
+ asyncio.run(capture_process())
1310
+
1311
+ except KeyboardInterrupt:
1312
+ console.print("\n[yellow]⚠️ Capture cancelled by user[/yellow]")
1313
+ except Exception as e:
1314
+ console.print(f"[red]❌ Error capturing auth: {escape(str(e))}[/red]")
1315
+
1119
1316
  @main.command()
1120
1317
  @click.option('--base-url', '-u', required=True)
1121
1318
  @click.option('--path', '-p', default='/', help='Path to navigate to')
@@ -1076,6 +1076,47 @@ cursorflow test --actions '[
1076
1076
  ]' --save-session "2fa-user"
1077
1077
  ```
1078
1078
 
1079
+ ### **SSO Authentication (Google, Microsoft, Okta)**
1080
+
1081
+ **SSO requires manual capture** because of external identity providers:
1082
+
1083
+ ```bash
1084
+ # 1. Capture SSO auth (opens browser, you login manually)
1085
+ cursorflow capture-auth --base-url http://localhost:3000 \
1086
+ --path /dashboard \
1087
+ --browser chrome \
1088
+ --output google-sso.json
1089
+
1090
+ # Browser opens (use --browser chrome for better visibility on macOS)
1091
+ # You complete SSO login, CursorFlow captures cookies
1092
+
1093
+ # 2. Copy cookies from google-sso.json to .cursorflow/config.json:
1094
+ {
1095
+ "auth": {
1096
+ "method": "cookies",
1097
+ "cookies": [/* paste from google-sso.json */]
1098
+ }
1099
+ }
1100
+
1101
+ # 3. Use captured auth
1102
+ cursorflow test --use-session "sso-user" --path /dashboard
1103
+ ```
1104
+
1105
+ **SSO providers supported:**
1106
+ - Google OAuth
1107
+ - Microsoft Azure AD
1108
+ - Okta
1109
+ - Auth0
1110
+ - Any OAuth/SAML provider
1111
+
1112
+ **When SSO tokens expire:**
1113
+ ```bash
1114
+ # Re-capture auth (SSO tokens typically expire in 1-24 hours)
1115
+ cursorflow capture-auth --base-url http://localhost:3000 \
1116
+ --path /dashboard \
1117
+ --output sso-refreshed.json
1118
+ ```
1119
+
1079
1120
  ### **Troubleshooting Auth**
1080
1121
 
1081
1122
  **Auth failing?**
@@ -1100,6 +1141,18 @@ cat .cursorflow/sessions/user_session.json
1100
1141
  cursorflow test --use-session "user" --fresh-session
1101
1142
  ```
1102
1143
 
1144
+ **SSO not working?**
1145
+ ```bash
1146
+ # Re-capture auth state
1147
+ cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
1148
+
1149
+ # Check if localStorage has tokens (some SSO stores tokens there)
1150
+ cat auth-capture.json | grep localStorage
1151
+
1152
+ # Test immediately after capture
1153
+ cursorflow test --use-session "sso-user" --path /dashboard
1154
+ ```
1155
+
1103
1156
  ## Best Practices
1104
1157
 
1105
1158
  ### **🔥 Hot Reload CSS Iteration Best Practices**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cursorflow
3
- Version: 2.7.7
3
+ Version: 2.7.9
4
4
  Summary: 🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis
5
5
  Author-email: GeekWarrior Development <rbush@cooltheory.com>
6
6
  License-Expression: MIT
@@ -177,6 +177,22 @@ cursorflow test --use-session "user" \
177
177
  - Form authentication (username/password)
178
178
  - Cookie authentication (JWT tokens, session cookies)
179
179
  - Header authentication (Bearer tokens, API keys)
180
+ - SSO authentication (Google, Microsoft, Okta, Auth0)
181
+
182
+ **SSO/OAuth Quick Start:**
183
+ ```bash
184
+ # Capture SSO auth (opens browser for manual login)
185
+ cursorflow capture-auth --base-url http://localhost:3000 \
186
+ --path /dashboard \
187
+ --browser chrome \
188
+ --output google-sso.json
189
+
190
+ # Use captured auth
191
+ # (Copy cookies from google-sso.json to .cursorflow/config.json)
192
+ cursorflow test --use-session "sso-user" --path /dashboard
193
+ ```
194
+
195
+ **Tip:** Use `--browser chrome` on macOS for better window visibility
180
196
 
181
197
  **See:** [Complete Authentication Guide](docs/user/USAGE_GUIDE.md#authentication--session-management)
182
198
 
@@ -1,7 +1,7 @@
1
1
  cursorflow/__init__.py,sha256=2V9xzG2tYxVWOTmSw2v9Jdbr7lSrMi_y2SMUMuNZdvw,2990
2
2
  cursorflow/auto_init.py,sha256=dXQaXXiXe4wkUP-jd8fcJ5fYVt7ASdTb47b7SzXymOM,6122
3
3
  cursorflow/auto_updater.py,sha256=oQ12TIMZ6Cm3HF-x9iRWFtvOLkRh-JWPqitS69-4roE,7851
4
- cursorflow/cli.py,sha256=5uObhh0ggolMX9DBHtQ8F74ewpzEcUxj9XkwoWyfCBA,80095
4
+ cursorflow/cli.py,sha256=M9TVyDEyi-2WVG4FxF2eAld9o0f35mbNBVFJeZ5Cyug,89736
5
5
  cursorflow/install_cursorflow_rules.py,sha256=DsZ0680y9JMuTKFXjdgYtOKIEAjBMsdwL8LmA9WEb5A,11864
6
6
  cursorflow/post_install.py,sha256=WieBiKWG0qBAQpF8iMVWUyb9Fr2Xky9qECTMPrlAbpE,2678
7
7
  cursorflow/updater.py,sha256=SroSQHQi5cYyzcOK_bf-WzmQmE7yeOs8qo3r__j-Z6E,19583
@@ -33,10 +33,10 @@ cursorflow/log_sources/local_file.py,sha256=GVnhsaifIdc41twXwbxRM9-fBeRDsknDpk5I
33
33
  cursorflow/log_sources/ssh_remote.py,sha256=_Kwh0bhRpKgq-0c98oaX2hN6h9cT-wCHlqY5NiWVCoY,8388
34
34
  cursorflow/rules/__init__.py,sha256=gPcA-IkhXj03sl7cvZV0wwo7CtEkcyuKs4y0F5oQbqE,458
35
35
  cursorflow/rules/cursorflow-installation.mdc,sha256=D55pzzDPAVVbE3gAtKPUGoT-2fvB-FI2l6yrTdzUIEo,10208
36
- cursorflow/rules/cursorflow-usage.mdc,sha256=oTp9RTyhZfRjX5DJq-R2lthT2E0nF-5gA-Ao13jjS5A,37490
37
- cursorflow-2.7.7.dist-info/licenses/LICENSE,sha256=e4QbjAsj3bW-xgQOvQelr8sGLYDoqc48k6cKgCr_pBU,1080
38
- cursorflow-2.7.7.dist-info/METADATA,sha256=M_sXtrzj4lW1jDIHuRnuPzrotxlv8scA78PdvRQORKg,20838
39
- cursorflow-2.7.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
- cursorflow-2.7.7.dist-info/entry_points.txt,sha256=-Ed_n4Uff7wClEtWS-Py6xmQabecB9f0QAOjX0w7ljA,51
41
- cursorflow-2.7.7.dist-info/top_level.txt,sha256=t1UZwRyZP4u-ng2CEcNHmk_ZT4ibQxoihB2IjTF7ovc,11
42
- cursorflow-2.7.7.dist-info/RECORD,,
36
+ cursorflow/rules/cursorflow-usage.mdc,sha256=b1hhZ9S6Oc5bElTM75QOLIgwbX0jCc1_25MwEd8Z--k,38844
37
+ cursorflow-2.7.9.dist-info/licenses/LICENSE,sha256=e4QbjAsj3bW-xgQOvQelr8sGLYDoqc48k6cKgCr_pBU,1080
38
+ cursorflow-2.7.9.dist-info/METADATA,sha256=9wRJgyI0SRgdHxsYH0Zq5bywy5bNwP1RYP33yDDsS-U,21329
39
+ cursorflow-2.7.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
+ cursorflow-2.7.9.dist-info/entry_points.txt,sha256=-Ed_n4Uff7wClEtWS-Py6xmQabecB9f0QAOjX0w7ljA,51
41
+ cursorflow-2.7.9.dist-info/top_level.txt,sha256=t1UZwRyZP4u-ng2CEcNHmk_ZT4ibQxoihB2IjTF7ovc,11
42
+ cursorflow-2.7.9.dist-info/RECORD,,