aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pearl.el9
-rw-r--r--tests/test-pearl-local-views.el33
2 files changed, 41 insertions, 1 deletions
diff --git a/pearl.el b/pearl.el
index d984876..38252b1 100644
--- a/pearl.el
+++ b/pearl.el
@@ -3962,7 +3962,11 @@ the id so it can be deleted by hand)."
(message "Cancelled; no local view deleted"))
((not (assoc name pearl-local-views))
(user-error "No local view named %s" name))
- ((not (yes-or-no-p (format "Delete local view %s? " name)))
+ ((progn
+ ;; Refuse a cross-account entry before the confirm or any customViewDelete:
+ ;; deleting under the wrong account could target the wrong remote workspace.
+ (pearl--require-local-view-account name (cdr (assoc name pearl-local-views)))
+ (not (yes-or-no-p (format "Delete local view %s? " name))))
(message "Kept local view %s" name))
(t
(let ((view-id (plist-get (cdr (assoc name pearl-local-views))
@@ -4295,6 +4299,9 @@ the user can re-publish with Replace to reconcile."
(let ((entry (assoc name pearl-local-views)))
(unless entry
(user-error "No local view named %s" name))
+ ;; Refuse a cross-account entry before any customViewCreate/Update: publishing
+ ;; under the wrong account would create the view in the wrong workspace.
+ (pearl--require-local-view-account name (cdr entry))
(let* ((spec (cdr entry))
(filter-plist (plist-get spec :filter))
(existing-view-id (plist-get spec :linear-view-id))
diff --git a/tests/test-pearl-local-views.el b/tests/test-pearl-local-views.el
index 71fb173..b474e74 100644
--- a/tests/test-pearl-local-views.el
+++ b/tests/test-pearl-local-views.el
@@ -167,5 +167,38 @@
(should (equal (plist-get spec :filter) '(:open t)))
(should (equal (plist-get spec :linear-view-id) "v-1")))))))
+;;; account guard on publish and delete -- no Linear call on mismatch (Phase 5)
+
+(ert-deftest test-pearl-publish-local-view-refuses-cross-account ()
+ "Publishing a cross-account local view errors before any customViewCreate/Update."
+ (let ((pearl-local-views '(("v" :filter (:open t) :account "acct-b")))
+ (pearl-accounts '(("acct-a" . x) ("acct-b" . y)))
+ (created nil))
+ (cl-letf (((symbol-function 'pearl--current-account-context)
+ (lambda () '(:name "acct-a")))
+ ((symbol-function 'pearl--require-account-context) (lambda (&rest _) nil))
+ ((symbol-function 'pearl--customview-create-async)
+ (lambda (&rest _) (setq created t)))
+ ((symbol-function 'pearl--customview-update-async)
+ (lambda (&rest _) (setq created t))))
+ (should-error (pearl-publish-local-view "v") :type 'user-error)
+ (should-not created))))
+
+(ert-deftest test-pearl-delete-local-view-refuses-cross-account-no-linear-call ()
+ "Deleting a cross-account local view errors before the confirm or customViewDelete."
+ (let ((pearl-local-views '(("v" :filter (:open t)
+ :linear-view-id "vid" :account "acct-b")))
+ (pearl-accounts '(("acct-a" . x)))
+ (deleted nil) (confirmed nil))
+ (cl-letf (((symbol-function 'pearl--current-account-context)
+ (lambda () '(:name "acct-a")))
+ ((symbol-function 'pearl--customview-delete-async)
+ (lambda (&rest _) (setq deleted t)))
+ ((symbol-function 'yes-or-no-p)
+ (lambda (&rest _) (setq confirmed t) t)))
+ (should-error (pearl-delete-local-view "v") :type 'user-error)
+ (should-not deleted)
+ (should-not confirmed))))
+
(provide 'test-pearl-local-views)
;;; test-pearl-local-views.el ends here