diff options
| -rw-r--r-- | pearl.el | 9 | ||||
| -rw-r--r-- | tests/test-pearl-local-views.el | 33 |
2 files changed, 41 insertions, 1 deletions
@@ -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 |
