mirror of
https://github.com/labring/FastGPT.git
synced 2026-01-28 01:10:33 +08:00
* fix: push again, user select option button and form input radio content overflow (#5601) * fix: push again, user select option button and form input radio content overflow * fix: use useCallback instead of useMemo, fix unnecessary delete * fix: Move the variable inside the component * fix: do not pass valueLabel to MySelect * ui * del collection api adapt * refactor: inherit permission (#5529) * refactor: permission update conflict check function * refactor(permission): app collaborator update api * refactor(permission): support app update collaborator * feat: support fe permission conflict check * refactor(permission): app permission * refactor(permission): dataset permission * refactor(permission): team permission * chore: fe adjust * fix: type error * fix: audit pagiation * fix: tc * chore: initv4130 * fix: app/dataset auth logic * chore: move code * refactor(permission): remove selfPermission * fix: mock * fix: test * fix: app & dataset auth * fix: inherit * test(inheritPermission): test syncChildrenPermission * prompt editor add list plugin (#5620) * perf: search result (#5608) * fix: table size (#5598) * temp: list value * backspace * optimize code --------- Co-authored-by: Archer <545436317@qq.com> Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com> * fix: fe & member list (#5619) * chore: initv4130 * fix: MemberItemCard * fix: MemberItemCard * chore: fe adjust & init script * perf: test code * doc * fix debug variables (#5617) * perf: search result (#5608) * fix: table size (#5598) * fix debug variables * fix --------- Co-authored-by: Archer <545436317@qq.com> Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com> * perf: member ui * fix: inherit bug (#5624) * refactor(permission): remove getClbsWithInfo, which is useless * fix: app list privateApp * fix: get infos * perf(fe): remove delete icon when it is disable in MemberItemCard * fix: dataset private dataset * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Archer <545436317@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * perf: auto coupon * chore: upgrade script & get infos avatar (#5625) * fix: get infos * chore: initv4130 * feat: support WecomRobot publish, and fix AesKey can not save bug (#5526) * feat: resolve conflicts * fix: add param 'show_publish_wecom' * feat: abstract out WecomCrypto type * doc: wecom robot document * fix: solve instability in AI output * doc: update some pictures * feat: remove functions from request.ts to chat.ts and toolCall.ts * doc: wecom robot doc update * fix * delete unused code * doc: update version and prompt * feat: remove wecom crypto, delete wecom code in workflow * feat: delete unused codes --------- Co-authored-by: heheer <zhiyu44@qq.com> * remove test * rename init shell * feat: collection page store * reload sandbox * pysandbox * remove log * chore: remove useless code (#5629) * chore: remove useless code * fix: checkConflict * perf: support hidden type for RoleList * fix: copy node * update doc * fix(permission): some bug (#5632) * fix: app/dataset list * fix: inherit bug * perf: del app;i18n;save chat * fix: test * i18n * fix: sumper overflow return OwnerRoleVal (#5633) * remove invalid code * fix: scroll * fix: objectId * update next * update package * object id * mock redis * feat: add redis append to resolve wecom stream response (#5643) * feat: resolve conflicts * fix: add param 'show_publish_wecom' * feat: abstract out WecomCrypto type * doc: wecom robot document * fix: solve instability in AI output * doc: update some pictures * feat: remove functions from request.ts to chat.ts and toolCall.ts * doc: wecom robot doc update * fix * delete unused code * doc: update version and prompt * feat: remove wecom crypto, delete wecom code in workflow * feat: delete unused codes * feat: add redis append method --------- Co-authored-by: heheer <zhiyu44@qq.com> * cache per * fix(test): init team sub when creating mocked user (#5646) * fix: button is not vertically centered (#5647) * doc * fix: gridFs objectId (#5649) --------- Co-authored-by: Zeng Qingwen <143274079+fishwww-ww@users.noreply.github.com> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: heheer <zhiyu44@qq.com>
183 lines
4.8 KiB
TypeScript
183 lines
4.8 KiB
TypeScript
import type { CollaboratorIdType, CollaboratorItemType } from './collaborator';
|
|
import { ManageRoleVal, OwnerRoleVal } from './constant';
|
|
import type { RoleValueType } from './type';
|
|
import { type PermissionValueType } from './type';
|
|
/**
|
|
* Sum the permission value.
|
|
* If no permission value is provided, return undefined to fallback to default value.
|
|
* @param per permission value (number)
|
|
* @returns sum of permission value
|
|
*/
|
|
export const sumPer = (...per: PermissionValueType[]) => {
|
|
if (per.length === 0) {
|
|
// prevent sum 0 value, to fallback to default value
|
|
return undefined;
|
|
}
|
|
const res = per.reduce((acc, cur) => acc | cur, 0);
|
|
if (res < 0) {
|
|
// overflowed
|
|
return OwnerRoleVal;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
/**
|
|
* Check if the update cause conflict (need to remove inheritance permission).
|
|
* Conflict condition:
|
|
* The updated collaborator is a parent collaborator.
|
|
* @param parentClbs parent collaborators
|
|
* @param oldChildClbs old child collaborators
|
|
* @param newChildClbs new child collaborators
|
|
*/
|
|
export const checkRoleUpdateConflict = ({
|
|
parentClbs,
|
|
newChildClbs
|
|
}: {
|
|
parentClbs: CollaboratorItemType[];
|
|
newChildClbs: CollaboratorItemType[];
|
|
}): boolean => {
|
|
if (parentClbs.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
// Use a Map for faster lookup by teamId
|
|
const parentClbRoleMap = new Map(
|
|
parentClbs.map((clb) => [
|
|
getCollaboratorId(clb),
|
|
{
|
|
...clb
|
|
}
|
|
])
|
|
);
|
|
|
|
const changedClbs = getChangedCollaborators({
|
|
newRealClbs: newChildClbs,
|
|
oldRealClbs: parentClbs
|
|
});
|
|
|
|
for (const changedClb of changedClbs) {
|
|
const parent = parentClbRoleMap.get(getCollaboratorId(changedClb));
|
|
if (parent && ((changedClb.changedRole & parent.permission) !== 0 || changedClb.deleted)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
export type ChangedClbType = {
|
|
changedRole: RoleValueType;
|
|
deleted: boolean;
|
|
} & CollaboratorIdType;
|
|
|
|
/**
|
|
* Get changed collaborators.
|
|
* return empty array if all collaborators are unchanged.
|
|
*
|
|
* for each return item:
|
|
* ```typescript
|
|
* {
|
|
* // ... ids
|
|
* changedRole: number; // set bit means the role is changed
|
|
* deleted: boolean; // is deleted
|
|
* }
|
|
* ```
|
|
*
|
|
* **special**: for low 3 bit: always get the lowest change, unset the higher change.
|
|
*/
|
|
export const getChangedCollaborators = ({
|
|
oldRealClbs,
|
|
newRealClbs
|
|
}: {
|
|
oldRealClbs: CollaboratorItemType[];
|
|
newRealClbs: CollaboratorItemType[];
|
|
}): ChangedClbType[] => {
|
|
if (oldRealClbs.length === 0) {
|
|
return newRealClbs.map((clb) => ({
|
|
...clb,
|
|
changedRole: clb.permission,
|
|
deleted: false
|
|
}));
|
|
}
|
|
const oldClbsMap = new Map(oldRealClbs.map((clb) => [getCollaboratorId(clb), clb]));
|
|
const changedClbs: ChangedClbType[] = [];
|
|
for (const newClb of newRealClbs) {
|
|
const oldClb = oldClbsMap.get(getCollaboratorId(newClb));
|
|
if (!oldClb) {
|
|
changedClbs.push({
|
|
...newClb,
|
|
changedRole: newClb.permission,
|
|
deleted: false
|
|
});
|
|
continue;
|
|
}
|
|
const changedRole = oldClb.permission ^ newClb.permission;
|
|
if (changedRole) {
|
|
changedClbs.push({
|
|
...newClb,
|
|
changedRole,
|
|
deleted: false
|
|
});
|
|
}
|
|
}
|
|
|
|
for (const oldClb of oldRealClbs) {
|
|
const newClb = newRealClbs.find((clb) => getCollaboratorId(clb) === getCollaboratorId(oldClb));
|
|
if (!newClb) {
|
|
changedClbs.push({
|
|
...oldClb,
|
|
changedRole: oldClb.permission,
|
|
deleted: true
|
|
});
|
|
}
|
|
}
|
|
|
|
changedClbs.forEach((clb) => {
|
|
// For the lowest 3 bits, only keep the lowest set bit as 1, clear other lower bits, keep higher bits unchanged
|
|
const low3 = clb.changedRole & 0b111;
|
|
const lowestBit = low3 & -low3;
|
|
clb.changedRole = (clb.changedRole & ~0b111) | lowestBit;
|
|
});
|
|
|
|
return changedClbs;
|
|
};
|
|
|
|
export const getCollaboratorId = (clb: CollaboratorIdType) =>
|
|
(clb.tmbId || clb.groupId || clb.orgId)!;
|
|
|
|
export const mergeCollaboratorList = <T extends CollaboratorItemType>({
|
|
parentClbs,
|
|
childClbs
|
|
}: {
|
|
parentClbs: T[];
|
|
childClbs: T[];
|
|
}) => {
|
|
const idToClb = new Map<string, T>();
|
|
|
|
// Add all items from list1
|
|
for (const parentClb of parentClbs) {
|
|
if (parentClb.permission === OwnerRoleVal) {
|
|
idToClb.set(getCollaboratorId(parentClb), { ...parentClb, permission: ManageRoleVal });
|
|
continue;
|
|
}
|
|
idToClb.set(getCollaboratorId(parentClb), { ...parentClb });
|
|
}
|
|
|
|
// Merge permissions from list2
|
|
for (const childClb of childClbs) {
|
|
const id = getCollaboratorId(childClb);
|
|
if (idToClb.has(id)) {
|
|
// If already exists, merge permission bits
|
|
const original = idToClb.get(id)!;
|
|
idToClb.set(id, {
|
|
...original,
|
|
permission: sumPer(original.permission, childClb.permission)!
|
|
});
|
|
} else {
|
|
idToClb.set(id, { ...childClb });
|
|
}
|
|
}
|
|
|
|
return Array.from(idToClb.values());
|
|
};
|