Skip to content

Add board visibility (private/shared/public) for multiuser mode#122

Open
Copilot wants to merge 3 commits intolstein/feature/workflow-isolation-in-multiuser-modefrom
copilot/enhancement-allow-shared-boards
Open

Add board visibility (private/shared/public) for multiuser mode#122
Copilot wants to merge 3 commits intolstein/feature/workflow-isolation-in-multiuser-modefrom
copilot/enhancement-allow-shared-boards

Conversation

Copy link

Copilot AI commented Mar 9, 2026

Adds three visibility levels for boards in multiuser mode: private (owner/admin only), shared (all users can view, owner/admin can modify), and public (all users can view and write; only owner/admin can rename or delete).

Summary

Backend

  • BoardVisibility enum (private | shared | public) added to board_records_common.py; board_visibility field added to BoardRecord and BoardChanges
  • Migration 29: adds board_visibility TEXT NOT NULL DEFAULT 'private' column to boards table; migrates existing is_public=1 rows to 'public'
  • board_records_sqlite.py: update() handles board_visibility; get_many()/get_all() queries use board_visibility IN ('shared', 'public') instead of is_public = 1
  • boards.py router: get_board and list_all_board_image_names allow non-owner access for shared/public boards; update_board and delete_board remain owner/admin-only

Frontend

  • schema.ts: BoardVisibility enum, board_visibility field on BoardDTO and BoardChanges
  • BoardContextMenu.tsx: "Set Private / Set Shared / Set Public" menu items (owner and admins only); visibility handlers extracted into named useCallback hooks to comply with react/jsx-no-bind; Delete Board, Archive, and Unarchive menu items are disabled (greyed out) for non-owners of shared and public boards
  • BoardEditableTitle.tsx: pencil icon and double-click rename hidden for non-owners of shared and public boards
  • GalleryBoard.tsx: blue share icon badge for shared boards, green globe badge for public boards; DnD drop target disabled for non-owners of shared boards
  • GalleryImage.tsx: drag-out disabled for non-owners viewing a shared board, preventing images from being moved out
  • GalleryItemDeleteIconButton.tsx: shift+hover trash icon hidden when viewing a shared board as a non-owner
  • ContextMenuItemDeleteImage.tsx: delete image menu item hidden when viewing a shared board as a non-owner
  • ContextMenuItemChangeBoard.tsx: "Change Board" menu item disabled when viewing a shared board as a non-owner
  • MultipleSelectionMenuItems.tsx: "Change Board" and "Delete Selection" disabled when viewing a shared board as a non-owner
  • InvokeQueueBackButton.tsx: main Invoke/generate button disabled when the auto-add board is a shared board the current user does not own
  • FloatingLeftPanelButtons.tsx: floating invoke icon button also disabled when the auto-add board is a shared board the current user does not own
  • ChangeBoardModal.tsx: destination board list filtered to exclude shared boards the current user does not own, preventing moves into read-only boards
  • New hooksuseBoardAccess(board) returns { canWriteImages, canRenameBoard, canDeleteBoard }; useSelectedBoard() and useAutoAddBoard() look up the relevant BoardDTO from the RTK Query cache
  • en.json: i18n strings for all new visibility UI

Tests

10 new tests in test_boards_multiuser.py covering default visibility, setting each level, cross-user access enforcement, reversion to private, non-owner restriction, and admin override. All 33 tests pass.

Related Issues / Discussions

QA Instructions

  1. Enable multiuser mode (multiuser: true in config)
  2. Create a board as User A — verify it defaults to private (User B cannot see it)
  3. Right-click board → Set Shared — verify User B can now view it but:
    • The pencil icon is hidden and double-clicking the name does nothing
    • The Delete Board, Archive, and Unarchive options in the context menu are greyed out
    • The trash icon on images and "Delete Image" context menu item are hidden
    • Both the main Invoke button and the floating invoke icon button are disabled if this shared board is the auto-add target
    • Dragging images onto the board is disabled
    • Dragging images out of the board is disabled
    • The "Change Board" destination list does not include this shared board
  4. Set to Public — verify User B can view and write images (including generating into it), but cannot rename, delete, or archive the board
  5. Set back to Private — verify User B loses access again
  6. Verify shared/public boards show the appropriate icon badge in the boards list
  7. Verify admins retain full access to all boards regardless of visibility

Merge Plan

Migration 29 adds a new column with a safe default ('private'), so existing databases upgrade non-destructively. No redux slice changes.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)
Original prompt

This section details on the original issue you should resolve

<issue_title>[enhancement]: Allow shared boards in multiuser mode</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Contact Details

No response

What should this feature add?

Currently when multiuser mode is active, all user-created boards are strictly private. They are entirely isolated from each other.

I would like it to be possible to designate a board as one of "Private," "Shared," or "Public".

  • Private board -- Only visible to the user who created it.
  • Shared board -- Visible to all users. Read/Write for the user who created it (they can add images to it and delete images from it). Read-only for other users.
  • Public board -- Visible and Read/Write to all users.

The Administrator should continue to be able to see all boards created by all users and have read/write access to them.

There is code in the lstein/feature/workflow-isolation-in-multiuser-mode that enables sharing of workflows. I have designated this branch as the base for this pull request.

In terms of user interface, try adding a discrete pulldown menu to the right of the board's name can be used to choose among the three board types. Something small like a caret (^) mark, and badges that appear when the board is shared or public.

Alternatives

No response

Additional Content

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Add support for shared boards in multiuser mode Add board visibility (private/shared/public) for multiuser mode Mar 9, 2026
@lstein
Copy link
Owner

lstein commented Mar 9, 2026

@copilot I'm getting the following eslint errors:

