gdpr

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GDPR Compliance

GDPR合规

Data Subject Rights Implementation

数据主体权利实施

Right to Access (Data Export)

访问权(数据导出)

typescript
app.get('/api/privacy/my-data', auth, async (req, res) => {
  const userId = req.user.id;

  const data = {
    profile: await db.user.findUnique({ where: { id: userId }, select: exportableFields }),
    orders: await db.order.findMany({ where: { userId }, select: orderExportFields }),
    preferences: await db.preference.findMany({ where: { userId } }),
    consents: await db.consent.findMany({ where: { userId } }),
  };

  res.json(data);
  // Or: generate downloadable file
  // res.attachment('my-data.json').json(data);
});
typescript
app.get('/api/privacy/my-data', auth, async (req, res) => {
  const userId = req.user.id;

  const data = {
    profile: await db.user.findUnique({ where: { id: userId }, select: exportableFields }),
    orders: await db.order.findMany({ where: { userId }, select: orderExportFields }),
    preferences: await db.preference.findMany({ where: { userId } }),
    consents: await db.consent.findMany({ where: { userId } }),
  };

  res.json(data);
  // Or: generate downloadable file
  // res.attachment('my-data.json').json(data);
});

Right to Erasure (Deletion)

删除权(擦除)

typescript
async function deleteUserData(userId: string): Promise<void> {
  // Anonymize where deletion would break referential integrity
  await db.order.updateMany({
    where: { userId },
    data: { customerName: '[deleted]', email: '[deleted]' },
  });

  // Delete personal data
  await db.preference.deleteMany({ where: { userId } });
  await db.consent.deleteMany({ where: { userId } });
  await db.session.deleteMany({ where: { userId } });

  // Anonymize the user record (keep for accounting if legally required)
  await db.user.update({
    where: { id: userId },
    data: {
      email: `deleted-${userId}@anonymized.local`,
      name: '[deleted]',
      phone: null,
      deletedAt: new Date(),
    },
  });

  // Log the deletion (audit requirement)
  await auditLog.record({
    action: 'user.data_deleted',
    resource: { type: 'user', id: userId },
    actor: { id: userId, type: 'user' },
  });
}
typescript
async function deleteUserData(userId: string): Promise<void> {
  // Anonymize where deletion would break referential integrity
  await db.order.updateMany({
    where: { userId },
    data: { customerName: '[deleted]', email: '[deleted]' },
  });

  // Delete personal data
  await db.preference.deleteMany({ where: { userId } });
  await db.consent.deleteMany({ where: { userId } });
  await db.session.deleteMany({ where: { userId } });

  // Anonymize the user record (keep for accounting if legally required)
  await db.user.update({
    where: { id: userId },
    data: {
      email: `deleted-${userId}@anonymized.local`,
      name: '[deleted]',
      phone: null,
      deletedAt: new Date(),
    },
  });

  // Log the deletion (audit requirement)
  await auditLog.record({
    action: 'user.data_deleted',
    resource: { type: 'user', id: userId },
    actor: { id: userId, type: 'user' },
  });
}

Consent Management

同意管理

typescript
interface ConsentRecord {
  userId: string;
  purpose: string;         // 'marketing', 'analytics', 'essential'
  granted: boolean;
  grantedAt: Date;
  ipAddress: string;
  version: string;          // Policy version at time of consent
}

app.post('/api/consent', auth, async (req, res) => {
  const { purposes } = req.body; // { marketing: true, analytics: false }

  for (const [purpose, granted] of Object.entries(purposes)) {
    await db.consent.upsert({
      where: { userId_purpose: { userId: req.user.id, purpose } },
      create: {
        userId: req.user.id,
        purpose,
        granted: granted as boolean,
        grantedAt: new Date(),
        ipAddress: req.ip,
        version: CURRENT_PRIVACY_POLICY_VERSION,
      },
      update: {
        granted: granted as boolean,
        grantedAt: new Date(),
        ipAddress: req.ip,
        version: CURRENT_PRIVACY_POLICY_VERSION,
      },
    });
  }

  res.json({ updated: true });
});

// Check consent before processing
async function hasConsent(userId: string, purpose: string): Promise<boolean> {
  const consent = await db.consent.findUnique({
    where: { userId_purpose: { userId, purpose } },
  });
  return consent?.granted === true;
}
typescript
interface ConsentRecord {
  userId: string;
  purpose: string;         // 'marketing', 'analytics', 'essential'
  granted: boolean;
  grantedAt: Date;
  ipAddress: string;
  version: string;          // Policy version at time of consent
}

app.post('/api/consent', auth, async (req, res) => {
  const { purposes } = req.body; // { marketing: true, analytics: false }

  for (const [purpose, granted] of Object.entries(purposes)) {
    await db.consent.upsert({
      where: { userId_purpose: { userId: req.user.id, purpose } },
      create: {
        userId: req.user.id,
        purpose,
        granted: granted as boolean,
        grantedAt: new Date(),
        ipAddress: req.ip,
        version: CURRENT_PRIVACY_POLICY_VERSION,
      },
      update: {
        granted: granted as boolean,
        grantedAt: new Date(),
        ipAddress: req.ip,
        version: CURRENT_PRIVACY_POLICY_VERSION,
      },
    });
  }

  res.json({ updated: true });
});

// Check consent before processing
async function hasConsent(userId: string, purpose: string): Promise<boolean> {
  const consent = await db.consent.findUnique({
    where: { userId_purpose: { userId, purpose } },
  });
  return consent?.granted === true;
}

PII Field Handling

PII字段处理

typescript
// Mark PII fields in schema
const PII_FIELDS = {
  user: ['email', 'name', 'phone', 'address', 'dateOfBirth'],
  order: ['customerName', 'shippingAddress', 'email'],
} as const;

// Encrypt PII at rest
const encryptedFields = ['dateOfBirth', 'phone', 'address'];

// Pseudonymization for analytics
function pseudonymize(userId: string): string {
  return createHmac('sha256', PSEUDONYM_KEY).update(userId).digest('hex');
}
typescript
// Mark PII fields in schema
const PII_FIELDS = {
  user: ['email', 'name', 'phone', 'address', 'dateOfBirth'],
  order: ['customerName', 'shippingAddress', 'email'],
} as const;

// Encrypt PII at rest
const encryptedFields = ['dateOfBirth', 'phone', 'address'];

// Pseudonymization for analytics
function pseudonymize(userId: string): string {
  return createHmac('sha256', PSEUDONYM_KEY).update(userId).digest('hex');
}

Cookie Consent Banner

Cookie同意横幅

typescript
// Express middleware — block non-essential cookies without consent
function cookieConsentMiddleware(req: Request, res: Response, next: NextFunction) {
  const consent = req.cookies['cookie-consent'];
  if (!consent) {
    // Only set essential cookies
    req.analyticsEnabled = false;
    req.marketingEnabled = false;
  } else {
    const prefs = JSON.parse(consent);
    req.analyticsEnabled = prefs.analytics === true;
    req.marketingEnabled = prefs.marketing === true;
  }
  next();
}
typescript
// Express middleware — block non-essential cookies without consent
function cookieConsentMiddleware(req: Request, res: Response, next: NextFunction) {
  const consent = req.cookies['cookie-consent'];
  if (!consent) {
    // Only set essential cookies
    req.analyticsEnabled = false;
    req.marketingEnabled = false;
  } else {
    const prefs = JSON.parse(consent);
    req.analyticsEnabled = prefs.analytics === true;
    req.marketingEnabled = prefs.marketing === true;
  }
  next();
}

Anti-Patterns

反模式

Anti-PatternFix
Hard-deleting all dataAnonymize where referential integrity needed
No consent versioningTrack which policy version user consented to
PII in log filesRedact or pseudonymize PII before logging
Consent as one checkboxGranular consent per purpose (marketing, analytics)
No data processing recordsMaintain Article 30 records of processing activities
Ignoring third-party data sharingDocument and control all data processors
反模式修复方案
硬删除所有数据在需要保持引用完整性的地方进行匿名化处理
无同意版本控制记录用户同意的政策版本
日志文件中包含PII记录前编辑或伪匿名化PII
单一复选框式同意按用途(营销、分析)提供细粒度同意选项
无数据处理记录维护第30条要求的处理活动记录
忽略第三方数据共享记录并管控所有数据处理方

Production Checklist

生产环境检查清单

  • Data subject access request endpoint
  • Data deletion/anonymization endpoint
  • Consent management with purpose granularity
  • Consent versioning (tracks policy version)
  • PII inventory documented
  • Data retention policies implemented
  • Cookie consent banner (EU users)
  • Data Processing Agreement with third parties
  • Article 30 records of processing activities
  • 数据主体访问请求端点
  • 数据删除/匿名化端点
  • 按用途细分的同意管理
  • 同意版本控制(跟踪政策版本)
  • 已记录PII清单
  • 已实施数据保留政策
  • Cookie同意横幅(针对欧盟用户)
  • 与第三方签订的数据处理协议
  • 第30条要求的处理活动记录