diff --git a/components/report-window/deduce-problems.tsx b/components/report-window/deduce-problems.tsx index 6694be7..68e45a5 100644 --- a/components/report-window/deduce-problems.tsx +++ b/components/report-window/deduce-problems.tsx @@ -2,18 +2,14 @@ import { RequestCluster } from '../../request-cluster'; import { ParsedAnswers } from './parse-answers'; import NoInformationAtAllProblem from './problems/no-information-at-all'; import { Problem } from './problems/problem'; +import { UnknownLegalBasis } from './problems/unknown-legal-basis'; import { UnlawfulCookieAccess } from './problems/unlawful-cookies'; export default function deduceProblems( answers: ParsedAnswers, clusters: Record ): Problem[] { - const problems = []; - if (answers.popup_type === 'none') { - problems.push(new NoInformationAtAllProblem(answers, clusters)); - } - if (UnlawfulCookieAccess.qualifies(answers, Object.values(clusters))) { - problems.push(new UnlawfulCookieAccess(answers, clusters)); - } - return problems; + return [NoInformationAtAllProblem, UnlawfulCookieAccess, UnknownLegalBasis] + .map((c) => new c(answers, clusters)) + .filter((p) => p.qualifies()); } diff --git a/components/report-window/email-content.tsx b/components/report-window/email-content.tsx index 340564f..37e6efc 100644 --- a/components/report-window/email-content.tsx +++ b/components/report-window/email-content.tsx @@ -19,6 +19,7 @@ export default function EmailContent({ visited_url: string; clusters: Record; }) { + console.log('rendering email!', answers); const _ = (key: string) => v(key, answers.zaimek); const problems = deduceProblems(answers, clusters); const explainers = Array.from( diff --git a/components/report-window/explainers.tsx b/components/report-window/explainers.tsx index de02fd1..f360caa 100644 --- a/components/report-window/explainers.tsx +++ b/components/report-window/explainers.tsx @@ -20,7 +20,7 @@ export const Explainers: Record J W wypadku, gdy ujawnienie czy dostęp do danych osobowych zostało dokonane przez skrypty podmiotów trzecich (np. Google, Facebook, itp), których autorem nie jest Administrator strony, Administrator wciąż jest odpowiedzialny za procesy - przetwarzania danych osobowych, jakie realizują te skrypty—w myśl treści{' '} + przetwarzania danych osobowych, jakie realizują te skrypty - w myśl treści{' '} wyroku TSUE w sprawie C-40/17 diff --git a/components/report-window/generate-survey-questions.ts b/components/report-window/generate-survey-questions.ts index 0b12500..cbf8011 100644 --- a/components/report-window/generate-survey-questions.ts +++ b/components/report-window/generate-survey-questions.ts @@ -16,14 +16,7 @@ function generateHostPage( return { defaultValueExpression: `{${f(name, previous_cluster)}}` }; } const domain = cluster.id; - let types_of_data: string[] = []; - if (cluster.exposesOrigin()) { - types_of_data.push('część Twojej historii przeglądania'); - } - if (cluster.hasMarkedCookies()) { - types_of_data.push('unikalne ID z cookies'); - } - const danych = types_of_data.join(', '); + const danych = cluster.getDataTypeDescription(); return { title: cluster.id, elements: [ diff --git a/components/report-window/parse-answers.ts b/components/report-window/parse-answers.ts index 7aebc79..6467164 100644 --- a/components/report-window/parse-answers.ts +++ b/components/report-window/parse-answers.ts @@ -50,6 +50,7 @@ export function parseAnswers({ mentions_passive_consent, rejection_is_hard, administrator_identity_available_before_choice, + popup_action, ...rest }: RawAnswers): ParsedAnswers { return { @@ -62,6 +63,7 @@ export function parseAnswers({ mentions_passive_consent, rejection_is_hard, administrator_identity_available_before_choice, + popup_action, hosts: parseHostAnswers(rest), } as ParsedAnswers; } diff --git a/components/report-window/problems/no-information-at-all.tsx b/components/report-window/problems/no-information-at-all.tsx index c12158c..a0ef0f5 100644 --- a/components/report-window/problems/no-information-at-all.tsx +++ b/components/report-window/problems/no-information-at-all.tsx @@ -3,6 +3,9 @@ import { v } from '../verbs'; import { Problem } from './problem'; export default class NoInformationAtAllProblem extends Problem { + qualifies() { + return this.answers.popup_type === 'none'; + } getEmailContent() { const _ = (word: string) => v(word, this.answers.zaimek); return ( diff --git a/components/report-window/problems/problem.tsx b/components/report-window/problems/problem.tsx index 7815171..0c667a1 100644 --- a/components/report-window/problems/problem.tsx +++ b/components/report-window/problems/problem.tsx @@ -19,6 +19,7 @@ export abstract class Problem { abstract getEmailContent(): JSX.Element; abstract getNecessaryExplainers(): ExplainerKey[]; + abstract qualifies(): boolean; getMarkedClusters() { return Object.values(this.clusters).filter((c) => c.hasMarks()); diff --git a/components/report-window/problems/unknown-legal-basis.tsx b/components/report-window/problems/unknown-legal-basis.tsx new file mode 100644 index 0000000..598d18d --- /dev/null +++ b/components/report-window/problems/unknown-legal-basis.tsx @@ -0,0 +1,70 @@ +import { RequestCluster } from '../../../request-cluster'; +import { ExplainerKey } from '../explainers'; +import { ParsedHostAnswers } from '../parse-answers'; +import { v } from '../verbs'; +import { Problem } from './problem'; + +const testCluster: (cluster: RequestCluster, answers: ParsedHostAnswers | undefined) => boolean = ( + cluster, + hostAnswers +) => { + if (!hostAnswers) { + return false; + } + if (cluster.hasMarkedCookies()) { + /* if it has cookies, it will be picked up by the UnlawfulCookieAccess problem, and that one + is pretty detailed, so no need to mention it here. */ + return false; + } + return hostAnswers.legal_basis_type == 'not_mentioned'; +}; + +export class UnknownLegalBasis extends Problem { + getNecessaryExplainers(): ExplainerKey[] { + return ['responsibility_for_third_parties']; + } + + qualifies(): boolean { + return Object.values(this.clusters).some((cluster) => + testCluster(cluster, this.answers.hosts[cluster.id]) + ); + } + + getRelatedClusters() { + return Object.values(this.clusters).filter((cluster) => + testCluster(cluster, this.answers.hosts[cluster.id]) + ); + } + + getEmailContent() { + const clusters = this.getRelatedClusters(); + const _ = (key: string) => v(key, this.answers.zaimek); + return ( + <> +

Przetwarzanie danych osobowych bez podania podstawy prawnej

+

Państwa strona przetworzyła {_('moje')} dane osobowe poprzez ujawnienie:

+
    + {clusters.map((cluster) => ( +
  • + Właścicielowi domeny {cluster.id}:{' '} + {cluster.getDataTypeDescription('mojej')} +
  • + ))} +
+

+ {_('Moja')} historia przeglądania stanowi {_('moje')} dane osobowe. Zgodnie z + treścią Artykułu 13 p. 1 lit. c){' '} + + RODO + + , aby przetwarzać dane osobowe, trzeba poinformować osobę, której dane dotyczą, + o tym, jaka jest podstawa prawna takiego przetwarzania danych. +

+

+ Zwracam się zatem z pytaniem: jakie były podstawy prawne ujawnienia moich danych + każdemu z wyżej wymienionych podmiotów przez Państwa stronę? +

+ + ); + } +} diff --git a/components/report-window/problems/unlawful-cookies.tsx b/components/report-window/problems/unlawful-cookies.tsx index b23948d..c848502 100644 --- a/components/report-window/problems/unlawful-cookies.tsx +++ b/components/report-window/problems/unlawful-cookies.tsx @@ -1,7 +1,5 @@ -import { RequestCluster } from '../../../request-cluster'; import { wordlist } from '../../../util'; import { ExplainerKey } from '../explainers'; -import { ParsedAnswers } from '../parse-answers'; import { v } from '../verbs'; import { Problem } from './problem'; @@ -10,16 +8,16 @@ export class UnlawfulCookieAccess extends Problem { return ['cookies_are_pii', 'responsibility_for_third_parties']; } - static qualifies(answers: ParsedAnswers, clusters: RequestCluster[]): boolean { + qualifies(): boolean { // są cookiesy, nie było zgody, nie są konieczne do działania strony - const cookie_clusters = Object.values(clusters).filter((c) => c.hasMarkedCookies()); + const cookie_clusters = Object.values(this.clusters).filter((c) => c.hasMarkedCookies()); return cookie_clusters.some((cluster) => { - const hostAnswers = answers.hosts[cluster.id]; + const hostAnswers = this.answers.hosts[cluster.id]; return ( (hostAnswers.present == 'not_mentioned' || hostAnswers.present == 'not_before_making_a_choice' || - ['none', 'closed_popup', 'deny_all'].includes(answers.popup_action) || - answers.popup_type === 'none') && + ['none', 'closed_popup', 'deny_all'].includes(this.answers.popup_action) || + this.answers.popup_type === 'none') && hostAnswers.was_processing_necessary != 'yes' ); }); diff --git a/components/report-window/verbs.ts b/components/report-window/verbs.ts index 1136094..cf23b42 100644 --- a/components/report-window/verbs.ts +++ b/components/report-window/verbs.ts @@ -8,6 +8,7 @@ const words = { mnie: ['mnie', 'mnie', 'mnie', 'nas'], moich: ['moich', 'moich', 'moich', 'naszych'], moje: ['moje', 'moje', 'moje', 'nasze'], + moja: ['moja', 'moja', 'moja', 'nasza'], mojej: ['mojej', 'mojej', 'mojej', 'naszej'], muszę: ['muszę', 'muszę', 'muszę', 'musimy'], odkliknąłeś: ['odkliknąłeś', 'odkliknęłaś', 'odklikęłoś', 'odkliknęliście'], diff --git a/package-lock.json b/package-lock.json index 1a32d4d..45a2eff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "rentgen", "version": "0.0.3", "license": "GPL-3.0-or-later", "dependencies": { diff --git a/request-cluster.ts b/request-cluster.ts index 0ae09e4..7379228 100644 --- a/request-cluster.ts +++ b/request-cluster.ts @@ -182,4 +182,15 @@ export class RequestCluster extends SaferEmitter { entry.unmark(); }); } + + getDataTypeDescription(noun = 'Twojej') { + let types_of_data: string[] = []; + if (this.exposesOrigin()) { + types_of_data.push(`część ${noun} historii przeglądania`); + } + if (this.hasMarkedCookies()) { + types_of_data.push('unikalne ID z cookies'); + } + return types_of_data.join(', '); + } } diff --git a/safer-emitter.ts b/safer-emitter.ts index 9909331..011919d 100644 --- a/safer-emitter.ts +++ b/safer-emitter.ts @@ -48,7 +48,6 @@ export class SaferEmitter extends EventEmitter { Reflect.apply(listener, this, args); } catch (error) { console.error(error); - debugger; } }); }