mirror of https://github.com/wekan/wekan
The Open Source kanban (built with Meteor). Keep variable/table/field names camelCase. For translations, only add Pull Request changes to wekan/i18n/en.i18n.json , other translations are done at https://transifex.com/wekan/wekan only.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.9 KiB
99 lines
3.9 KiB
import { Meteor } from 'meteor/meteor';
|
|
import { ReactiveCache } from '/imports/reactiveCache';
|
|
import Org from '/models/org';
|
|
import Team from '/models/team';
|
|
import Boards from '/models/boards';
|
|
|
|
// #4737 / #5850: implement the per-org/team "Propagate Members To Boards" flag
|
|
// (orgPropagateMembersToBoards / teamPropagateMembersToBoards). Until now the
|
|
// flag was stored and displayed in the Admin Panel but never acted on. This is
|
|
// the ldap-sync.py-style propagation: for each org/team that has the flag on,
|
|
// the org/team's member users are added as members of the regular boards that
|
|
// list that org/team. The update is strictly add-only — existing board members
|
|
// (assigned manually or from another source) are never removed or modified —
|
|
// and template boards (type 'template-board'/'template-container') are
|
|
// explicitly skipped, since those are group-only and must not gain per-user
|
|
// members.
|
|
//
|
|
// Membership is read from the USER docs (user.orgs[].orgId / user.teams[].teamId),
|
|
// matching how setUserOrgsTeamsFromLdap maintains it.
|
|
Meteor.methods({
|
|
async propagateOrgTeamMembersToBoards() {
|
|
// Allow server-to-server calls (connection === null, used by the LDAP sync)
|
|
// and admins; reject any other client-originated call. Mirrors the guard in
|
|
// server/ldapGroupSync.js setUserOrgsTeamsFromLdap.
|
|
if (this.connection !== null) {
|
|
const caller = this.userId ? await ReactiveCache.getUser(this.userId) : null;
|
|
if (!caller || caller.isAdmin !== true) {
|
|
throw new Meteor.Error('not-authorized', 'Not authorized');
|
|
}
|
|
}
|
|
|
|
let boardsUpdated = 0;
|
|
let membersAdded = 0;
|
|
|
|
// Add the given member userIds to a single board, add-only. Returns the
|
|
// number of members actually added (0 if all were already present).
|
|
const addMembersToBoard = async (board, memberUserIds) => {
|
|
const existing = new Set((board.members || []).map(m => m.userId));
|
|
const toAdd = memberUserIds.filter(userId => !existing.has(userId));
|
|
if (toAdd.length === 0) {
|
|
return 0;
|
|
}
|
|
const newMembers = toAdd.map(userId => ({
|
|
userId,
|
|
isAdmin: false,
|
|
isActive: true,
|
|
isNoComments: false,
|
|
isCommentOnly: false,
|
|
isWorker: false,
|
|
}));
|
|
await Boards.updateAsync(
|
|
{ _id: board._id },
|
|
{ $push: { members: { $each: newMembers } } },
|
|
);
|
|
return toAdd.length;
|
|
};
|
|
|
|
// Propagate one org or team. `field` is the user-doc membership array
|
|
// ('orgs'/'teams') and `idField` is the id within it ('orgId'/'teamId');
|
|
// `boardField` is the board array ('orgs'/'teams').
|
|
const propagate = async (groupId, field, idField, boardField) => {
|
|
const memberUsers = await Meteor.users
|
|
.find({ [`${field}.${idField}`]: groupId }, { fields: { _id: 1 } })
|
|
.fetchAsync();
|
|
const memberUserIds = memberUsers.map(u => u._id);
|
|
if (memberUserIds.length === 0) {
|
|
return;
|
|
}
|
|
|
|
// Regular boards only (type 'board'); template boards are group-only and
|
|
// must never gain per-user members, so they are excluded here.
|
|
const boards = await Boards.find({
|
|
type: 'board',
|
|
archived: { $ne: true },
|
|
[boardField]: { $elemMatch: { [idField]: groupId, isActive: true } },
|
|
}).fetchAsync();
|
|
|
|
for (const board of boards) {
|
|
const added = await addMembersToBoard(board, memberUserIds);
|
|
if (added > 0) {
|
|
boardsUpdated += 1;
|
|
membersAdded += added;
|
|
}
|
|
}
|
|
};
|
|
|
|
const orgs = await Org.find({ orgPropagateMembersToBoards: true }).fetchAsync();
|
|
for (const org of orgs) {
|
|
await propagate(org._id, 'orgs', 'orgId', 'orgs');
|
|
}
|
|
|
|
const teams = await Team.find({ teamPropagateMembersToBoards: true }).fetchAsync();
|
|
for (const team of teams) {
|
|
await propagate(team._id, 'teams', 'teamId', 'teams');
|
|
}
|
|
|
|
return { boardsUpdated, membersAdded };
|
|
},
|
|
});
|
|
|