Compare commits
6 Commits
592122a7da
...
3ab97b23aa
Author | SHA1 | Date | |
---|---|---|---|
3ab97b23aa | |||
f39bfd12b5 | |||
6e062f92d7 | |||
d512e3cede | |||
c22c8a9045 | |||
052eb5eb89 |
@ -2,18 +2,15 @@ import { RequestCluster } from '../../request-cluster';
|
|||||||
import { ParsedAnswers } from './parse-answers';
|
import { ParsedAnswers } from './parse-answers';
|
||||||
import NoInformationAtAllProblem from './problems/no-information-at-all';
|
import NoInformationAtAllProblem from './problems/no-information-at-all';
|
||||||
import { Problem } from './problems/problem';
|
import { Problem } from './problems/problem';
|
||||||
|
import { TransferOutsideEU } from './problems/transfer-outside-eu';
|
||||||
|
import { UnknownLegalBasis } from './problems/unknown-legal-basis';
|
||||||
import { UnlawfulCookieAccess } from './problems/unlawful-cookies';
|
import { UnlawfulCookieAccess } from './problems/unlawful-cookies';
|
||||||
|
|
||||||
export default function deduceProblems(
|
export default function deduceProblems(
|
||||||
answers: ParsedAnswers,
|
answers: ParsedAnswers,
|
||||||
clusters: Record<string, RequestCluster>
|
clusters: Record<string, RequestCluster>
|
||||||
): Problem[] {
|
): Problem[] {
|
||||||
const problems = [];
|
return [NoInformationAtAllProblem, UnlawfulCookieAccess, UnknownLegalBasis, TransferOutsideEU]
|
||||||
if (answers.popup_type === 'none') {
|
.map((c) => new c(answers, clusters))
|
||||||
problems.push(new NoInformationAtAllProblem(answers, clusters));
|
.filter((p) => p.qualifies());
|
||||||
}
|
|
||||||
if (UnlawfulCookieAccess.qualifies(answers, Object.values(clusters))) {
|
|
||||||
problems.push(new UnlawfulCookieAccess(answers, clusters));
|
|
||||||
}
|
|
||||||
return problems;
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ export default function EmailContent({
|
|||||||
visited_url: string;
|
visited_url: string;
|
||||||
clusters: Record<string, RequestCluster>;
|
clusters: Record<string, RequestCluster>;
|
||||||
}) {
|
}) {
|
||||||
|
console.log('rendering email!', answers);
|
||||||
const _ = (key: string) => v(key, answers.zaimek);
|
const _ = (key: string) => v(key, answers.zaimek);
|
||||||
const problems = deduceProblems(answers, clusters);
|
const problems = deduceProblems(answers, clusters);
|
||||||
const explainers = Array.from(
|
const explainers = Array.from(
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export type ExplainerKey = 'cookies_are_pii';
|
// various explainers that could be related to multiple problems. They are gathered here and added at the end of the email to avoid pasting them multiple times
|
||||||
|
|
||||||
|
export type ExplainerKey = 'cookies_are_pii' | 'responsibility_for_third_parties';
|
||||||
|
|
||||||
export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => JSX.Element> = {
|
export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => JSX.Element> = {
|
||||||
cookies_are_pii: () => (
|
cookies_are_pii: () => (
|
||||||
@ -11,4 +13,18 @@ export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => J
|
|||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
responsibility_for_third_parties: () => (
|
||||||
|
<>
|
||||||
|
<h2>Administrator strony ponosi odpowiedzialność za skrypty podmiotów trzecich</h2>
|
||||||
|
<p>
|
||||||
|
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{' '}
|
||||||
|
<a href="https://curia.europa.eu/juris/document/document.jsf?text=&docid=216555&pageIndex=0&doclang=PL&mode=lst&dir=&occ=first&part=1&cid=1254905">
|
||||||
|
wyroku TSUE w sprawie C-40/17
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
@ -1,26 +1,30 @@
|
|||||||
|
import { RequestCluster } from '../../request-cluster';
|
||||||
|
|
||||||
function generateHostPage(
|
function generateHostPage(
|
||||||
host: string,
|
cluster: RequestCluster,
|
||||||
index: number,
|
index: number,
|
||||||
all_hosts: string[]
|
all_clusters: RequestCluster[]
|
||||||
): { title: string; elements: any[]; visibleIf: string } {
|
): { title: string; elements: any[]; visibleIf?: string } {
|
||||||
function f(name: string, h = host) {
|
function f(name: string, c = cluster) {
|
||||||
return `${h.replace(/\./g, '_')}|${name}`;
|
return `${c.id.replace(/\./g, '_')}|${name}`;
|
||||||
}
|
}
|
||||||
const previous_host: string | null = index > 0 ? all_hosts[index - 1] : null;
|
const previous_cluster: RequestCluster | null = index > 0 ? all_clusters[index - 1] : null;
|
||||||
function defaultValue(name: string) {
|
function defaultValue(name: string) {
|
||||||
if (!previous_host) {
|
if (!previous_cluster) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return { defaultValueExpression: `{${f(name, previous_host)}}` };
|
return { defaultValueExpression: `{${f(name, previous_cluster)}}` };
|
||||||
}
|
}
|
||||||
|
const domain = cluster.id;
|
||||||
|
const danych = cluster.getDataTypeDescription();
|
||||||
return {
|
return {
|
||||||
title: host,
|
title: cluster.id,
|
||||||
elements: [
|
elements: [
|
||||||
{
|
{
|
||||||
type: 'radiogroup',
|
type: 'radiogroup',
|
||||||
name: f('present'),
|
name: f('present'),
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
title: `Cel ujawnienia danych właścicielowi domeny ${host}`,
|
title: `Cel ujawnienia danych (${danych}) właścicielowi domeny ${domain}`,
|
||||||
...defaultValue('present'),
|
...defaultValue('present'),
|
||||||
visibleIf: '{popup_type} != "none"',
|
visibleIf: '{popup_type} != "none"',
|
||||||
choices: [
|
choices: [
|
||||||
@ -56,10 +60,10 @@ function generateHostPage(
|
|||||||
'present'
|
'present'
|
||||||
)}} != "not_mentioned" and {${f('present')}} != "not_before_making_a_choice"`,
|
)}} != "not_mentioned" and {${f('present')}} != "not_before_making_a_choice"`,
|
||||||
choices: [
|
choices: [
|
||||||
{ value: 'consent', text: 'to zgoda.' },
|
{ value: 'consent', text: 'to zgoda (art. 6 ust. 1 lit. a RODO).' },
|
||||||
{
|
{
|
||||||
value: 'legitimate_interest',
|
value: 'legitimate_interest',
|
||||||
text: 'to uzasadniony interes.',
|
text: 'to uzasadniony interes (art. 6 ust. 1 lit. f RODO).',
|
||||||
},
|
},
|
||||||
{ value: 'not_mentioned', text: 'nie jest wskazana nigdzie na stronie.' },
|
{ value: 'not_mentioned', text: 'nie jest wskazana nigdzie na stronie.' },
|
||||||
],
|
],
|
||||||
@ -76,7 +80,7 @@ function generateHostPage(
|
|||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
value: 'claims_consent_but_sends_before_consent',
|
value: 'claims_consent_but_sends_before_consent',
|
||||||
text: `Strona wysłała {moje} dane do ${host} zanim {wyraziłem} na to zgodę`,
|
text: `Strona wysłała {moje} dane do ${domain} zanim {wyraziłem} na to zgodę`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'claims_consent_but_there_was_no_easy_refuse',
|
value: 'claims_consent_but_there_was_no_easy_refuse',
|
||||||
@ -111,18 +115,18 @@ function generateHostPage(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
title: `Jak administrator opisał to, na czym polega uzasadniony interes w kontekście ${host}?`,
|
title: `Jak administrator opisał to, na czym polega uzasadniony interes w kontekście ${domain}?`,
|
||||||
name: f('legitimate_interest_description'),
|
name: f('legitimate_interest_description'),
|
||||||
visibleIf: `{${f('legitimate_interest_activity_specified')}} = 'vague'`,
|
visibleIf: `{${f('legitimate_interest_activity_specified')}} = 'vague'`,
|
||||||
placeholder: 'marketing',
|
placeholder: 'marketing',
|
||||||
defaultValueExpression:
|
defaultValueExpression:
|
||||||
index == 0
|
index == 0
|
||||||
? 'marketing'
|
? 'marketing'
|
||||||
: `{${f('legitimate_interest_description', previous_host)}}`,
|
: `{${f('legitimate_interest_description', previous_cluster)}}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'radiogroup',
|
type: 'radiogroup',
|
||||||
title: `Czy domena ${host} należy do podmiotu spoza Europy (np. Google, Facebook)?`,
|
title: `Czy domena ${domain} należy do podmiotu spoza Europy (np. Google, Facebook)?`,
|
||||||
name: f('outside_eu'),
|
name: f('outside_eu'),
|
||||||
...defaultValue('outside_eu'),
|
...defaultValue('outside_eu'),
|
||||||
visibleIf: `{${f('legitimate_interest_activity_specified')}} = "precise" or {${f(
|
visibleIf: `{${f('legitimate_interest_activity_specified')}} = "precise" or {${f(
|
||||||
@ -137,7 +141,7 @@ function generateHostPage(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'radiogroup',
|
type: 'radiogroup',
|
||||||
title: `Czy w {Twojej} ocenie wysłanie {Twoich} danych do właściciela domeny ${host} było konieczne do świadczenia zażądanej przez {Ciebie} usługi drogą elektroniczną?`,
|
title: `Czy w {Twojej} ocenie ujawnienie {Twoich} danych (${danych}) właścicielowi domeny ${domain} było konieczne do świadczenia zażądanej przez {Ciebie} usługi drogą elektroniczną?`,
|
||||||
name: f('was_processing_necessary'),
|
name: f('was_processing_necessary'),
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
...defaultValue('was_processing_necessary'),
|
...defaultValue('was_processing_necessary'),
|
||||||
@ -154,7 +158,7 @@ function generateHostPage(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function generateSurveyQuestions(hosts: string[]) {
|
export default function generateSurveyQuestions(clusters: RequestCluster[]) {
|
||||||
return {
|
return {
|
||||||
showQuestionNumbers: 'off',
|
showQuestionNumbers: 'off',
|
||||||
showProgressBar: 'top',
|
showProgressBar: 'top',
|
||||||
@ -393,7 +397,7 @@ export default function generateSurveyQuestions(hosts: string[]) {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
...hosts.map(generateHostPage),
|
...clusters.map(generateHostPage),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ export function parseAnswers({
|
|||||||
mentions_passive_consent,
|
mentions_passive_consent,
|
||||||
rejection_is_hard,
|
rejection_is_hard,
|
||||||
administrator_identity_available_before_choice,
|
administrator_identity_available_before_choice,
|
||||||
|
popup_action,
|
||||||
...rest
|
...rest
|
||||||
}: RawAnswers): ParsedAnswers {
|
}: RawAnswers): ParsedAnswers {
|
||||||
return {
|
return {
|
||||||
@ -62,6 +63,7 @@ export function parseAnswers({
|
|||||||
mentions_passive_consent,
|
mentions_passive_consent,
|
||||||
rejection_is_hard,
|
rejection_is_hard,
|
||||||
administrator_identity_available_before_choice,
|
administrator_identity_available_before_choice,
|
||||||
|
popup_action,
|
||||||
hosts: parseHostAnswers(rest),
|
hosts: parseHostAnswers(rest),
|
||||||
} as ParsedAnswers;
|
} as ParsedAnswers;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ import { v } from '../verbs';
|
|||||||
import { Problem } from './problem';
|
import { Problem } from './problem';
|
||||||
|
|
||||||
export default class NoInformationAtAllProblem extends Problem {
|
export default class NoInformationAtAllProblem extends Problem {
|
||||||
|
qualifies() {
|
||||||
|
return this.answers.popup_type === 'none';
|
||||||
|
}
|
||||||
getEmailContent() {
|
getEmailContent() {
|
||||||
const _ = (word: string) => v(word, this.answers.zaimek);
|
const _ = (word: string) => v(word, this.answers.zaimek);
|
||||||
return (
|
return (
|
||||||
@ -39,6 +42,7 @@ export default class NoInformationAtAllProblem extends Problem {
|
|||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
explainers.push('cookies_are_pii');
|
explainers.push('cookies_are_pii');
|
||||||
|
explainers.push('responsibility_for_third_parties');
|
||||||
}
|
}
|
||||||
return explainers;
|
return explainers;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ export abstract class Problem {
|
|||||||
|
|
||||||
abstract getEmailContent(): JSX.Element;
|
abstract getEmailContent(): JSX.Element;
|
||||||
abstract getNecessaryExplainers(): ExplainerKey[];
|
abstract getNecessaryExplainers(): ExplainerKey[];
|
||||||
|
abstract qualifies(): boolean;
|
||||||
|
|
||||||
getMarkedClusters() {
|
getMarkedClusters() {
|
||||||
return Object.values(this.clusters).filter((c) => c.hasMarks());
|
return Object.values(this.clusters).filter((c) => c.hasMarks());
|
||||||
|
63
components/report-window/problems/transfer-outside-eu.tsx
Normal file
63
components/report-window/problems/transfer-outside-eu.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { RequestCluster } from '../../../request-cluster';
|
||||||
|
import { ExplainerKey } from '../explainers';
|
||||||
|
import { v } from '../verbs';
|
||||||
|
import { Problem } from './problem';
|
||||||
|
|
||||||
|
export class TransferOutsideEU extends Problem {
|
||||||
|
getNecessaryExplainers(): ExplainerKey[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
qualifies(): boolean {
|
||||||
|
return Object.values(this.answers.hosts).some(
|
||||||
|
(hostAnswers) => hostAnswers.outside_eu == 'yes'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRelatedClusters(): RequestCluster[] {
|
||||||
|
return Object.entries(this.answers.hosts)
|
||||||
|
.filter(([_, hostAnswers]) => hostAnswers.outside_eu == 'yes')
|
||||||
|
.map(([id]) => this.clusters[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmailContent() {
|
||||||
|
const clusters = this.getRelatedClusters();
|
||||||
|
const _ = (key: string) => v(key, this.answers.zaimek);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2>Transfer danych osobowych poza Europejski Obszar Gospodarczy</h2>
|
||||||
|
<p>
|
||||||
|
Państwa strona przetworzyła {_('moje')} dane osobowe poprzez przesłanie danych
|
||||||
|
do:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
{clusters.map((cluster) => (
|
||||||
|
<li key={cluster.id}>
|
||||||
|
Właściciela domeny <strong>{cluster.id}</strong>: (w zakresie:{' '}
|
||||||
|
{cluster.getDataTypeDescription('mojej')});
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Według {_('mojej')} najlepszej wiedzy, każdy z tych podmiotów utrzymuje swoje
|
||||||
|
serwery poza Europejskim Obszarem Gospodarczym. Zatem Państwa strona przesłała
|
||||||
|
{_('moje')} dane osobowe poza EOG. Jeżeli tak jest, to takie przetwarzanie
|
||||||
|
danych jest niezgodne z prawem, gdyż dane trafiają do krajów, które nie
|
||||||
|
gwarantują ochrony danych w stopniu, jakiego wymaga RODO, a tzw. „Tarcza
|
||||||
|
Prywatności” została unieważniona w 2020r. Zob.{' '}
|
||||||
|
<a href="https://panoptykon.org/noyb-skargi-schrems-ii">
|
||||||
|
artykuł Fundacji Panoptykon w tej sprawie
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{_('Zwracam')} się zatem do Państwa z pytaniem:{' '}
|
||||||
|
<strong>
|
||||||
|
czy wyżej wymienione podmioty, którym Państwa strona ujawniła moje dane
|
||||||
|
osobowe, przechowują moje dane poza EOG?
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
73
components/report-window/problems/unknown-legal-basis.tsx
Normal file
73
components/report-window/problems/unknown-legal-basis.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<h2>Przetwarzanie danych osobowych bez podania podstawy prawnej</h2>
|
||||||
|
<p>Państwa strona przetworzyła {_('moje')} dane osobowe poprzez ujawnienie:</p>
|
||||||
|
<ul>
|
||||||
|
{clusters.map((cluster) => (
|
||||||
|
<li key={cluster.id}>
|
||||||
|
Właścicielowi domeny <strong>{cluster.id}</strong>:{' '}
|
||||||
|
{cluster.getDataTypeDescription('mojej')}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
{_('Moja')} historia przeglądania stanowi {_('moje')} dane osobowe. Zgodnie z
|
||||||
|
treścią Artykułu 13 p. 1 lit. c){' '}
|
||||||
|
<a href="https://eur-lex.europa.eu/legal-content/PL/TXT/HTML/?uri=CELEX:32016R0679&qid=1632163985520&from=PL#d1e1822-1-1">
|
||||||
|
RODO
|
||||||
|
</a>
|
||||||
|
, aby przetwarzać dane osobowe, trzeba poinformować osobę, której dane dotyczą,
|
||||||
|
o tym, jaka jest podstawa prawna takiego przetwarzania danych.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Zwracam się zatem z pytaniem:{' '}
|
||||||
|
<strong>
|
||||||
|
jakie były podstawy prawne ujawnienia moich danych każdemu z wyżej
|
||||||
|
wymienionych podmiotów przez Państwa stronę?
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,23 @@
|
|||||||
import { RequestCluster } from '../../../request-cluster';
|
|
||||||
import { wordlist } from '../../../util';
|
import { wordlist } from '../../../util';
|
||||||
import { ExplainerKey } from '../explainers';
|
import { ExplainerKey } from '../explainers';
|
||||||
import { ParsedAnswers } from '../parse-answers';
|
|
||||||
import { v } from '../verbs';
|
import { v } from '../verbs';
|
||||||
import { Problem } from './problem';
|
import { Problem } from './problem';
|
||||||
|
|
||||||
export class UnlawfulCookieAccess extends Problem {
|
export class UnlawfulCookieAccess extends Problem {
|
||||||
getNecessaryExplainers(): ExplainerKey[] {
|
getNecessaryExplainers(): ExplainerKey[] {
|
||||||
return [];
|
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
|
// 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) => {
|
return cookie_clusters.some((cluster) => {
|
||||||
const hostAnswers = answers.hosts[cluster.id];
|
const hostAnswers = this.answers.hosts[cluster.id];
|
||||||
return (
|
return (
|
||||||
(hostAnswers.present == 'not_mentioned' ||
|
(hostAnswers.present == 'not_mentioned' ||
|
||||||
hostAnswers.present == 'not_before_making_a_choice' ||
|
hostAnswers.present == 'not_before_making_a_choice' ||
|
||||||
['none', 'closed_popup', 'deny_all'].includes(answers.popup_action) ||
|
['none', 'closed_popup', 'deny_all'].includes(this.answers.popup_action) ||
|
||||||
answers.popup_type === 'none') &&
|
this.answers.popup_type === 'none') &&
|
||||||
hostAnswers.was_processing_necessary != 'yes'
|
hostAnswers.was_processing_necessary != 'yes'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -76,7 +74,8 @@ export class UnlawfulCookieAccess extends Problem {
|
|||||||
<li>
|
<li>
|
||||||
Użytkownik wyraził zgodę na takie przetwarzanie danych <em>po</em> tym, jak
|
Użytkownik wyraził zgodę na takie przetwarzanie danych <em>po</em> tym, jak
|
||||||
został poinformowany bezpośrednio o celu uzyskania dostępu do tej
|
został poinformowany bezpośrednio o celu uzyskania dostępu do tej
|
||||||
informacji;
|
informacji. Zgodnie z Art. 174 ustawy Prawo Telekomunikacyjne, taka zgoda
|
||||||
|
musiałaby spełniać warunki zgody ustalone przez RODO;
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Dostęp do treści plików cookies jest konieczny do dostarczania usługi
|
Dostęp do treści plików cookies jest konieczny do dostarczania usługi
|
||||||
@ -163,9 +162,12 @@ export class UnlawfulCookieAccess extends Problem {
|
|||||||
''
|
''
|
||||||
)}
|
)}
|
||||||
<p>
|
<p>
|
||||||
{_('Proszę')} o wskazanie, czy być może stosowali Państwo inną podstawę prawną
|
{_('Proszę')} o wskazanie,{' '}
|
||||||
do takiego przetwarzania {_('moich')} danych osobowych, czy przetwarzali je
|
<strong>
|
||||||
państwo bez ważnej podstawy prawnej?
|
czy być może stosowali Państwo inną podstawę prawną do takiego przetwarzania{' '}
|
||||||
|
{_('moich')} danych osobowych, czy przetwarzali je państwo bez ważnej
|
||||||
|
podstawy prawnej?
|
||||||
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
{maybe_unnecessary_hosts.length > 1 ? (
|
{maybe_unnecessary_hosts.length > 1 ? (
|
||||||
<p>
|
<p>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import * as Survey from 'survey-react';
|
import * as Survey from 'survey-react';
|
||||||
|
import { RequestCluster } from '../../request-cluster';
|
||||||
import RawAnswers from './raw-answers';
|
import RawAnswers from './raw-answers';
|
||||||
import useSurvey from './use-survey';
|
import useSurvey from './use-survey';
|
||||||
|
|
||||||
export default function Questions({
|
export default function Questions({
|
||||||
hosts,
|
clusters,
|
||||||
onComplete,
|
onComplete,
|
||||||
}: {
|
}: {
|
||||||
hosts: string[];
|
clusters: RequestCluster[];
|
||||||
onComplete: (data: RawAnswers) => void;
|
onComplete: (data: RawAnswers) => void;
|
||||||
}) {
|
}) {
|
||||||
const survey = useSurvey(hosts, {
|
const survey = useSurvey(clusters, {
|
||||||
onComplete: (sender) => onComplete(sender.data),
|
onComplete: (sender) => onComplete(sender.data),
|
||||||
});
|
});
|
||||||
if (!survey) {
|
if (!survey) {
|
||||||
|
@ -35,9 +35,9 @@ function Report() {
|
|||||||
<div {...{ 'data-version': counter }}>
|
<div {...{ 'data-version': counter }}>
|
||||||
{mode === 'survey' ? (
|
{mode === 'survey' ? (
|
||||||
<Questions
|
<Questions
|
||||||
hosts={Object.values(clusters)
|
clusters={Object.values(clusters).filter(
|
||||||
.filter((cluster) => cluster.getMarkedRequests().length > 0)
|
(cluster) => cluster.getMarkedRequests().length > 0
|
||||||
.map((cluster) => cluster.id)}
|
)}
|
||||||
onComplete={(answers) => {
|
onComplete={(answers) => {
|
||||||
setAnswers(parseAnswers(answers));
|
setAnswers(parseAnswers(answers));
|
||||||
setMode('screenshots');
|
setMode('screenshots');
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as Survey from 'survey-react';
|
import * as Survey from 'survey-react';
|
||||||
|
import { RequestCluster } from '../../request-cluster';
|
||||||
import generateSurveyQuestions from './generate-survey-questions';
|
import generateSurveyQuestions from './generate-survey-questions';
|
||||||
import RawAnswers from './raw-answers';
|
import RawAnswers from './raw-answers';
|
||||||
import verbs, { v } from './verbs';
|
import verbs, { v } from './verbs';
|
||||||
|
|
||||||
export default function useSurvey(
|
export default function useSurvey(
|
||||||
hosts: string[],
|
clusters: RequestCluster[],
|
||||||
{ onComplete }: { onComplete: (sender: { data: RawAnswers }) => void }
|
{ onComplete }: { onComplete: (sender: { data: RawAnswers }) => void }
|
||||||
): Survey.ReactSurveyModel {
|
): Survey.ReactSurveyModel {
|
||||||
const [survey, setSurvey] = React.useState<Survey.Model>(null);
|
const [survey, setSurvey] = React.useState<Survey.Model>(null);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const model = generateSurveyQuestions(hosts);
|
const model = generateSurveyQuestions(clusters);
|
||||||
console.log(model);
|
console.log(model);
|
||||||
const survey = new Survey.Model(model);
|
const survey = new Survey.Model(model);
|
||||||
survey.onProcessTextValue.add(function (
|
survey.onProcessTextValue.add(function (
|
||||||
|
@ -8,6 +8,7 @@ const words = {
|
|||||||
mnie: ['mnie', 'mnie', 'mnie', 'nas'],
|
mnie: ['mnie', 'mnie', 'mnie', 'nas'],
|
||||||
moich: ['moich', 'moich', 'moich', 'naszych'],
|
moich: ['moich', 'moich', 'moich', 'naszych'],
|
||||||
moje: ['moje', 'moje', 'moje', 'nasze'],
|
moje: ['moje', 'moje', 'moje', 'nasze'],
|
||||||
|
moja: ['moja', 'moja', 'moja', 'nasza'],
|
||||||
mojej: ['mojej', 'mojej', 'mojej', 'naszej'],
|
mojej: ['mojej', 'mojej', 'mojej', 'naszej'],
|
||||||
muszę: ['muszę', 'muszę', 'muszę', 'musimy'],
|
muszę: ['muszę', 'muszę', 'muszę', 'musimy'],
|
||||||
odkliknąłeś: ['odkliknąłeś', 'odkliknęłaś', 'odklikęłoś', 'odkliknęliście'],
|
odkliknąłeś: ['odkliknąłeś', 'odkliknęłaś', 'odklikęłoś', 'odkliknęliście'],
|
||||||
|
@ -145,16 +145,6 @@ const Toolbar = () => {
|
|||||||
<section className="summary">
|
<section className="summary">
|
||||||
<div className="counters-wrapper">
|
<div className="counters-wrapper">
|
||||||
<div className="counters">
|
<div className="counters">
|
||||||
<div className="counter counter--browser-history">
|
|
||||||
<img src="/assets/icons/warning.svg#color" width="24" height="24" />
|
|
||||||
<span data-event={`${eventCounts['*']}`}>
|
|
||||||
{
|
|
||||||
Object.values(getMemory().getClustersForOrigin(origin)).filter(
|
|
||||||
(cluster) => cluster.exposesOrigin()
|
|
||||||
).length
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="counter counter--cookies">
|
<div className="counter counter--cookies">
|
||||||
<img src="/assets/icons/cookie.svg#color" width="24" height="24" />
|
<img src="/assets/icons/cookie.svg#color" width="24" height="24" />
|
||||||
<span data-event={`${eventCounts['*']}`}>
|
<span data-event={`${eventCounts['*']}`}>
|
||||||
@ -165,6 +155,16 @@ const Toolbar = () => {
|
|||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="counter counter--browser-history">
|
||||||
|
<img src="/assets/icons/warning.svg#color" width="24" height="24" />
|
||||||
|
<span data-event={`${eventCounts['*']}`}>
|
||||||
|
{
|
||||||
|
Object.values(getMemory().getClustersForOrigin(origin)).filter(
|
||||||
|
(cluster) => cluster.exposesOrigin()
|
||||||
|
).length
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="big-counter" data-event={`${eventCounts['*']}`}>
|
<div className="big-counter" data-event={`${eventCounts['*']}`}>
|
||||||
{Object.values(getMemory().getClustersForOrigin(origin)).length}
|
{Object.values(getMemory().getClustersForOrigin(origin)).length}
|
||||||
@ -174,18 +174,6 @@ const Toolbar = () => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="details">
|
<section className="details">
|
||||||
{exposedOriginDomainCopy ? (
|
|
||||||
<p
|
|
||||||
data-event={`${eventCounts['*']}`}
|
|
||||||
title={Object.values(getMemory().getClustersForOrigin(origin))
|
|
||||||
.filter((cluster) => cluster.exposesOrigin())
|
|
||||||
.map((domain) => domain.id)
|
|
||||||
.join(', ')}
|
|
||||||
>
|
|
||||||
{first_sentence_cookie}
|
|
||||||
<strong>{exposedOriginDomainCopy}</strong>
|
|
||||||
</p>
|
|
||||||
) : null}
|
|
||||||
{cookieDomainCopy ? (
|
{cookieDomainCopy ? (
|
||||||
<p
|
<p
|
||||||
data-event={`${eventCounts['*']}`}
|
data-event={`${eventCounts['*']}`}
|
||||||
@ -194,10 +182,22 @@ const Toolbar = () => {
|
|||||||
.map((domain) => domain.id)
|
.map((domain) => domain.id)
|
||||||
.join(', ')}
|
.join(', ')}
|
||||||
>
|
>
|
||||||
{first_sentence_history}
|
{first_sentence_cookie}
|
||||||
<strong>{cookieDomainCopy}</strong>
|
<strong>{cookieDomainCopy}</strong>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
{exposedOriginDomainCopy ? (
|
||||||
|
<p
|
||||||
|
data-event={`${eventCounts['*']}`}
|
||||||
|
title={Object.values(getMemory().getClustersForOrigin(origin))
|
||||||
|
.filter((cluster) => cluster.exposesOrigin())
|
||||||
|
.map((domain) => domain.id)
|
||||||
|
.join(', ')}
|
||||||
|
>
|
||||||
|
{first_sentence_history}
|
||||||
|
<strong>{exposedOriginDomainCopy}</strong>
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{exposedOriginDomainCopy || cookieDomainCopy ? (
|
{exposedOriginDomainCopy || cookieDomainCopy ? (
|
||||||
|
@ -117,9 +117,10 @@ export default class ExtendedRequest {
|
|||||||
|
|
||||||
async cacheOrigin(): Promise<void> {
|
async cacheOrigin(): Promise<void> {
|
||||||
let url: string;
|
let url: string;
|
||||||
if (this.data.tabId && this.data.tabId >= 0) {
|
if (this.data.type === 'main_frame') {
|
||||||
const tab = await browser.tabs.get(this.data.tabId);
|
url = this.data.url;
|
||||||
url = tab.url;
|
} else if (this.data.originUrl) {
|
||||||
|
url = this.data.originUrl;
|
||||||
} else if (
|
} else if (
|
||||||
(this.data as any)?.frameAncestors &&
|
(this.data as any)?.frameAncestors &&
|
||||||
(this.data as any).frameAncestors[0] !== undefined
|
(this.data as any).frameAncestors[0] !== undefined
|
||||||
|
12
memory.ts
12
memory.ts
@ -3,7 +3,7 @@ import { getshorthost, makeThrottle } from './util';
|
|||||||
import { RequestCluster } from './request-cluster';
|
import { RequestCluster } from './request-cluster';
|
||||||
import { SaferEmitter } from './safer-emitter';
|
import { SaferEmitter } from './safer-emitter';
|
||||||
|
|
||||||
function setDomainsNumber(counter: number, tabId: number) {
|
function setDomainsCount(counter: number, tabId: number) {
|
||||||
browser.browserAction.setBadgeText({ text: counter < 0 ? '0' : counter.toString(), tabId });
|
browser.browserAction.setBadgeText({ text: counter < 0 ? '0' : counter.toString(), tabId });
|
||||||
browser.browserAction.setTitle({
|
browser.browserAction.setTitle({
|
||||||
title: 'Rentgen',
|
title: 'Rentgen',
|
||||||
@ -35,10 +35,12 @@ export default class Memory extends SaferEmitter {
|
|||||||
? browser.browserAction.setBadgeBackgroundColor({ color: '#ff726b' })
|
? browser.browserAction.setBadgeBackgroundColor({ color: '#ff726b' })
|
||||||
: browser.browserAction.setBadgeBackgroundColor({ color: '#ffb900' });
|
: browser.browserAction.setBadgeBackgroundColor({ color: '#ffb900' });
|
||||||
|
|
||||||
setDomainsNumber(
|
if (request.tabId >= 0) {
|
||||||
Object.values(this.getClustersForOrigin(request.origin)).length,
|
setDomainsCount(
|
||||||
request.tabId
|
Object.values(this.getClustersForOrigin(request.origin)).length,
|
||||||
);
|
request.tabId
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
1
package-lock.json
generated
1
package-lock.json
generated
@ -5,7 +5,6 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "rentgen",
|
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -182,4 +182,15 @@ export class RequestCluster extends SaferEmitter {
|
|||||||
entry.unmark();
|
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(', ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@ export class SaferEmitter extends EventEmitter {
|
|||||||
Reflect.apply(listener, this, args);
|
Reflect.apply(listener, this, args);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
debugger;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user