diff --git a/.prettierrc b/.prettierrc index c694529..3840076 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ trailingComma: "es5" tabWidth: 4 -printWidth: 80 +printWidth: 100 semi: true singleQuote: true diff --git a/esbuild.config.js b/esbuild.config.js index 6f66cfa..f22cd23 100644 --- a/esbuild.config.js +++ b/esbuild.config.js @@ -54,6 +54,10 @@ esbuild outdir: './lib', loader: { '.woff': 'file', '.woff2': 'file' }, plugins: [scss(), skipReactImports], + define: { + PLUGIN_NAME: '"Rentgen"', + PLUGIN_URL: '"https://git.internet-czas-dzialac.pl/icd/rentgen"', + }, external: ['react', 'react-dom'], watch, }) diff --git a/report-window/email-template-1.tsx b/report-window/email-template-1.tsx deleted file mode 100644 index 37ef15d..0000000 --- a/report-window/email-template-1.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import React from 'react'; -import { RequestCluster } from '../request-cluster'; -import { StolenDataEntry } from '../stolen-data-entry'; -import { getDate, toBase64 } from '../util'; -import DomainSummary from './domain-summary'; - -type PopupState = 'not_clicked' | 'clicked_but_no_reject_all'; - -export default function EmailTemplate1({ - entries, - clusters, -}: { - entries: StolenDataEntry[]; - clusters: Record; - version: number; -}): JSX.Element { - const [popupState, setPopupState] = - React.useState('not_clicked'); - const [acceptAllName, setAcceptAllName] = React.useState( - 'Zaakceptuj wszystkie' - ); - const [popupScreenshotBase64, setPopupScreenshotBase64] = - React.useState(null); - - return ( -
- - - {popupState === 'clicked_but_no_reject_all' ? ( - <> -
- - - setAcceptAllName(e.target.value), - }} - /> -
-
- - { - setPopupScreenshotBase64( - await toBase64(e.target.files[0]) - ); - }, - }} - /> -
- - ) : null} -

- Dzień dobry, w dniu {getDate()} odwiedziłem stronę{' '} - {entries[0].request.originalURL}. Strona ta wysłała moje dane - osobowe do podmiotów trzecich - bez mojej zgody.{' '} -

-
    - {Object.values(clusters) - .filter((cluster) => cluster.hasMarks()) - .map((cluster) => ( - - ))} -
-

- {' '} - Dane te zostały wysłane przez Państwa stronę - a mówiąc - dokładniej, przez zamieszczone przez Państwa na tej stronie - skrypty. -

- {popupState === 'not_clicked' ? ( -

- Nastąpiło to, zanim zdążyłem w ogóle przeczytać treść - wyskakującego okienka ze zgodami i zanim miałem szansę - wyrazić sprzeciw takiemu przetwarzaniu danych osobowych. -

- ) : null} - {popupState === 'clicked_but_no_reject_all' ? ( -

- O ile po wejściu na stronę wcisnąłem w wyskakującym okienku - przycisk „{acceptAllName}”, o tyle nie stanowi to według - mnie ważnej w świetle RODO zgody, gdyż brakowało w tym - okienku równie łatwo osiągalnego przycisku, którego - kliknięcie skutkowałoby zasygnalizowaniem braku mojej zgody - na takie przetwarzanie moich danych. Mówiąc wprost - - wyrażenie „zgody” było łatwiejsze niż jej niewyrażenie. - Niewyrażenie zgody wiąże się z negatywną konsekwencją - konieczności przechodzenia przez dodatkowe kroki w - wyskakującym okienku. Zatem tak otrzymana przez Państwo moja - „zgoda” nie jest poprawną podstawą prawną do przetwarzania - moich danych osobowych, gdyż nie spełnia warunku - dobrowolności wspomnianego w Art. 4. pkt 11{' '} - - rozporządzenia Parlamentu Europejskiego i Rady (UE) - 2016/679 z dnia 27 kwietnia 2016 r. w sprawie ochrony - osób fizycznych w związku z przetwarzaniem danych - osobowych i w sprawie swobodnego przepływu takich danych - oraz uchylenia dyrektywy 95/46/WE - - .{} -

- ) : null} -

- Udokumentowałem to na zrzutach ekranu z mojej przeglądarki - internetowej, które to zrzuty przesyłam w załączeniu. -

-

- Wiem, że nie wszystkie rodzaje przetwarzania danych wymagają - zgody użytkownika. W kontekście stron internetowych z - wymienionych w Art. 6. pkt 1. RODO mogą mieć zastosowanie albo - „zgoda” (Art. 6. pkt 1. lit. a)), albo niezbędność tego - przetwarzania do wykonania umowy (Art. 6. pkt 1. lit. b)), albo - uzasadniony interes (Art. 6. pkt 1. lit. f)). Wiem też, że każda - z tych podstaw prawnych ma moc dopiero po spełnieniu określonych - warunków. -

-

- Nie widzę ważnej podstawy prawnej legalizującej procesy - przetwarzania moich danych osobowych, jakie wymieniłem powyżej - (na pewno nie jest to przetwarzanie konieczne do wyświetlenia - strony z technicznego punktu widzenia). Jeżeli takie przesłanki - legalizujące jednak występują, proszę o ich wskazanie, - - {' '} - dla każdego z celów i podmiotów z osobna - - . -

-

- Jeżeli wskazaną przez Państwa przesłanką legalizującą dany - element procesu przetwarzania danych osobowych przez Państwa - stronę jest Art 6. pkt 1 lit. a) RODO (zgoda), na mocy Art. 7 - pkt 1 RODO proszę o wykazanie, że udzieliłem Państwu zgodę na - takie przetwarzanie moich danych osobowych zanim to - przetwarzanie nastąpiło, oraz że ta zgoda jest ważna w świetle - RODO (odnosząc się w szczególności do art. 7 ust. 3 RODO). Z - góry zaznaczam, że „ustawienia przeglądarki” nie stanowią ważnej - w świetle RODO zgody. -

-

- Jeżeli wskazaną przez Państwa przesłanką legalizującą dany - element procesu przetwarzania danych osobowych przez Państwa - stronę jest Art 6. pkt 1 lit. b) RODO (niezbędność takiego - przetwarzania do wykonania umowy), proszę o wskazanie, w jaki - sposób ta konieczność zachodzi, oraz co sprawia, że Państwa - zdaniem nie można wykonać umowy związanej z wyświetleniem - Państwa strony bez przekazywania identyfikatora internetowego z - plików Cookies lub historii przeglądania w nagłówku Referer do - wskazanych podmiotów trzecich. -

-

- Jeżeli wskazaną przez Państwa przesłanką legalizującą dany - element procesu przetwarzania danych osobowych przez Państwa - stronę jest Art 6. pkt 1 lit. f) RODO (uzasadniony interes), - proszę o wskazanie, jaki to jest{' '} - konkretny interes (prosze o bardziej dokładny - opis niż np. tylko "marketing"), oraz o wynik testu równowagi - pomiędzy Państwa interesem a moimi podstawowymi wolnościami i - prawami - ze wskazaniem tego, co sprawia, że w Państwa ocenie - Państwa uzasadniony interes przeważa moje prawa i interesy w - kontekście wspomnianych powyżej procesów przetwarzania danych. - Proszę też pamiętać, że aby w ramach danego celu przetwarzania - powołać się na prawnie uzasadniony interes, powinni mi Państo - umożliwić wyrażenie sprzeciwu wobec przetwarzania moich danych w - tym celu przed rozpoczęciem przetwarzania - zob.{' '} - - Wytyczne 8/2020 Europejskiej Rady Ochrony Danych dotyczące - targetowania użytkowników mediów społecznościowych - -

-

- Niniejszym zwracam się także z żądaniem ujawnienia tożsamości - podmiotów, które są właścicielami wyżej wymienionych domen, abym - mógł zapoznać się z ich politykami prywatności i zwrócić się do - tych podmiotów o usunięcie z ich baz wysłanych przez Państwa - stronę moich danych. -

-

- Proszę też o wysłanie kopii danych zebranych na mój temat i - wysłanych do wyżej wymienionych podmiotów. -

-

- W odpowiedzi proszę się nie powoływać na IAB Europe i ich - rzekomą renomę w tworzeniu rozwiązań zgodnych z RODO. IAB chroni - interes reklamodawców, a nie Użytkowników, i ich rozwiązania - (np. TCF) są{' '} - - notorycznie niezgodne z RODO i pozbawione szacunku dla - Użytkowników - - . -

-

- Apeluję także o wprowadzenie stosownych zmian na stronie tak, - aby nie pozostawiać cienia wątpliwości odnośnie tego, na mocy - jakiej przesłanki legalizującej dane są przetwarzane przez - wspomniane podmioty trzecie, lub tak, aby te dane po prostu nie - były wysyłane. Pomoże to zachować prywatność innym użytkownikom - Państwa strony. Polecam Państwa uwadze oficjalne wytyczne EROD - dotyczące zgody w kontekście RODO: - https://edpb.europa.eu/sites/default/files/files/file1/edpb_guidelines_202005_consent_pl.pdf - ). Aby na przykład zapobiec automatycznemu wysyłaniu historii - przeglądania do podmiotów trzecich przez Państwa stronę, można - po prostu ustawić odpowiednio treść nagłówka{' '} - - Referrer-Policy{' '} - - . -

