Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 39x 39x 3x 3x 3x 3x 39x 2x 2x 1x 39x 39x 1x 1x 1x 1x 39x 39x | import type { FastifyPluginAsync, FastifyRequest } from "fastify";
import type { AppConfig } from "../config.js";
import { assertServiceToken } from "../lib/service-token.js";
import { readUserUid } from "../lib/user-uid.js";
import { prisma } from "../lib/prisma.js";
import type { ObjectStore } from "../storage/object-store.js";
/** Удаляет персональные данные пользователя: профиль, велики (+фото в R2), лайки, избранное, аватар. */
export async function purgeUserData(uid: string, objectStore: ObjectStore | null): Promise<void> {
const profile = await prisma.userProfile.findUnique({
where: { firebaseUid: uid },
select: { avatarKey: true },
});
const bikes = await prisma.bike.findMany({
where: { ownerUid: uid },
select: { photoKey: true },
});
await prisma.trackLike.deleteMany({ where: { firebaseUid: uid } });
await prisma.trackFavorite.deleteMany({ where: { firebaseUid: uid } });
await prisma.bike.deleteMany({ where: { ownerUid: uid } });
await prisma.userProfile.deleteMany({ where: { firebaseUid: uid } });
if (objectStore) {
if (profile?.avatarKey) {
await objectStore.delete(profile.avatarKey).catch(() => undefined);
}
for (const bike of bikes) {
if (bike.photoKey) {
await objectStore.delete(bike.photoKey).catch(() => undefined);
}
}
}
}
export const accountRoutes: FastifyPluginAsync<{
config: AppConfig;
objectStore: ObjectStore | null;
}> = async (app, opts) => {
const { config, objectStore } = opts;
function authorize(request: FastifyRequest): string {
const token = request.headers["x-service-token"];
assertServiceToken(Array.isArray(token) ? token[0] : token, config.serviceToken);
return readUserUid(request);
}
/** Удалить мои данные — профиль/велики/лайки/аватар. Аккаунт и треки остаются. */
app.delete("/account/data", async (request, reply) => {
const uid = authorize(request);
await purgeUserData(uid, objectStore);
return reply.send({ ok: true });
});
/** Удалить аккаунт — персональные данные + осиротить треки (owner → NULL). Firebase удаляет клиент. */
app.delete("/account", async (request, reply) => {
const uid = authorize(request);
await purgeUserData(uid, objectStore);
await prisma.gpxTrack.updateMany({ where: { ownerUid: uid }, data: { ownerUid: null } });
return reply.send({ ok: true });
});
};
|