ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: синхронизация профиля из Tasker
This commit is contained in:
parent
06a6160a46
commit
95225280e7
|
|
@ -535,6 +535,44 @@ app.post("/api/internal/tasker/invite-requests/cancel", asyncRoute(async (req, r
|
||||||
res.json({ ok: true, taskerInviteRequest: result.taskerInviteRequest });
|
res.json({ ok: true, taskerInviteRequest: result.taskerInviteRequest });
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
app.post("/api/internal/tasker/profile-sync", asyncRoute(async (req, res) => {
|
||||||
|
if (!isInternalRequestAuthorized(req)) {
|
||||||
|
res.status(config.internalAccessToken ? 401 : 503).json({
|
||||||
|
ok: false,
|
||||||
|
error: config.internalAccessToken ? "internal_access_unauthorized" : "internal_access_not_configured",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const snapshot = controlPlaneStore.getSnapshot({ name: "NODE.DC tasker profile sync" });
|
||||||
|
const user = findInternalAccessUser(snapshot.data, req.body);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
res.status(404).json({ ok: false, error: "user_not_found" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const patch = sanitizeTaskerProfilePatch(req.body);
|
||||||
|
|
||||||
|
if (Object.keys(patch).length === 0) {
|
||||||
|
res.json({ ok: true, user, data: snapshot.data, skipped: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actor = {
|
||||||
|
sub: "tasker-profile-sync",
|
||||||
|
name: req.body?.source === "tasker" ? "Operational Core" : "NODE.DC profile sync",
|
||||||
|
email: typeof req.body?.email === "string" ? req.body.email : user.email,
|
||||||
|
source: "tasker",
|
||||||
|
};
|
||||||
|
const result = await controlPlaneStore.updateUserProfile(user.id, patch, actor);
|
||||||
|
const syncResult = await syncUsersToAuthentik(result.data, [user.id], actor);
|
||||||
|
const updatedUser = syncResult.data.users.find((candidate) => candidate.id === user.id) ?? result.user;
|
||||||
|
|
||||||
|
publishControlPlaneEvent("tasker.profile.updated", [user.id]);
|
||||||
|
res.json({ ok: true, user: updatedUser, data: syncResult.data });
|
||||||
|
}));
|
||||||
|
|
||||||
app.patch("/api/profile", requireSession, asyncRoute(async (req, res) => {
|
app.patch("/api/profile", requireSession, asyncRoute(async (req, res) => {
|
||||||
const { actor } = getLauncherProfileContext(req.nodedcSession);
|
const { actor } = getLauncherProfileContext(req.nodedcSession);
|
||||||
const result = await controlPlaneStore.updateUserProfile(actor.id, sanitizeSelfProfilePatch(req.body), req.nodedcSession.user);
|
const result = await controlPlaneStore.updateUserProfile(actor.id, sanitizeSelfProfilePatch(req.body), req.nodedcSession.user);
|
||||||
|
|
@ -1735,6 +1773,37 @@ function sanitizeSelfProfilePatch(payload) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sanitizeTaskerProfilePatch(payload) {
|
||||||
|
const patch = {};
|
||||||
|
const name = firstNonEmptyString(payload?.displayName, payload?.display_name, payload?.name);
|
||||||
|
const hasAvatar =
|
||||||
|
Object.hasOwn(payload ?? {}, "avatarUrl") ||
|
||||||
|
Object.hasOwn(payload ?? {}, "avatar_url") ||
|
||||||
|
Object.hasOwn(payload ?? {}, "avatar");
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
patch.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAvatar) {
|
||||||
|
patch.avatarUrl = nullableProfileUrl(payload?.avatarUrl ?? payload?.avatar_url ?? payload?.avatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
return patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
function firstNonEmptyString(...values) {
|
||||||
|
for (const value of values) {
|
||||||
|
if (typeof value === "string" && value.trim()) return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nullableProfileUrl(value) {
|
||||||
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
||||||
|
}
|
||||||
|
|
||||||
function toProvisioningResponse(provisionedUser) {
|
function toProvisioningResponse(provisionedUser) {
|
||||||
return {
|
return {
|
||||||
authentikUserId: provisionedUser.authentikUserId,
|
authentikUserId: provisionedUser.authentikUserId,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue