UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

372 lines (312 loc) 7.88 kB
const fs = require('fs'); const merge = require('lodash/merge'); const { Datastore } = require('../../dist/sdk'); const DEFAULT_CONFIG = { sections: [ 'purpose', 'owner', 'persons', 'recipients', 'duration', 'security_policies', 'updated_at', ], i18n: { title: 'Data Processings', 'section.purpose': 'Purpose', 'section.owner': 'Responsible for processing personal data', 'section.contact-details': 'Contact Details', 'section.persons': 'Categories of people concerned', 'section.recipients': 'Categories of recipients of data', 'section.duration': 'Shelf life of data', 'section.security_policies': 'Security Policies', 'section.updated_at': 'Updated At', activity: 'Activity', address: 'Address', email: 'Email', phone: 'Phone', url: 'URL', }, persons: { users: 'Users of the platform', }, }; function i18n(config, key, defaultValue = key) { if (process.env.I18N_DISABLED === 'false') { return key; } return config.i18n[key] ?? defaultValue; } function buildHeader(config) { return ` # ${i18n(config, 'title')} ${config.header} `; } function buildFooter(config) { return ` ${config.footer ?? i18n(config, 'title', '')} `; } function buildSection( config, modelConfig, processing, processingIndex, activityIndex, section, ) { return ` #### ${i18n(config, 'section.' + section)} ${ config[section] ?? i18n( config, `${modelConfig.name}.${processing.field}.${processing.name}.${section}`, processing[section], ) } `; } function buildCategory( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.category')} ${i18n(config, `category.${processing.category}`, processing.category)} `; } function buildOwner( config, modelConfig, processing, processingIndex, activityIndex, ) { const owner = processing.owner || config.owner; return ` #### ${i18n(config, 'section.owner')} ${owner.name} #### ${i18n(config, 'section.contact-details')} | <!-- --> | <!-- --> | |-------------|-------------| | ${i18n(config, 'address')} | ${owner.location?.address ?? '<address>'} - ${ owner.location?.postal_code ?? '<postal_code>' } ${owner.location?.city ?? '<city>'} | | ${i18n(config, 'email')} | ${owner.email ?? 'NA'} | | ${i18n(config, 'phone')} | ${owner.phone ?? 'NA'} | | ${i18n(config, 'url')} | ${owner.url ?? 'NA'} | `; } function buildSource( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.source')} ${i18n(config, `roles.${processing.source}`, processing.source)}.`; } function buildPersons( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.persons')} | <!-- --> | <!-- --> | |-------------|-------------| ${processing.persons .map((p) => `| \`${p}\` | ${i18n(config, `roles.${p}`, p ?? 'NA')} |`) .join('\n')} `; } function buildRecipients( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.recipients')} | <!-- --> | <!-- --> | |-------------|-------------| ${processing.recipients .map((r) => `| \`${r}\` | ${i18n(config, `roles.${r}`, r ?? 'NA')} |`) .join('\n')} `; } function buildDuration( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.duration')} - ${Math.round(processing.duration_in_seconds / (60 * 60 * 24 * 365))} years - ${Math.round(processing.duration_in_seconds / (60 * 60 * 24 * 30))} months - ${Math.round(processing.duration_in_seconds / (60 * 60 * 24))} days - ${Math.round(processing.duration_in_seconds / (60 * 60))} hours - ${Math.round(processing.duration_in_seconds / 60)} minutes - ${processing.duration_in_seconds} seconds `; } function buildUpdatedAt( config, modelConfig, processing, processingIndex, activityIndex, ) { return ` #### ${i18n(config, 'section.updated_at')} ${new Date(modelConfig.updated_at).toLocaleDateString(config.locale || 'en', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', })} `; } function withSection(body, property, config, modelConfig, processing, pi, ai) { if (property === 'updated_at') { body += buildUpdatedAt(config, modelConfig, processing, pi, ai); } if (!processing[property] && !config[property]) { return body; } switch (property) { case 'owner': body += buildOwner(config, modelConfig, processing, pi, ai); break; case 'category': body += buildCategory(config, modelConfig, processing, pi, ai); break; case 'source': body += buildSource(config, modelConfig, processing, pi, ai); break; case 'persons': body += buildPersons(config, modelConfig, processing, pi, ai); break; case 'recipients': body += buildRecipients(config, modelConfig, processing, pi, ai); break; case 'duration_in_seconds': body += buildDuration(config, modelConfig, processing, pi, ai); break; default: if (processing[property] || config[property]) { body += buildSection(config, modelConfig, processing, pi, ai, property); } } return body; } function buildProcessing( config, modelConfig, processing, processingIndex, activityIndex, ) { let body = '\n<div class="page"/>\n\n'; if (processingIndex === 0) { body += '## ' + i18n(config, `model.${modelConfig.name}`, `${modelConfig.name}`) + '\n\n'; } body += '### ' + i18n(config, 'activity') + ' ' + (activityIndex + 1) + '.' + (processingIndex + 1) + ' - ' + i18n( config, `field.${modelConfig.name}.${processing.field}`, `\`${processing.field}\``, ) + ' - ' + i18n(config, 'processing.' + processing.name, null) ?? processing.name + '\n\n'; for (const section of config.sections) { body = withSection( body, section, config, modelConfig, processing, processingIndex, activityIndex, ); } body += '\n---\n'; return body; } function buildProcessings(config, modelConfig, processings, activityIndex) { let body = ''; body += processings .map((processing, processingIndex) => buildProcessing( config, modelConfig, processing, processingIndex, activityIndex, ), ) .join(`\n`); return body; } async function main(configPath) { console.log('[gdpr#processings] Starting the generation...'); const datastore = new Datastore({ baseUrl: process.env.DATASTORE_API_URL || 'http://localhost:3001', token: process.env.DATASTORE_ACCESS_TOKEN || 'token', debug: false, }); const { data: models } = await datastore.getModels(); const config = require(configPath); const buildConfig = merge({}, DEFAULT_CONFIG, config); let body = buildHeader(buildConfig); let activityIndex = -1; for (const modelConfig of Object.values(models)) { if (config.only?.length > 0 && !config.only.includes(modelConfig.name)) { continue; } const processings = modelConfig.processings ?? []; if (processings.length === 0) { continue; } activityIndex += 1; body += buildProcessings( buildConfig, modelConfig, processings, activityIndex, ); } body += buildFooter(buildConfig); fs.writeFileSync('/tmp/processings.md', body); console.log('[gdpr#processings] Generation ended successfully'); } main(...process.argv.slice(2)).catch((err) => { console.error(err); if (err?.response?.data) { console.error('[gdpr#processings] Error', err?.response?.data); } process.exit(1); });