-
- ); -} diff --git a/report-window/email-template-2-controls.tsx b/report-window/email-template-2-controls.tsx deleted file mode 100644 index db27b86..0000000 --- a/report-window/email-template-2-controls.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import React from 'react'; -import { toBase64 } from '../util'; -import { EmailTemplate2Config } from './email-template-2'; - -export default function EmailTemplate2Controls({ - config, - setConfig, -}: { - config: EmailTemplate2Config; - setConfig: React.Dispatch>; -}): JSX.Element { - return ( -
-
- - -
- {config.popup_type !== 'none' ? ( -
- - { - const popup_screenshot_base64 = await toBase64( - e.target.files[0] - ); - setConfig((v) => ({ - ...v, - popup_screenshot_base64, - })); - }, - }} - /> -
- ) : ( - '' - )} - {config.popup_type === 'consent' ? ( -
- - - setConfig((v) => ({ - ...v, - popup_accept_all_text: e.target.value, - })), - }} - /> -
- ) : ( - '' - )} -
- - -
- {config.popup_action === 'closed' ? ( -
- - - setConfig((v) => ({ - ...v, - popup_closed_how: e.target.value, - })) - } - /> -
- ) : ( - '' - )} - {config.popup_type !== 'none' ? ( -
- - setConfig((v) => ({ - ...v, - popup_mentions_passive_consent: - e.target.checked, - })) - } - /> - -
- ) : ( - '' - )} - {config.popup_mentions_passive_consent ? ( -
- - - setConfig((v) => ({ - ...v, - popup_passive_consent_text: e.target.value, - })) - } - /> -
- ) : ( - '' - )} -
- ); -} diff --git a/report-window/email-template-3-controls.tsx b/report-window/email-template-3-controls.tsx new file mode 100644 index 0000000..e7fd579 --- /dev/null +++ b/report-window/email-template-3-controls.tsx @@ -0,0 +1,310 @@ +import React from 'react'; +import { toBase64 } from '../util'; +import { EmailTemplate3Config } from './email-template-3'; + +function setHostSetting< + P1 extends keyof EmailTemplate3Config['hosts_settings'], + P2 extends keyof EmailTemplate3Config['hosts_settings'][P1] +>( + setConfig: React.Dispatch>, + [p1, p2]: [P1, P2], + value: EmailTemplate3Config['hosts_settings'][P1][P2] +) { + setConfig((v) => { + console.log(v, { + ...v, + hosts_settings: { + ...v.hosts_settings, + [p1]: { + ...v.hosts_settings[p2], + [p2]: value, + }, + }, + }); + return { + ...v, + hosts_settings: { + ...v.hosts_settings, + [p1]: { + ...v.hosts_settings[p1], + [p2]: value, + }, + }, + }; + }); +} + +export default function EmailTemplate3Controls({ + config, + setConfig, +}: { + config: EmailTemplate3Config; + setConfig: React.Dispatch>; +}): JSX.Element { + const p = config.pronoun; + return ( +
+
+ + +
+ +
+ + +
+ {config.policy_readable !== 'null' ? ( +
+ {Object.entries(config.hosts_settings).map(([id, settings]) => ( +
+
{id}
+

+ Cele przetwarzania danych przez właściciela domeny {id}{' '} + +

+ {!['not_mentioned', 'null'].includes(settings.presence) ? ( +

+ Wskazana przez administratora podstawa prawna dla{' '} + tego konkretnego celu{' '} + +

+ ) : ( + '' + )} + {!['not_mentioned', 'null'].includes(settings.legal_basis_type) ? ( +
dodatkowe pytania
+ ) : ( + '' + )} +
+ ))} +
+ ) : ( + '' + )} +
+ + +
+ {config.popup_type !== 'none' ? ( +
+ + { + const popup_screenshot_base64 = await toBase64(e.target.files[0]); + setConfig((v) => ({ + ...v, + popup_screenshot_base64, + })); + }, + }} + /> +
+ ) : ( + '' + )} + {config.popup_type === 'consent' ? ( +
+ + + setConfig((v) => ({ + ...v, + popup_accept_all_text: e.target.value, + })), + }} + /> +
+ ) : ( + '' + )} +
+ + +
+ {config.popup_action === 'closed' ? ( +
+ + + setConfig((v) => ({ + ...v, + popup_closed_how: e.target.value, + })) + } + /> +
+ ) : ( + '' + )} + {config.popup_type !== 'none' ? ( +
+ + setConfig((v) => ({ + ...v, + popup_mentions_passive_consent: e.target.checked, + })) + } + /> + +
+ ) : ( + '' + )} + {config.popup_mentions_passive_consent ? ( +
+ + + setConfig((v) => ({ + ...v, + popup_passive_consent_text: e.target.value, + })) + } + /> +
+ ) : ( + '' + )} +
+ ); +} diff --git a/report-window/email-template-3.tsx b/report-window/email-template-3.tsx new file mode 100644 index 0000000..f8b703d --- /dev/null +++ b/report-window/email-template-3.tsx @@ -0,0 +1,147 @@ +import React from 'react'; +import { RequestCluster } from '../request-cluster'; +import { StolenDataEntry } from '../stolen-data-entry'; +import { getDate } from '../util'; +import EmailTemplate3Controls from './email-template-3-controls'; + +declare var PLUGIN_NAME: string; +declare var PLUGIN_URL: string; + +export type EmailTemplate3Config = { + pronoun: 0 | 1 | 2 | 3; // masc, fem, neutral, plural + policy_readable: 'null' | 'yes' | 'entirely_obscured_by_popup' | 'cant_find'; + hosts_settings: Record< + string, + { + presence: 'null' | 'not_mentioned' | 'mentioned_in_popup' | 'mentioned_in_policy'; + legal_basis_type: 'null' | 'consent' | 'legitimate_interest' | 'not_mentioned'; + problems: { + claims_consent_but_sends_before_consent: boolean; + claims_consent_but_there_was_no_easy_refuse: boolean; + claims_legitimate_interest_but_its_not_legitimate: boolean; + }; + } + >; + popup_type: 'none' | 'passive_cookie_banner' | 'consent'; + popup_action: 'ignored' | 'accepted' | 'closed'; + popup_closed_how: string; + popup_screenshot_base64: string | null; + popup_accept_all_text: string; + popup_mentions_passive_consent: boolean; + popup_passive_consent_text: string; +}; + +export default function EmailTemplate3({ + entries, + clusters, +}: { + entries: StolenDataEntry[]; + clusters: Record; + version: number; +}): JSX.Element { + const all_host_ids = Array.from(new Set(entries.map((entry) => entry.request.shorthost))); + + const [config, setConfig] = React.useState({ + pronoun: Math.round(Math.random()) as 0 | 1, + policy_readable: 'null', + hosts_settings: Object.fromEntries( + all_host_ids.map((cluster_id) => [ + cluster_id, + { + presence: 'null', + legal_basis_presence: 'null', + legal_basis_type: 'null', + problems: { + claims_consent_but_sends_before_consent: false, + claims_consent_but_there_was_no_easy_refuse: false, + claims_legitimate_interest_but_its_not_legitimate: false, + }, + }, + ]) + ), + popup_type: 'none', + popup_action: 'ignored', + popup_screenshot_base64: null, + popup_accept_all_text: 'Zaakceptuj wszystkie', + popup_mentions_passive_consent: false, + popup_passive_consent_text: '', + popup_closed_how: 'kliknięcie przycisku „X”', + }); + + const visited_url = entries[0].request.originalURL; + + const p = config.pronoun; + + return ( +
+
+ +
+
+

+ Dzień dobry, w dniu {getDate()}{' '} + {['odwiedziłem', 'odwiedziłam', 'odwiedziłom', 'odwiedziliśmy'][p]} stronę{' '} + {visited_url} i {['zbadałem', 'zbadałam', 'zbadałom', 'zbadaliśmy'][p]} ją za + pomocą wtyczki {PLUGIN_NAME} w celu zbadania, jakie + informacje o {['mnie', 'mnie', 'mnie', 'nas'][p]} wysyła ta strona do podmiotów + trzecich. +

+

+ {['Moją', 'Moją', 'Moją', 'Naszą'][p]} szczególną uwagę przykuło: WYFILTROWANE + WZGLĘDEM TEGO, CZY DANEGO PODMIOTU NIE MA W POLITYCE PRYWATNOŚCI LUB + POWIADOMIENIU O COOKIESACH{' '} +

    +
  • + - wysyłanie mojego identyfikatora internetowego [z Cookie] (value) oraz + części mojej historii przeglądania do właściciela domeny (domain); +
  • +
  • - (...).
  • +
+

+

+ Dane te zostały wysłane zanim {['miałem', 'miałam', 'miałom', 'mieliśmy'][p]}{' '} + szansę przeczytać Państwa politykę prywatności i w jakikolwiek czynny i + jednoznaczny sposób wyrazić zgodę na takie przetwarzanie moich danych osobowych. +

+ {config.policy_readable !== 'yes' ? ( +

+ {['Chciałem', 'Chciałam', 'Chciałom', 'Chcieliśmy'][p]} przeczytać Państwa + politykę prywatności przed akceptacją, ale{' '} + {config.policy_readable == 'cant_find' ? ( + <>nie mogę znaleźć jej nigdzie na Państwa stronie. + ) : ( + '' + )}{' '} + {config.policy_readable == 'entirely_obscured_by_popup' ? ( + <>jest ona przesłonięta przez okienko o RODO. + ) : ( + '' + )} +

+ ) : ( + '' + )} +

+ Dane zostały udostępnione podmiotom, o których nie{' '} + {['znalazłem', 'znalazłam', 'znalazłom', 'znaleźliśmy'][p]} informacji ani w + Państwa polityce prywatności, ani w żadnym wyskakującym okienku na Państwa + stronie. Z tego powodu zwracam{p == 3 ? 'y' : ''} się do Państwa z pytaniem: + jakie były podstawy prawne takiego ujawnienia{' '} + {['moich', 'moich', 'moich', 'naszych'][p]} danych osobowych wyżej wymienionym + podmiotom? Uprzejmie + {['proszę', 'proszę', 'proszę', 'prosimy'][p]} o wskazanie podstawy prawnej dla + każdego z tych podmiotów z osobna. +

+
+
+ ); +} diff --git a/report-window/email-template.tsx b/report-window/email-template.tsx index 4bb6580..ac8f656 100644 --- a/report-window/email-template.tsx +++ b/report-window/email-template.tsx @@ -1,8 +1,6 @@ -import React from 'react'; import { RequestCluster } from '../request-cluster'; import { StolenDataEntry } from '../stolen-data-entry'; -import EmailTemplate1 from './email-template-1'; -import EmailTemplate2 from './email-template-2'; +import EmailTemplate3 from './email-template-3'; export default function EmailTemplate({ entries, @@ -13,21 +11,9 @@ export default function EmailTemplate({ clusters: Record; version: number; }) { - const [templateVersion, setTemplateVersion] = React.useState('2'); return (
- - {templateVersion === '1' ? ( - - ) : ( - - )} +
); } diff --git a/report-window/report-window.html b/report-window/report-window.html index 098ce50..145c9ec 100644 --- a/report-window/report-window.html +++ b/report-window/report-window.html @@ -9,14 +9,16 @@
+ + - \ No newline at end of file + diff --git a/report-window/report-window.tsx b/report-window/report-window.tsx index 24c910a..2ce0ef4 100644 --- a/report-window/report-window.tsx +++ b/report-window/report-window.tsx @@ -80,44 +80,39 @@ function DataPreview({ } function Report() { - console.time('getOrigin'); - const origin = new URL(document.location.toString()).searchParams.get( - 'origin' - ); - console.timeEnd('getOrigin'); - console.time('useMemory'); - const [counter, setCounter] = useEmitter(getMemory()); - console.timeEnd('useMemory'); - console.time('getClustersForOrigin'); - const clusters = getMemory().getClustersForOrigin(origin); - console.timeEnd('getClustersForOrigin'); - const [entries, setEntries] = React.useState([]); - console.time('useEffect report-window'); - React.useEffect(() => { - setEntries( - Object.values(clusters) - .map((cluster) => { - cluster.calculateRepresentativeStolenData(); - return cluster.representativeStolenData; - }) - .reduce(reduceConcat, []) - .filter((entry) => entry.isMarked) + try { + const origin = new URL(document.location.toString()).searchParams.get( + 'origin' ); - }, []); - console.timeEnd('useEffect report-window'); - if (entries.length == 0) { - return <>Wczytywanie...; + const [counter, setCounter] = useEmitter(getMemory()); + const clusters = getMemory().getClustersForOrigin(origin); + const [entries, setEntries] = React.useState([]); + React.useEffect(() => { + setEntries( + Object.values(clusters) + .map((cluster) => { + cluster.calculateRepresentativeStolenData(); + return cluster.representativeStolenData; + }) + .reduce(reduceConcat, []) + .filter((entry) => entry.isMarked) + ); + }, []); + if (entries.length == 0) { + return <>Wczytywanie...; + } + const result = ( +
+

Generuj treść maila dla {origin}

+ + {/* */} +
+ ); + return result; + } catch (e) { + console.error(e); + return
ERRO! {JSON.stringify(e)}
; } - console.time('rendering template'); - const result = ( -
-

Generuj treść maila dla {origin}

- - -
- ); - console.timeEnd('rendering template'); - return result; } ReactDOM.render(, document.getElementById('app'));