@@ -283,6 +283,227 @@ defmodule LightningWeb.CredentialLive.KeychainCredentialFormComponentTest do
283283 end
284284 end
285285
286+ describe "keychain credential form - from_collab_editor flag" do
287+ test "edit with from_collab_editor skips push_event" , % { conn: conn } do
288+ user = insert ( :user )
289+
290+ project =
291+ insert ( :project , project_users: [ % { user_id: user . id , role: :owner } ] )
292+
293+ project_user =
294+ Lightning.Repo . get_by! (
295+ Lightning.Projects.ProjectUser ,
296+ user_id: user . id ,
297+ project_id: project . id
298+ )
299+
300+ keychain_credential =
301+ insert ( :keychain_credential ,
302+ name: "Original" ,
303+ path: "$.original" ,
304+ project: project ,
305+ created_by: user
306+ )
307+
308+ conn = log_in_user ( conn , user )
309+
310+ { :ok , view , _html } =
311+ live_isolated ( conn , TestKeychainCredentialEditorLive ,
312+ session: % {
313+ "current_user" => user ,
314+ "project" => project ,
315+ "project_user" => project_user ,
316+ "keychain_credential" => keychain_credential ,
317+ "action" => :edit ,
318+ "from_collab_editor" => true
319+ }
320+ )
321+
322+ # Update should work without push_event
323+ view
324+ |> element ( "form[phx-submit='save']" )
325+ |> render_submit ( % {
326+ "keychain_credential" => % {
327+ "name" => "Updated from Collab" ,
328+ "path" => "$.updated"
329+ }
330+ } )
331+
332+ # Verify update succeeded
333+ updated =
334+ Lightning.Repo . get! (
335+ Credentials.KeychainCredential ,
336+ keychain_credential . id
337+ )
338+
339+ assert updated . name == "Updated from Collab"
340+ end
341+
342+ test "create with from_collab_editor skips push_event" , % { conn: conn } do
343+ user = insert ( :user )
344+
345+ project =
346+ insert ( :project , project_users: [ % { user_id: user . id , role: :owner } ] )
347+
348+ project_user =
349+ Lightning.Repo . get_by! (
350+ Lightning.Projects.ProjectUser ,
351+ user_id: user . id ,
352+ project_id: project . id
353+ )
354+
355+ keychain_credential = % Credentials.KeychainCredential {
356+ project_id: project . id ,
357+ created_by_id: user . id
358+ }
359+
360+ conn = log_in_user ( conn , user )
361+
362+ { :ok , view , _html } =
363+ live_isolated ( conn , TestKeychainCredentialEditorLive ,
364+ session: % {
365+ "current_user" => user ,
366+ "project" => project ,
367+ "project_user" => project_user ,
368+ "keychain_credential" => keychain_credential ,
369+ "action" => :new ,
370+ "from_collab_editor" => true
371+ }
372+ )
373+
374+ # Create should work without push_event
375+ view
376+ |> element ( "form[phx-submit='save']" )
377+ |> render_submit ( % {
378+ "keychain_credential" => % {
379+ "name" => "Created from Collab" ,
380+ "path" => "$.key"
381+ }
382+ } )
383+
384+ # Verify creation succeeded
385+ created =
386+ Lightning.Repo . get_by ( Credentials.KeychainCredential ,
387+ name: "Created from Collab"
388+ )
389+
390+ assert created
391+ end
392+
393+ test "viewer edit with from_collab_editor still blocks unauthorized" , % {
394+ conn: conn
395+ } do
396+ owner = insert ( :user )
397+ viewer = insert ( :user )
398+
399+ project =
400+ insert ( :project ,
401+ project_users: [
402+ % { user_id: owner . id , role: :owner } ,
403+ % { user_id: viewer . id , role: :viewer }
404+ ]
405+ )
406+
407+ project_user =
408+ Lightning.Repo . get_by! (
409+ Lightning.Projects.ProjectUser ,
410+ user_id: viewer . id ,
411+ project_id: project . id
412+ )
413+
414+ keychain_credential =
415+ insert ( :keychain_credential ,
416+ name: "Protected" ,
417+ path: "$.original" ,
418+ project: project ,
419+ created_by: owner
420+ )
421+
422+ conn = log_in_user ( conn , viewer )
423+
424+ { :ok , view , _html } =
425+ live_isolated ( conn , TestKeychainCredentialEditorLive ,
426+ session: % {
427+ "current_user" => viewer ,
428+ "project" => project ,
429+ "project_user" => project_user ,
430+ "keychain_credential" => keychain_credential ,
431+ "action" => :edit ,
432+ "from_collab_editor" => true
433+ }
434+ )
435+
436+ # Try to update - should be blocked by permission check
437+ view
438+ |> element ( "form[phx-submit='save']" )
439+ |> render_submit ( % {
440+ "keychain_credential" => % {
441+ "name" => "Hacked" ,
442+ "path" => "$.hacked"
443+ }
444+ } )
445+
446+ # Verify NOT updated
447+ unchanged =
448+ Lightning.Repo . get! (
449+ Credentials.KeychainCredential ,
450+ keychain_credential . id
451+ )
452+
453+ assert unchanged . name == "Protected"
454+ end
455+
456+ test "viewer create with from_collab_editor still blocks unauthorized" , % {
457+ conn: conn
458+ } do
459+ viewer = insert ( :user )
460+
461+ project =
462+ insert ( :project , project_users: [ % { user_id: viewer . id , role: :viewer } ] )
463+
464+ project_user =
465+ Lightning.Repo . get_by! (
466+ Lightning.Projects.ProjectUser ,
467+ user_id: viewer . id ,
468+ project_id: project . id
469+ )
470+
471+ keychain_credential = % Credentials.KeychainCredential {
472+ project_id: project . id ,
473+ created_by_id: viewer . id
474+ }
475+
476+ conn = log_in_user ( conn , viewer )
477+
478+ { :ok , view , _html } =
479+ live_isolated ( conn , TestKeychainCredentialEditorLive ,
480+ session: % {
481+ "current_user" => viewer ,
482+ "project" => project ,
483+ "project_user" => project_user ,
484+ "keychain_credential" => keychain_credential ,
485+ "action" => :new ,
486+ "from_collab_editor" => true
487+ }
488+ )
489+
490+ # Try to create - should be blocked
491+ view
492+ |> element ( "form[phx-submit='save']" )
493+ |> render_submit ( % {
494+ "keychain_credential" => % {
495+ "name" => "Unauthorized" ,
496+ "path" => "$.id"
497+ }
498+ } )
499+
500+ # Verify NOT created
501+ assert Lightning.Repo . get_by ( Credentials.KeychainCredential ,
502+ name: "Unauthorized"
503+ ) == nil
504+ end
505+ end
506+
286507 describe "keychain credential form - permissions" do
287508 test "viewer cannot create keychain credential" , % { conn: conn } do
288509 viewer = insert ( :user )
0 commit comments