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.
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import type { TFunction } from "i18next";
|
|
import { capitalize, uniq } from "es-toolkit/compat";
|
|
import { Scope } from "@shared/types";
|
|
|
|
export class OAuthScopeHelper {
|
|
public static normalizeScopes(scopes: string[], t: TFunction): string[] {
|
|
const methodToReadable = {
|
|
list: t("read"),
|
|
info: t("read"),
|
|
read: t("read"),
|
|
write: t("write"),
|
|
create: t("write"),
|
|
update: t("write"),
|
|
delete: t("write"),
|
|
"*": t("read and write"),
|
|
};
|
|
|
|
const translatedNamespaces = {
|
|
apiKeys: t("API keys"),
|
|
attachments: t("attachments"),
|
|
collections: t("collections"),
|
|
comments: t("comments"),
|
|
documents: t("documents"),
|
|
events: t("events"),
|
|
groups: t("groups"),
|
|
integrations: t("integrations"),
|
|
notifications: t("notifications"),
|
|
reactions: t("reactions"),
|
|
pins: t("pins"),
|
|
shares: t("shares"),
|
|
users: t("users"),
|
|
teams: t("teams"),
|
|
"*": t("workspace"),
|
|
};
|
|
|
|
const normalizedScopes = scopes.map((scope) => {
|
|
if (scope === Scope.Read) {
|
|
return t("Read all data");
|
|
}
|
|
if (scope === Scope.Write) {
|
|
return t("Write all data");
|
|
}
|
|
|
|
const [namespace, method] = scope.replace("/api/", "").split(/[:.]/g);
|
|
const readableMethod =
|
|
methodToReadable[method as keyof typeof methodToReadable] ?? method;
|
|
if (!readableMethod) {
|
|
return scope;
|
|
}
|
|
|
|
const translatedNamespace =
|
|
translatedNamespaces[namespace as keyof typeof translatedNamespaces] ??
|
|
namespace;
|
|
return capitalize(`${readableMethod} ${translatedNamespace}`);
|
|
});
|
|
|
|
return uniq(normalizedScopes);
|
|
}
|
|
}
|