mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
0139b91b5d
* chore: Replace lodash with es-toolkit Migrate all direct lodash imports to es-toolkit/compat for a smaller, faster, lodash-compatible utility library. Transitive lodash usage from other packages remains unchanged. * fix: Restore isPlainObject semantics in CanCan policy The lodash migration aliased `isObject` to `lodash/isPlainObject` and the codemod incorrectly mapped the local name to es-toolkit's `isObject`, which also returns true for arrays and functions. This caused condition objects in policy definitions to be skipped, breaking authorization checks across the codebase. * fix: Restore unicode-aware length counting in validators es-toolkit/compat's size() returns string.length, while lodash's _.size() counts unicode code points. Switch to [...value].length to preserve the previous behavior so multi-byte characters like emoji count as one.
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { has, isEqual } from "es-toolkit/compat";
|
|
import { TeamPreference } from "@shared/types";
|
|
import env from "@server/env";
|
|
import type { Team, User } from "@server/models";
|
|
import { TeamDomain } from "@server/models";
|
|
import type { APIContext } from "@server/types";
|
|
|
|
type Props = {
|
|
params: Partial<Omit<Team, "allowedDomains">> & { allowedDomains?: string[] };
|
|
user: User;
|
|
team: Team;
|
|
};
|
|
|
|
const teamUpdater = async (ctx: APIContext, { params, user, team }: Props) => {
|
|
const { allowedDomains, preferences, subdomain, ...attributes } = params;
|
|
team.setAttributes(attributes);
|
|
|
|
if (subdomain !== undefined && env.isCloudHosted) {
|
|
team.subdomain = subdomain === "" ? null : subdomain;
|
|
}
|
|
|
|
if (allowedDomains !== undefined) {
|
|
const existingAllowedDomains = await TeamDomain.findAll({
|
|
where: { teamId: team.id },
|
|
transaction: ctx.state.transaction,
|
|
});
|
|
|
|
// Only keep existing domains if they are still in the list of allowed domains
|
|
const newAllowedDomains = team.allowedDomains.filter((existingTeamDomain) =>
|
|
allowedDomains.includes(existingTeamDomain.name)
|
|
);
|
|
|
|
// Add new domains
|
|
const existingDomains = team.allowedDomains.map((x) => x.name);
|
|
const newDomains = allowedDomains.filter(
|
|
(newDomain) => newDomain !== "" && !existingDomains.includes(newDomain)
|
|
);
|
|
await Promise.all(
|
|
newDomains.map(async (newDomain) => {
|
|
newAllowedDomains.push(
|
|
await TeamDomain.createWithCtx(ctx, {
|
|
name: newDomain,
|
|
teamId: team.id,
|
|
createdById: user.id,
|
|
})
|
|
);
|
|
})
|
|
);
|
|
|
|
// Destroy the existing TeamDomains that were removed
|
|
const deletedDomains = existingAllowedDomains.filter(
|
|
(x) => !allowedDomains.includes(x.name)
|
|
);
|
|
await Promise.all(deletedDomains.map((x) => x.destroyWithCtx(ctx)));
|
|
team.allowedDomains = newAllowedDomains;
|
|
}
|
|
|
|
if (preferences) {
|
|
for (const key of Object.values(TeamPreference)) {
|
|
if (
|
|
has(preferences, key) &&
|
|
!isEqual(preferences[key], team.getPreference(key))
|
|
) {
|
|
team.setPreference(key, preferences[key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return team.saveWithCtx(ctx);
|
|
};
|
|
|
|
export default teamUpdater;
|