ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: Launcher control plane и доступы
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const publicDataPath = join(projectRoot, "public", "storage", "launcher-data.json");
|
||||
const distDataPath = join(projectRoot, "dist", "storage", "launcher-data.json");
|
||||
|
||||
const now = new Date().toISOString();
|
||||
const existingData = readJson(publicDataPath);
|
||||
const services = Array.isArray(existingData.services) ? existingData.services : [];
|
||||
const existingUsersByEmail = new Map(
|
||||
(Array.isArray(existingData.users) ? existingData.users : []).map((user) => [String(user.email || "").toLowerCase(), user])
|
||||
);
|
||||
const dcTouchAuthentikUserId = existingUsersByEmail.get("dcctouch@gmail.com")?.authentikUserId ?? null;
|
||||
const silverPsihAuthentikUserId = existingUsersByEmail.get("silver_psih@yahoo.com")?.authentikUserId ?? null;
|
||||
|
||||
const liveData = {
|
||||
...existingData,
|
||||
clients: [
|
||||
{
|
||||
id: "client_romashka",
|
||||
type: "company",
|
||||
name: "DCTOUCH",
|
||||
legalName: "ООО ДИСИТАЧ",
|
||||
status: "active",
|
||||
contractStartsAt: "2026-05-04T00:00:00.000Z",
|
||||
contractEndsAt: null,
|
||||
paidUntil: null,
|
||||
demoEndsAt: null,
|
||||
contactName: "DC Touch",
|
||||
contactEmail: "dcctouch@gmail.com",
|
||||
notes: "Live-клиент NODE.DC для первичной проверки control-plane, SSO и доступа к сервисам.",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
users: [
|
||||
{
|
||||
id: "user_root",
|
||||
authentikUserId: dcTouchAuthentikUserId,
|
||||
name: "DC Touch",
|
||||
email: "dcctouch@gmail.com",
|
||||
phone: null,
|
||||
position: "NODE.DC Super Admin",
|
||||
notes: "Главный супер-администратор NODE.DC. Authentik-пользователь уже создан в dev-контуре.",
|
||||
avatarUrl: null,
|
||||
globalStatus: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "user_silver_psih",
|
||||
authentikUserId: silverPsihAuthentikUserId,
|
||||
name: "Silver Psy",
|
||||
email: "silver_psih@yahoo.com",
|
||||
phone: null,
|
||||
position: "Manager",
|
||||
notes: "Живой пользователь из Plane. Требует создания/синхронизации в Authentik через Launcher flow.",
|
||||
avatarUrl: null,
|
||||
globalStatus: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
memberships: [
|
||||
{
|
||||
id: "mem_dc_touch_dctouch",
|
||||
clientId: "client_romashka",
|
||||
userId: "user_root",
|
||||
role: "client_owner",
|
||||
status: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "mem_silver_psih_dctouch",
|
||||
clientId: "client_romashka",
|
||||
userId: "user_silver_psih",
|
||||
role: "member",
|
||||
status: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
{
|
||||
id: "group_dctouch_admins",
|
||||
clientId: "client_romashka",
|
||||
name: "Администраторы",
|
||||
description: "Администраторы клиента и владельцы платформенного доступа.",
|
||||
memberIds: ["user_root"],
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "group_dctouch_managers",
|
||||
clientId: "client_romashka",
|
||||
name: "Менеджеры",
|
||||
description: "Рабочая группа менеджеров с доступом к операционному контуру.",
|
||||
memberIds: ["user_silver_psih"],
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
grants: [
|
||||
{
|
||||
id: "grant_dctouch_task_admins",
|
||||
serviceId: "service_task_manager",
|
||||
targetType: "group",
|
||||
targetId: "group_dctouch_admins",
|
||||
appRole: "admin",
|
||||
status: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "grant_dctouch_task_managers",
|
||||
serviceId: "service_task_manager",
|
||||
targetType: "group",
|
||||
targetId: "group_dctouch_managers",
|
||||
appRole: "member",
|
||||
status: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "grant_dctouch_nodedc_admins",
|
||||
serviceId: "service_nodedc",
|
||||
targetType: "group",
|
||||
targetId: "group_dctouch_admins",
|
||||
appRole: "admin",
|
||||
status: "active",
|
||||
createdAt: "2026-05-04T00:00:00.000Z",
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
exceptions: [],
|
||||
invites: [],
|
||||
syncStatuses: [
|
||||
{
|
||||
id: "sync_dctouch_client_authentik",
|
||||
objectId: "client_romashka",
|
||||
objectName: "DCTOUCH",
|
||||
objectType: "client",
|
||||
target: "authentik",
|
||||
state: "synced",
|
||||
lastSyncAt: now,
|
||||
error: null,
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "sync_dc_touch_authentik",
|
||||
objectId: "user_root",
|
||||
objectName: "dcctouch@gmail.com",
|
||||
objectType: "user",
|
||||
target: "authentik",
|
||||
state: dcTouchAuthentikUserId ? "synced" : "pending",
|
||||
lastSyncAt: dcTouchAuthentikUserId ? now : null,
|
||||
error: dcTouchAuthentikUserId ? null : "Пользователь есть в Authentik, но Launcher seed ещё не содержит Authentik UUID.",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "sync_silver_psih_authentik",
|
||||
objectId: "user_silver_psih",
|
||||
objectName: "silver_psih@yahoo.com",
|
||||
objectType: "user",
|
||||
target: "authentik",
|
||||
state: silverPsihAuthentikUserId ? "synced" : "pending",
|
||||
lastSyncAt: silverPsihAuthentikUserId ? now : null,
|
||||
error: silverPsihAuthentikUserId
|
||||
? null
|
||||
: "Пользователь найден в Plane, но ещё не создан в Authentik через Launcher invite/sync flow.",
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "sync_dctouch_groups_authentik",
|
||||
objectId: "client_romashka:groups",
|
||||
objectName: "DCTOUCH groups",
|
||||
objectType: "group",
|
||||
target: "authentik",
|
||||
state: "pending",
|
||||
lastSyncAt: null,
|
||||
error: null,
|
||||
updatedAt: now,
|
||||
},
|
||||
{
|
||||
id: "sync_task_manager_authentik",
|
||||
objectId: "service_task_manager",
|
||||
objectName: "OPERATIONAL CORE",
|
||||
objectType: "service",
|
||||
target: "authentik",
|
||||
state: "synced",
|
||||
lastSyncAt: now,
|
||||
error: null,
|
||||
updatedAt: now,
|
||||
},
|
||||
],
|
||||
auditEvents: [
|
||||
{
|
||||
id: "audit_live_seed_control_plane",
|
||||
at: now,
|
||||
actorUserId: "system",
|
||||
actorName: "NODE.DC seed",
|
||||
action: "Применён live seed control-plane",
|
||||
objectType: "control_plane",
|
||||
objectName: "Launcher users and access",
|
||||
clientId: "client_romashka",
|
||||
result: "success",
|
||||
details: "Demo-участники удалены из runtime storage. Оставлены dcctouch@gmail.com и silver_psih@yahoo.com.",
|
||||
},
|
||||
],
|
||||
services,
|
||||
};
|
||||
|
||||
await writeJson(publicDataPath, liveData);
|
||||
|
||||
if (existsSync(join(projectRoot, "dist"))) {
|
||||
await writeJson(distDataPath, liveData);
|
||||
}
|
||||
|
||||
console.log(`Seeded ${liveData.users.length} users, ${liveData.clients.length} client, ${liveData.groups.length} groups.`);
|
||||
|
||||
function readJson(path) {
|
||||
if (!existsSync(path)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return JSON.parse(readFileSync(path, "utf8"));
|
||||
}
|
||||
|
||||
async function writeJson(path, data) {
|
||||
await mkdir(dirname(path), { recursive: true });
|
||||
await writeFile(path, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
||||
}
|
||||
Reference in New Issue
Block a user