cursorflow 2.7.7__py3-none-any.whl → 2.7.8__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,158 @@ 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
+ def capture_auth(base_url, path, output, wait):
1125
+ """
1126
+ Capture authentication state after manual SSO/OAuth login
1127
+
1128
+ Opens a browser, waits for you to complete SSO login manually,
1129
+ then captures all cookies, localStorage, and sessionStorage.
1130
+ Perfect for Google/Microsoft/Okta SSO authentication.
1131
+
1132
+ \b
1133
+ Process:
1134
+ 1. Browser opens to your app
1135
+ 2. Complete SSO login manually (Google, Microsoft, Okta, etc.)
1136
+ 3. Navigate to a protected page (e.g., /dashboard)
1137
+ 4. CursorFlow captures all auth state
1138
+ 5. Auth state saved to JSON file
1139
+ 6. Use in .cursorflow/config.json as cookie authentication
1140
+
1141
+ \b
1142
+ Examples:
1143
+ # Capture Google SSO auth
1144
+ cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
1145
+
1146
+ # Capture with custom wait time
1147
+ cursorflow capture-auth -u http://localhost:3000 -p /dashboard --wait 120
1148
+
1149
+ # Save to custom file
1150
+ cursorflow capture-auth -u http://localhost:3000 --output google-sso.json
1151
+ """
1152
+ console.print(f"\n🔐 SSO Authentication Capture")
1153
+ console.print(f"📍 Base URL: [cyan]{base_url}[/cyan]")
1154
+ console.print(f"🎯 Target path: [cyan]{path}[/cyan]")
1155
+ console.print(f"⏱️ Wait time: [yellow]{wait}[/yellow] seconds")
1156
+ console.print(f"📄 Output file: [green]{output}[/green]\n")
1157
+
1158
+ console.print("📋 [bold]Instructions:[/bold]")
1159
+ console.print(" 1. Browser will open to your application")
1160
+ console.print(" 2. [yellow]Complete SSO login manually[/yellow] (Google, Microsoft, Okta, etc.)")
1161
+ console.print(" 3. Navigate to a protected page (e.g., /dashboard)")
1162
+ console.print(" 4. [green]Press Enter[/green] when fully logged in")
1163
+ console.print(" 5. CursorFlow will capture all auth state\n")
1164
+
1165
+ input("Press Enter to open browser and start capture...")
1166
+
1167
+ try:
1168
+ from playwright.async_api import async_playwright
1169
+ import json
1170
+
1171
+ async def capture_process():
1172
+ async with async_playwright() as p:
1173
+ # Launch browser in HEADED mode (user needs to interact)
1174
+ browser = await p.chromium.launch(headless=False)
1175
+ context = await browser.new_context()
1176
+ page = await context.new_page()
1177
+
1178
+ console.print(f"\n🌐 Opening browser to: [cyan]{base_url}[/cyan]")
1179
+ await page.goto(base_url)
1180
+
1181
+ console.print(f"\n⏳ [yellow]Complete your SSO login in the browser...[/yellow]")
1182
+ console.print(f" Waiting up to {wait} seconds...")
1183
+ console.print(f" [bold]Press Enter in this terminal when logged in and on {path}[/bold]\n")
1184
+
1185
+ # Wait for user to complete login
1186
+ import sys
1187
+ import select
1188
+
1189
+ # Simple blocking wait for Enter key
1190
+ input("Press Enter after completing login... ")
1191
+
1192
+ # Navigate to target path to ensure we're at the right place
1193
+ if path != '/':
1194
+ console.print(f"📍 Navigating to: [cyan]{path}[/cyan]")
1195
+ await page.goto(f"{base_url.rstrip('/')}{path}")
1196
+ await page.wait_for_load_state("networkidle")
1197
+
1198
+ console.print("\n📸 Capturing authentication state...")
1199
+
1200
+ # Capture all authentication data
1201
+ storage_state = await context.storage_state()
1202
+
1203
+ # Get localStorage
1204
+ local_storage = await page.evaluate("""
1205
+ () => {
1206
+ const storage = {};
1207
+ for (let i = 0; i < localStorage.length; i++) {
1208
+ const key = localStorage.key(i);
1209
+ storage[key] = localStorage.getItem(key);
1210
+ }
1211
+ return storage;
1212
+ }
1213
+ """)
1214
+
1215
+ # Get sessionStorage
1216
+ session_storage = await page.evaluate("""
1217
+ () => {
1218
+ const storage = {};
1219
+ for (let i = 0; i < sessionStorage.length; i++) {
1220
+ const key = sessionStorage.key(i);
1221
+ storage[key] = sessionStorage.getItem(key);
1222
+ }
1223
+ return storage;
1224
+ }
1225
+ """)
1226
+
1227
+ # Organize captured data
1228
+ auth_data = {
1229
+ "captured_at": time.strftime("%Y-%m-%d %H:%M:%S"),
1230
+ "base_url": base_url,
1231
+ "current_url": page.url,
1232
+ "method": "cookies",
1233
+ "cookies": storage_state.get("cookies", []),
1234
+ "localStorage": local_storage,
1235
+ "sessionStorage": session_storage,
1236
+ "usage_instructions": {
1237
+ "1": "Copy the 'cookies' array below",
1238
+ "2": "Add to .cursorflow/config.json under auth.cookies",
1239
+ "3": "Set auth.method to 'cookies'",
1240
+ "4": "Use with: cursorflow test --use-session <name>"
1241
+ }
1242
+ }
1243
+
1244
+ # Save to file
1245
+ output_path = Path(output)
1246
+ with open(output_path, 'w') as f:
1247
+ json.dump(auth_data, f, indent=2)
1248
+
1249
+ console.print(f"\n✅ Authentication state captured!")
1250
+ console.print(f"📄 Saved to: [green]{output_path.absolute()}[/green]")
1251
+ console.print(f"🍪 Captured {len(auth_data['cookies'])} cookies")
1252
+ console.print(f"💾 localStorage: {len(local_storage)} items")
1253
+ console.print(f"💾 sessionStorage: {len(session_storage)} items")
1254
+
1255
+ console.print(f"\n📋 [bold]Next steps:[/bold]")
1256
+ console.print(f" 1. Open: [cyan]{output}[/cyan]")
1257
+ console.print(f" 2. Copy the 'cookies' array")
1258
+ console.print(f" 3. Add to .cursorflow/config.json:")
1259
+ console.print(f'\n {{\n "auth": {{\n "method": "cookies",\n "cookies": [... paste here ...]\n }}\n }}\n')
1260
+ console.print(f" 4. Test with: [cyan]cursorflow test --use-session sso-user[/cyan]\n")
1261
+
1262
+ await browser.close()
1263
+
1264
+ asyncio.run(capture_process())
1265
+
1266
+ except KeyboardInterrupt:
1267
+ console.print("\n[yellow]⚠️ Capture cancelled by user[/yellow]")
1268
+ except Exception as e:
1269
+ console.print(f"[red]❌ Error capturing auth: {escape(str(e))}[/red]")
1270
+
1119
1271
  @main.command()
1120
1272
  @click.option('--base-url', '-u', required=True)
1121
1273
  @click.option('--path', '-p', default='/', help='Path to navigate to')
@@ -1076,6 +1076,45 @@ 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
+ --output google-sso.json
1088
+
1089
+ # Browser opens, you complete SSO login, CursorFlow captures cookies
1090
+
1091
+ # 2. Copy cookies from google-sso.json to .cursorflow/config.json:
1092
+ {
1093
+ "auth": {
1094
+ "method": "cookies",
1095
+ "cookies": [/* paste from google-sso.json */]
1096
+ }
1097
+ }
1098
+
1099
+ # 3. Use captured auth
1100
+ cursorflow test --use-session "sso-user" --path /dashboard
1101
+ ```
1102
+
1103
+ **SSO providers supported:**
1104
+ - Google OAuth
1105
+ - Microsoft Azure AD
1106
+ - Okta
1107
+ - Auth0
1108
+ - Any OAuth/SAML provider
1109
+
1110
+ **When SSO tokens expire:**
1111
+ ```bash
1112
+ # Re-capture auth (SSO tokens typically expire in 1-24 hours)
1113
+ cursorflow capture-auth --base-url http://localhost:3000 \
1114
+ --path /dashboard \
1115
+ --output sso-refreshed.json
1116
+ ```
1117
+
1079
1118
  ### **Troubleshooting Auth**
1080
1119
 
1081
1120
  **Auth failing?**
@@ -1100,6 +1139,18 @@ cat .cursorflow/sessions/user_session.json
1100
1139
  cursorflow test --use-session "user" --fresh-session
1101
1140
  ```
1102
1141
 
1142
+ **SSO not working?**
1143
+ ```bash
1144
+ # Re-capture auth state
1145
+ cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
1146
+
1147
+ # Check if localStorage has tokens (some SSO stores tokens there)
1148
+ cat auth-capture.json | grep localStorage
1149
+
1150
+ # Test immediately after capture
1151
+ cursorflow test --use-session "sso-user" --path /dashboard
1152
+ ```
1153
+
1103
1154
  ## Best Practices
1104
1155
 
1105
1156
  ### **🔥 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.8
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,19 @@ 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
+ --output google-sso.json
188
+
189
+ # Use captured auth
190
+ # (Copy cookies from google-sso.json to .cursorflow/config.json)
191
+ cursorflow test --use-session "sso-user" --path /dashboard
192
+ ```
180
193
 
181
194
  **See:** [Complete Authentication Guide](docs/user/USAGE_GUIDE.md#authentication--session-management)
182
195
 
@@ -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=Tt3I9d6SFplJjM4UPdxXklGjh1kt511-irE_jqDAw_A,87342
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=wv7EOeybBUmgYGux9yE_8SWAgoNYa5DfbT5sC44WNOU,38768
37
+ cursorflow-2.7.8.dist-info/licenses/LICENSE,sha256=e4QbjAsj3bW-xgQOvQelr8sGLYDoqc48k6cKgCr_pBU,1080
38
+ cursorflow-2.7.8.dist-info/METADATA,sha256=aCPcMbLb-PrXzfCqebLSdwjW17Fs33sRVteAa81uRlM,21237
39
+ cursorflow-2.7.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
+ cursorflow-2.7.8.dist-info/entry_points.txt,sha256=-Ed_n4Uff7wClEtWS-Py6xmQabecB9f0QAOjX0w7ljA,51
41
+ cursorflow-2.7.8.dist-info/top_level.txt,sha256=t1UZwRyZP4u-ng2CEcNHmk_ZT4ibQxoihB2IjTF7ovc,11
42
+ cursorflow-2.7.8.dist-info/RECORD,,