/home/lstein/Projects/InvokeAI-lstein/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx
  130:17  error  JSX props should not use arrow functions  react/jsx-no-bind
  137:17  error  JSX props should not use arrow functions  react/jsx-no-bind
  144:17  error  JSX props should not use arrow functions  react/jsx-no-bind

Copy link
Author

Copilot AI commented Mar 9, 2026

@copilot I'm getting the following eslint errors:

/home/lstein/Projects/InvokeAI-lstein/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx

...

Fixed in 0d7f7ea. Replaced the three inline arrow functions with dedicated useCallback handlers (handleSetVisibilityPrivate, handleSetVisibilityShared, handleSetVisibilityPublic) that each delegate to the shared handleSetVisibility callback.

@lstein lstein marked this pull request as ready for review March 9, 2026 22:24
@lstein lstein self-requested a review as a code owner March 9, 2026 22:24
Copy link
Owner

@lstein lstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few glitches to correct. In these examples, "Board A Public" and "Board A Shared" are owned by user A and are public and shared respectively. User B is a non-administrative user.

  1. Shared boards are read-only for non-owners. So when B is logged in he should not be able to generate images and store them in Board A Shared, to move images in and out of Board A Shared, or delete images from Board A Shared. As much as possible, user interfaces that attempt to modify the board should be disabled, so that if Board A Shared is the auto save target for image generation, the generation buttons should be disabled.
  2. Disable the option to delete a public or shared board when a non-owner tries to do so. So when B is logged in and right clicks on Board A Shared or Board A Public, the Delete menu option is greyed out.
  3. Similarly, the trash-can icon to delete individual image files, and the delete image menu item should be deleted when B is logged in and working with Board A Shared.
  4. The pencil icon should be hidden from Board A Shared and Board A Public when B is logged in. Only the owner (or the administrator) should be able to edit the name of a shared or public board.

Copy link
Author

Copilot AI commented Mar 9, 2026

A few glitches to correct. In these examples, "Board A Public" and "Board A Shared" are owned by user A and are public and shared respectively. User B is a non-administrative user.

  1. Shared boards a...

Addressed in a0b90b1. Here's what was changed:

  1. Shared board read-only: GalleryItemDeleteIconButton (shift+hover trash icon) and ContextMenuItemDeleteImage hide when a non-owner views a shared board. ContextMenuItemChangeBoard and multi-select "Delete Selection"/"Change Board" are disabled too. The DnD drop target on shared boards is disabled for non-owners, preventing drag-in. The Invoke button is disabled when the auto-add board is shared and the user is not the owner.

  2. Delete board greyed out: BoardContextMenu now sets isDisabled={!canDeleteBoard} on the Delete Board menu item — greys it out for non-owners of both shared and public boards.

  3. Trash icon / delete image hidden for shared: Items 6–9 above all use the new useSelectedBoard()useBoardAccess() chain. When the selected board is shared and the current user is not the owner, canWriteImages is false and the delete controls are hidden/disabled.

  4. Pencil icon hidden for shared and public: BoardEditableTitle uses useBoardAccess(board).canRenameBoard; when false (non-owner of shared or public board), the pencil icon is not rendered and double-clicking the title has no effect.

New helpers: useBoardAccess(board) returns { canWriteImages, canRenameBoard, canDeleteBoard }. Logic: owner or admin → full access; public board non-owner → can write images but not rename/delete; shared board non-owner → read-only.

@lstein lstein self-requested a review March 10, 2026 02:19
Copy link
Owner

@lstein lstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still some issues:

  1. When a read-only shared board is selected, and I am not its owner, the "Add to Queue" button is active and lets me generate into the shared board. This button should be disabled when the target is a shared board and I am not the owner of the board or the administrator.
  2. I am able to drag an image out of a shared board and into a private board, thereby deleting it from the shared board, even when I am not the owner of the shared board. Dragging from a shared board when I am not the owner (or administrator) should be disabled.
  3. I can right click on an image in a private or public board and select "Change Board" to move it into a shared board, even when I am not the owner of the shared board. The drop target for a shared board should be disabled unless I am the owner (or administrator).
  4. I can archive a public or shared board, even when I am not the owner of that board. If I am not the owner, the archive menu selection should be disabled.

Copy link
Author

Copilot AI commented Mar 10, 2026

There are still some issues:

  1. When a read-only shared board is selected, and I am not its owner, the "Add to Queue" button is active and lets me generate into the shared board. This button should b...

Fixed in ae9cca7. Here's what was addressed:

  1. "Add to Queue" icon button still active — The floating InvokeIconButton in FloatingLeftPanelButtons.tsx was a second invoke entry point that wasn't covered. Now it also checks useBoardAccess(autoAddBoard).canWriteImages and is disabled for non-owners of shared boards.

  2. Dragging images out of shared boardGalleryImage.tsx now reads useSelectedBoard() + useBoardAccess() and conditionally registers the draggable() binding. When canDragFromBoard is false (non-owner viewing a shared board), the draggable is not attached, so the image cannot be picked up. The monitorForElements monitor is always registered so multi-image drag indicators still work.

  3. "Change Board" destination includes shared boardsChangeBoardModal.tsx now applies a canWriteToBoard filter to the options list. Boards where the current user is not the owner/admin and which are shared are excluded. Public boards and the user's own boards remain available.

  4. Archive/Unarchive accessible to non-owners — Both the Archive and Unarchive menu items in BoardContextMenu.tsx now carry isDisabled={!canDeleteBoard}, so non-owners of shared and public boards see them greyed out.

Copilot AI and others added 3 commits March 9, 2026 22:56
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
…-board filter, archive

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
@lstein lstein force-pushed the copilot/enhancement-allow-shared-boards branch from 1fd217f to 9f8f7a1 Compare March 10, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants