фигня какая-то фикс статистики 10
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
9c5ba61ab5
commit
57fd5a4839
2 changed files with 81 additions and 20 deletions
|
|
@ -608,39 +608,92 @@ function createRefreshService({ db, fetch, getSettings, sseBroadcast, logger = c
|
|||
return dayKeyNow !== dayKeyLast;
|
||||
}
|
||||
|
||||
function firstDefined(obj, keys) {
|
||||
for (const key of keys) {
|
||||
const value = obj?.[key];
|
||||
if (value !== undefined && value !== null && String(value).trim() !== '') return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function extractClientUserRecord(raw) {
|
||||
const userId = firstDefined(raw, ['userId', 'userid', 'user_id', 'id']);
|
||||
const name = String(firstDefined(raw, ['name', 'fullName', 'fullname', 'displayName', 'username']) || '').trim();
|
||||
|
||||
const groupIds = new Set();
|
||||
const pushGroup = (value) => {
|
||||
if (value === undefined || value === null) return;
|
||||
const normalized = String(value).trim();
|
||||
if (normalized) groupIds.add(normalized);
|
||||
};
|
||||
|
||||
pushGroup(firstDefined(raw, ['userGroupId', 'usergroupid', 'user_group_id', 'groupId', 'group_id']));
|
||||
|
||||
for (const bucketName of ['groups', 'userGroups']) {
|
||||
const bucket = raw?.[bucketName];
|
||||
if (!Array.isArray(bucket)) continue;
|
||||
for (const group of bucket) {
|
||||
pushGroup(firstDefined(group, ['userGroupId', 'usergroupid', 'groupId', 'group_id', 'id']));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
userId: userId === null ? '' : String(userId).trim(),
|
||||
name,
|
||||
groupIds: [...groupIds],
|
||||
};
|
||||
}
|
||||
|
||||
async function syncClientUsers() {
|
||||
const s = getSettings();
|
||||
if (!s.api_key) return;
|
||||
const pageSize = 100;
|
||||
if (!s.api_key) return { fetched: 0, stored: 0, odata_count: null };
|
||||
const pageSize = 400;
|
||||
let skip = 0;
|
||||
const allUsers = [];
|
||||
let odataCount = null;
|
||||
const sourceRows = [];
|
||||
while (true) {
|
||||
const url = `https://apigw.intradesk.ru/settings/odata/v2/Clients?ApiKey=${s.api_key}`
|
||||
const url = `https://apigw.intradesk.ru/settings/odata/ClientUsers?ApiKey=${s.api_key}`
|
||||
+ `&$count=true`
|
||||
+ `&$orderby=${encodeURIComponent('id desc')}`
|
||||
+ `&$filter=${encodeURIComponent('(isarchived eq false)')}`
|
||||
+ `&$top=${pageSize}&$skip=${skip}`;
|
||||
const response = await fetch(url, { timeout: 30000 });
|
||||
if (!response.ok) break;
|
||||
if (!response.ok) {
|
||||
const body = await response.text().catch(() => '');
|
||||
throw new Error(`ClientUsers request failed (${response.status}): ${body.slice(0, 180)}`);
|
||||
}
|
||||
const json = await response.json();
|
||||
const users = json.value || [];
|
||||
allUsers.push(...users);
|
||||
if (users.length < pageSize) break;
|
||||
const rows = Array.isArray(json?.value) ? json.value : [];
|
||||
if (odataCount === null && Number.isFinite(Number(json?.['@odata.count']))) {
|
||||
odataCount = Number(json['@odata.count']);
|
||||
}
|
||||
sourceRows.push(...rows);
|
||||
if (rows.length < pageSize) break;
|
||||
skip += pageSize;
|
||||
}
|
||||
if (!allUsers.length) return;
|
||||
|
||||
const memberships = [];
|
||||
const seenMemberships = new Set();
|
||||
for (const raw of sourceRows) {
|
||||
const parsed = extractClientUserRecord(raw || {});
|
||||
if (!parsed.userId || !parsed.name || !parsed.groupIds.length) continue;
|
||||
for (const groupId of parsed.groupIds) {
|
||||
const dedupeKey = `${parsed.userId}|${groupId}`;
|
||||
if (seenMemberships.has(dedupeKey)) continue;
|
||||
seenMemberships.add(dedupeKey);
|
||||
memberships.push({ userId: parsed.userId, name: parsed.name, groupId });
|
||||
}
|
||||
}
|
||||
|
||||
const tx = db.transaction(() => {
|
||||
stmts.clearClientUsers.run();
|
||||
for (const u of allUsers) {
|
||||
const name = String(u.name || '').trim();
|
||||
if (!name || !u.id) continue;
|
||||
for (const g of (u.groups || [])) {
|
||||
if (g.userGroupId) {
|
||||
stmts.upsertClientUser.run(u.id, name, g.userGroupId);
|
||||
}
|
||||
}
|
||||
for (const row of memberships) {
|
||||
stmts.upsertClientUser.run(row.userId, row.name, row.groupId);
|
||||
}
|
||||
});
|
||||
tx();
|
||||
logger.log(`[Refresh] syncClientUsers: stored ${allUsers.length} users`);
|
||||
logger.log(`[Refresh] syncClientUsers: fetched ${sourceRows.length}, stored ${memberships.length}${odataCount !== null ? `, odata.count=${odataCount}` : ''}`);
|
||||
return { fetched: sourceRows.length, stored: memberships.length, odata_count: odataCount };
|
||||
}
|
||||
|
||||
let running = false;
|
||||
|
|
|
|||
12
server.js
12
server.js
|
|
@ -542,9 +542,17 @@ app.get('/api/client-users', auth, (req, res) => {
|
|||
|
||||
app.post('/api/admin/sync-client-users', auth, adminOnly, (req, res) => {
|
||||
refreshService.syncClientUsers()
|
||||
.then(() => {
|
||||
.then((syncMeta = {}) => {
|
||||
const count = db.prepare('SELECT COUNT(*) as c FROM client_users').get();
|
||||
res.json({ ok: true, count: count.c });
|
||||
res.json({
|
||||
ok: true,
|
||||
count: count.c,
|
||||
fetched: Number(syncMeta.fetched || 0),
|
||||
stored: Number(syncMeta.stored || 0),
|
||||
odata_count: syncMeta.odata_count !== null && syncMeta.odata_count !== undefined
|
||||
? Number(syncMeta.odata_count)
|
||||
: null,
|
||||
});
|
||||
})
|
||||
.catch((e) => res.status(500).json({ error: e.message }));
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue