mirror of
https://github.com/wekan/wekan.git
synced 2026-11-07 02:52:33 -05:00
In the IFTTT-Rules "Move card to the board" and "Link card to the board" actions, the board dropdown was empty for some users — the current board included — while colleagues in the same company could pick boards normally. Root cause: the dropdown filtered the (already access-scoped) client cache with `'members.userId': me`, i.e. it only kept boards where the user has a *direct* member entry. A user who reaches a board through an Organization, Team or email-domain share — but is not listed individually in `board.members` — matched nothing, so the whole selector came up empty. The dropdown now filters by the same visibility rule as `Boards.userBoards()` (public OR active member OR active org OR active team OR active domain), so org/team/domain-shared boards appear too, while archived boards, template containers, the user's templates board and internal helper boards stay excluded. Thanks to Augustin356 and xet7 ! Fixes #5698
54 lines
2.5 KiB
JavaScript
54 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
// Pure helpers deciding which boards may be picked as a destination in the
|
|
// IFTTT-Rules "move card to the board" / "link card to the board" selectors.
|
|
// Extracted from client/components/rules/actions/boardActions.js so the choice
|
|
// is unit-testable without Meteor.
|
|
//
|
|
// #5698 (Impossible to select other board in rules): the board dropdown used to
|
|
// filter the (already access-scoped) client cache with `'members.userId': me`,
|
|
// i.e. it only kept boards where the user has a DIRECT member entry. A user who
|
|
// reaches a board through an Organization, Team or email-domain share — but is
|
|
// not listed individually in board.members — got an EMPTY dropdown (not even the
|
|
// current board showed up), while a colleague who was a direct member saw the
|
|
// boards. This mirrors the board-list publication / Boards.userBoards() rule:
|
|
// public OR active member OR active org OR active team OR active domain.
|
|
|
|
function hasActive(list, predicate) {
|
|
return Array.isArray(list) && list.some(entry => entry && predicate(entry));
|
|
}
|
|
|
|
// Does `board` match `ctx`'s visibility? ctx = { userId, orgIds, teamIds,
|
|
// emailDomains } — the last three are plain id arrays (empty when absent).
|
|
function boardVisibleToUserContext(board, ctx) {
|
|
if (!board || !ctx) return false;
|
|
if (board.permission === 'public') return true;
|
|
if (hasActive(board.members, m => m.userId === ctx.userId && !!m.isActive)) {
|
|
return true;
|
|
}
|
|
const inSet = (list, key, ids) =>
|
|
Array.isArray(ids) &&
|
|
hasActive(list, entry => !!entry.isActive && ids.includes(entry[key]));
|
|
if (inSet(board.orgs, 'orgId', ctx.orgIds)) return true;
|
|
if (inSet(board.teams, 'teamId', ctx.teamIds)) return true;
|
|
if (inSet(board.domains, 'domain', ctx.emailDomains)) return true;
|
|
return false;
|
|
}
|
|
|
|
// May this board appear in the rules board selector for `ctx`?
|
|
// Excludes archived boards, non-'board' types (e.g. template containers), the
|
|
// user's own templates board, and internal caret-wrapped helper boards
|
|
// (`^Subtasks^` etc.), then requires the board to be visible to the user.
|
|
function canSelectBoardInRules(board, ctx, templatesBoardId) {
|
|
if (!board || !ctx) return false;
|
|
if (board.archived) return false;
|
|
if (board.type && board.type !== 'board') return false;
|
|
if (typeof board.title === 'string' && /^\^.*\^$/.test(board.title)) {
|
|
return false;
|
|
}
|
|
if (templatesBoardId && board._id === templatesBoardId) return false;
|
|
return boardVisibleToUserContext(board, ctx);
|
|
}
|
|
|
|
module.exports = { canSelectBoardInRules, boardVisibleToUserContext };
|