This commit is contained in:
1 parent
172c3a5a0e
commit
922d24cac7
5 files changed
+157
-19
No files matched your search
+13
-7
@@ -6,7 +6,6 @@ const text = (value) => typeof value === 'string' ? value.trim() : '';
|
||||
const truthy = (value) => value === true || value === 1 || value === '1' || value === 'true';
|
||||
const kind = (node) => text(node.orgUnitType || node.type).toUpperCase();
|
||||
const isCompany = (node) => kind(node) === 'COMPANY' || text(node.type).toUpperCase() === 'COMPANY';
|
||||
const isDepartment = (node) => ['DEPARTMENT', 'DIVISION', 'TEAM', 'ORG_UNIT', 'BUSINESS_UNIT'].includes(kind(node)) || text(node.type).toUpperCase() === 'DEPARTMENT';
|
||||
|
||||
export function orgContextConfig(env) {
|
||||
if (!truthy(env.ORG_CONTEXT_ENABLED)) return null;
|
||||
@@ -30,9 +29,10 @@ export function orgContextConfig(env) {
|
||||
return { endpoint: endpoint.toString(), roots, keyId, keySecret, ttl: ttl * 1000 };
|
||||
}
|
||||
|
||||
export function buildOrgDirectory(payloads) {
|
||||
export function buildOrgDirectory(payloads, rootIds = []) {
|
||||
const tenants = new Map();
|
||||
const memberships = new Map();
|
||||
const roots = new Set((rootIds.length ? rootIds : payloads.map((payload) => payload?.scope?.tenantId)).map(text).filter(Boolean).map((id) => id.toLowerCase()));
|
||||
function visit(node, parentId) {
|
||||
if (!node || typeof node !== 'object' || !text(node.id)) throw new Error('org_context_invalid_tenant');
|
||||
const id = text(node.id).toLowerCase();
|
||||
@@ -77,9 +77,14 @@ export function buildOrgDirectory(payloads) {
|
||||
chain.unshift(node);
|
||||
node = tenants.get(node.parentId);
|
||||
}
|
||||
const company = [...chain].reverse().find(isCompany);
|
||||
const department = [...chain].reverse().find(isDepartment);
|
||||
const departmentName = text(department?.name) || text(appointment.member.department);
|
||||
// The configured roots are classification/group tenants. Their direct child
|
||||
// is the real company, even when every descendant has generic COMPANY type.
|
||||
const rootIndex = chain.findIndex((item) => roots.has(item.id) || ['ROOT', 'COMPANY_GROUP'].includes(text(item.type).toUpperCase()));
|
||||
const company = rootIndex >= 0 ? chain[rootIndex + 1] : chain.find(isCompany);
|
||||
const departmentChain = company ? chain.slice(chain.indexOf(company) + 1) : [];
|
||||
const department = departmentChain.at(-1);
|
||||
const memberDepartment = text(appointment.member.department);
|
||||
const departmentName = text(department?.name) || (memberDepartment !== text(company?.name) && !chain.some((item) => roots.has(item.id) && text(item.name) === memberDepartment) ? memberDepartment : '');
|
||||
const value = {
|
||||
userId: appointment.member.id,
|
||||
tenantId: appointment.tenantId,
|
||||
@@ -88,7 +93,7 @@ export function buildOrgDirectory(payloads) {
|
||||
company: text(company?.name),
|
||||
departmentTenantId: department?.id || '',
|
||||
department: departmentName,
|
||||
departmentPath: chain.filter(isDepartment).map((item) => text(item.name)).filter(Boolean).join(' / '),
|
||||
departmentPath: departmentChain.map((item) => text(item.name)).filter(Boolean).join(' / '),
|
||||
isPrimary: truthy(appointment.member.isPrimary),
|
||||
phone: text(appointment.member.phone),
|
||||
position: text(appointment.member.position || appointment.member.jobTitle),
|
||||
@@ -147,12 +152,13 @@ export async function getOrgDirectory(env, { fetchImpl = fetch, now = Date.now }
|
||||
if (text(payload?.scope?.tenantId).toLowerCase() !== config.roots[index]) throw new Error('org_context_scope_mismatch');
|
||||
responses[index] = payload;
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) throw new Error('org_context_timeout');
|
||||
if (/^org_context_/.test(error?.message || '')) throw error;
|
||||
throw new Error('org_context_request_failed');
|
||||
} finally { clearTimeout(timeout); }
|
||||
}
|
||||
}));
|
||||
const directory = buildOrgDirectory(responses);
|
||||
const directory = buildOrgDirectory(responses, config.roots);
|
||||
if (directory.byUser.size === 0) throw new Error('org_context_members_missing');
|
||||
if (cache.size >= 8) cache.delete(cache.keys().next().value);
|
||||
cache.set(cacheKey, { directory, expiresAt: now() + config.ttl });
|
||||
|
||||
Reference in new issue
Block a user