Working filtered HAR export
This commit is contained in:
parent
d750c6b22b
commit
59de744c2d
@ -1,6 +1,33 @@
|
||||
import { StolenDataEntry } from "./stolen-data-entry";
|
||||
import { getshorthost, parseCookie, Request } from "./util";
|
||||
|
||||
export type HAREntry = {
|
||||
pageref: string;
|
||||
startedDateTime: string;
|
||||
request: {
|
||||
bodySize: number;
|
||||
cookies: {}[];
|
||||
headers: {}[];
|
||||
headersSize: number;
|
||||
httpVersion: string;
|
||||
method: string;
|
||||
postData: {
|
||||
mimeType: string;
|
||||
params: { name: string; value: string }[];
|
||||
text: string;
|
||||
};
|
||||
queryString: { name: string; value: string }[];
|
||||
url: string;
|
||||
};
|
||||
response: {}; // not relevant
|
||||
cache: {};
|
||||
timings: {};
|
||||
time: number;
|
||||
_securityState: string;
|
||||
serverIPAddress: string;
|
||||
connection: string;
|
||||
};
|
||||
|
||||
const whitelisted_cookies = [
|
||||
/^Accept.*$/,
|
||||
/^Host$/,
|
||||
@ -163,4 +190,10 @@ export default class ExtendedRequest {
|
||||
getHost() {
|
||||
return new URL(this.url).host;
|
||||
}
|
||||
|
||||
matchesHAREntry(har: HAREntry): boolean {
|
||||
const rq = this.data;
|
||||
const hrq = har.request;
|
||||
return rq.url == hrq.url;
|
||||
}
|
||||
}
|
||||
|
48
report-window/domain-summary.tsx
Normal file
48
report-window/domain-summary.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import { RequestCluster } from "../request-cluster";
|
||||
import { Classifications, Sources } from "../stolen-data-entry";
|
||||
|
||||
const emailClassifications: Record<keyof typeof Classifications, string> = {
|
||||
id: "sztucznie nadane mi ID",
|
||||
history: "część mojej historii przeglądania",
|
||||
};
|
||||
|
||||
const emailSources: Record<Sources, string> = {
|
||||
header: "w nagłówku HTTP",
|
||||
cookie: "z pliku Cookie",
|
||||
pathname: "jako części adresu URL",
|
||||
queryparams: "jako część adresu URL (query-params)",
|
||||
};
|
||||
|
||||
export default function DomainSummary({
|
||||
cluster,
|
||||
}: {
|
||||
cluster: RequestCluster;
|
||||
}) {
|
||||
return (
|
||||
<li>
|
||||
Właściciel domeny <strong>{cluster.id}</strong> otrzymał:{" "}
|
||||
<ul>
|
||||
{cluster
|
||||
.getMarkedEntries()
|
||||
.sort((entryA, entryB) => (entryA.value > entryB.value ? -1 : 1))
|
||||
.reduce((acc, entry, index, arr) => {
|
||||
if (index === 0) {
|
||||
return [entry];
|
||||
}
|
||||
if (entry.value != arr[index - 1].value) {
|
||||
acc.push(entry);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.map((entry) => (
|
||||
<li>
|
||||
{emailClassifications[entry.classification]}{" "}
|
||||
{emailSources[entry.source]}
|
||||
(<code>{entry.name.trim()}</code>)
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
}
|
121
report-window/email-template.tsx
Normal file
121
report-window/email-template.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
import React, { useState } from "react";
|
||||
import { RequestCluster } from "../request-cluster";
|
||||
import { StolenDataEntry } from "../stolen-data-entry";
|
||||
import { getDate } from "../util";
|
||||
import DomainSummary from "./domain-summary";
|
||||
|
||||
type PopupState = "not_clicked" | "clicked_but_invalid";
|
||||
|
||||
export default function EmailTemplate({
|
||||
marked_entries,
|
||||
clusters,
|
||||
}: {
|
||||
marked_entries: StolenDataEntry[];
|
||||
clusters: Record<string, RequestCluster>;
|
||||
}): JSX.Element {
|
||||
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label htmlFor="popupState">Status okienka o rodo:</label>
|
||||
<select
|
||||
id="popupState"
|
||||
value={popupState}
|
||||
onChange={(e) => setPopupState(e.target.value as PopupState)}
|
||||
>
|
||||
<option value="not_clicked">Nic nie kliknięte</option>
|
||||
<option value="clicked_but_invalid">Kliknięte, ale nieważne</option>
|
||||
</select>
|
||||
<p>
|
||||
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
|
||||
{marked_entries[0].request.originalURL}. Strona ta wysłała moje dane
|
||||
osobowe do podmiotów trzecich - bez mojej zgody.{" "}
|
||||
</p>
|
||||
<ul>
|
||||
{Object.values(clusters)
|
||||
.filter((cluster) => cluster.hasMarks())
|
||||
.map((cluster) => (
|
||||
<DomainSummary cluster={cluster} />
|
||||
))}
|
||||
</ul>
|
||||
{popupState === "not_clicked" ? (
|
||||
<p>
|
||||
Dane te zostały wysłane przez Państwa stronę zanim zdążyłem w ogóle
|
||||
przeczytać treść wyskakującego okienka ze zgodami.
|
||||
</p>
|
||||
) : null}
|
||||
<p>
|
||||
Nie widzę zatem przesłanki legalizującej takie przetwarzanie moich
|
||||
danych osobowych (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,
|
||||
<strong> dla każdego z celów i podmiotów z osobna</strong>.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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 sztucznie nadanego ID w
|
||||
plikach Cookies lub historii przeglądania w nagłówku Referer do
|
||||
wskazanych podmiotów trzecich.
|
||||
</p>
|
||||
<p>
|
||||
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 <strong>konkretny interes</strong> (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.
|
||||
</p>
|
||||
<p>
|
||||
Niniejszym zwracam się także z żądaniem wycofania przesłanych przez
|
||||
Państwa stronę moich danych osobowych z baz wyżej wymienionych podmiotów
|
||||
oraz przesłania potwierdzenia uwiarygadniającego pomyślne wycofanie tych
|
||||
danych. Proszę też o przesłanie 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.
|
||||
</p>
|
||||
<p>
|
||||
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych do
|
||||
wyżej wymienionych podmiotów.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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{" "}
|
||||
<a href="https://developer.mozilla.org/pl/docs/Web/HTTP/Headers/Referrer-Policy">
|
||||
Referrer-Policy{" "}
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
53
report-window/har-converter.tsx
Normal file
53
report-window/har-converter.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React, { useState } from "react";
|
||||
import { HAREntry } from "../extended-request";
|
||||
import { StolenDataEntry } from "../stolen-data-entry";
|
||||
|
||||
function handleNewFile(
|
||||
element: HTMLInputElement,
|
||||
marked_entries: StolenDataEntry[],
|
||||
setFiltered: (Blob) => void
|
||||
) {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", () => {
|
||||
const content = JSON.parse(reader.result as string);
|
||||
content.log.entries = content.log.entries.filter((har_entry: HAREntry) =>
|
||||
marked_entries.some((stolen_entry) =>
|
||||
stolen_entry.matchesHAREntry(har_entry)
|
||||
)
|
||||
);
|
||||
setFiltered(
|
||||
new Blob([JSON.stringify(content)], { type: "application/json" })
|
||||
);
|
||||
});
|
||||
reader.readAsText(element.files[0]);
|
||||
}
|
||||
|
||||
export default function HARConverter({
|
||||
marked_entries,
|
||||
}: {
|
||||
marked_entries: StolenDataEntry[];
|
||||
}) {
|
||||
const [filtered, setFiltered] = useState<Blob | null>(null);
|
||||
const [filename, setFilename] = useState("");
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="file"
|
||||
accept=".har"
|
||||
onChange={(e) => {
|
||||
setFilename(e.target.files[0].name);
|
||||
handleNewFile(e.target, marked_entries, setFiltered);
|
||||
}}
|
||||
/>
|
||||
{(filtered && (
|
||||
<a
|
||||
href={URL.createObjectURL(filtered)}
|
||||
download={filename.replace(".har", "-filtered.har")}
|
||||
>
|
||||
Pobierz wyfiltrowany HAR
|
||||
</a>
|
||||
)) ||
|
||||
null}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,55 +1,10 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { getMemory } from "../memory";
|
||||
import { RequestCluster } from "../request-cluster";
|
||||
import { Classifications, Sources } from "../stolen-data-entry";
|
||||
import { getDate } from "../util";
|
||||
|
||||
const emailClassifications: Record<keyof typeof Classifications, string> = {
|
||||
id: "sztucznie nadane mi ID",
|
||||
history: "część mojej historii przeglądania",
|
||||
};
|
||||
|
||||
const emailSources: Record<Sources, string> = {
|
||||
header: "w nagłówku HTTP",
|
||||
cookie: "z pliku Cookie",
|
||||
pathname: "jako części adresu URL",
|
||||
queryparams: "jako część adresu URL (query-params)",
|
||||
};
|
||||
|
||||
type PopupState = "not_clicked" | "clicked_but_invalid";
|
||||
|
||||
function DomainSummary({ cluster }: { cluster: RequestCluster }) {
|
||||
return (
|
||||
<li>
|
||||
Właściciel domeny <strong>{cluster.id}</strong> otrzymał:{" "}
|
||||
<ul>
|
||||
{cluster
|
||||
.getMarkedEntries()
|
||||
.sort((entryA, entryB) => (entryA.value > entryB.value ? -1 : 1))
|
||||
.reduce((acc, entry, index, arr) => {
|
||||
if (index === 0) {
|
||||
return [entry];
|
||||
}
|
||||
if (entry.value != arr[index - 1].value) {
|
||||
acc.push(entry);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.map((entry) => (
|
||||
<li>
|
||||
{emailClassifications[entry.classification]}{" "}
|
||||
{emailSources[entry.source]}
|
||||
(<code>{entry.name.trim()}</code>)
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
import EmailTemplate from "./email-template";
|
||||
import HARConverter from "./har-converter";
|
||||
|
||||
function Report() {
|
||||
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
|
||||
const origin = new URL(document.location.toString()).searchParams.get(
|
||||
"origin"
|
||||
);
|
||||
@ -111,108 +66,8 @@ function Report() {
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<label htmlFor="popupState">Status okienka o rodo:</label>
|
||||
<select
|
||||
id="popupState"
|
||||
value={popupState}
|
||||
onChange={(e) => setPopupState(e.target.value as PopupState)}
|
||||
>
|
||||
<option value="not_clicked">Nic nie kliknięte</option>
|
||||
<option value="clicked_but_invalid">Kliknięte, ale nieważne</option>
|
||||
</select>
|
||||
<div>
|
||||
<p>
|
||||
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
|
||||
{marked_entries[0].request.originalURL}. Strona ta wysłała moje dane
|
||||
osobowe do podmiotów trzecich - bez mojej zgody.{" "}
|
||||
</p>
|
||||
<ul>
|
||||
{Object.values(clusters)
|
||||
.filter((cluster) => cluster.hasMarks())
|
||||
.map((cluster) => (
|
||||
<DomainSummary cluster={cluster} />
|
||||
))}
|
||||
</ul>
|
||||
{popupState === "not_clicked" ? (
|
||||
<p>
|
||||
Dane te zostały wysłane przez Państwa stronę zanim zdążyłem w ogóle
|
||||
przeczytać treść wyskakującego okienka ze zgodami.
|
||||
</p>
|
||||
) : null}
|
||||
<p>
|
||||
Nie widzę zatem przesłanki legalizującej takie przetwarzanie moich
|
||||
danych osobowych (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,
|
||||
<strong> dla każdego z celów i podmiotów z osobna</strong>.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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 sztucznie nadanego ID
|
||||
w plikach Cookies lub historii przeglądania w nagłówku Referer do
|
||||
wskazanych podmiotów trzecich.
|
||||
</p>
|
||||
<p>
|
||||
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 <strong>konkretny interes</strong> (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.
|
||||
</p>
|
||||
<p>
|
||||
Niniejszym zwracam się także z żądaniem wycofania przesłanych przez
|
||||
Państwa stronę moich danych osobowych z baz wyżej wymienionych
|
||||
podmiotów oraz przesłania potwierdzenia uwiarygadniającego pomyślne
|
||||
wycofanie tych danych. Proszę też o przesłanie 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.
|
||||
</p>
|
||||
<p>
|
||||
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych
|
||||
do wyżej wymienionych podmiotów.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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{" "}
|
||||
<a href="https://developer.mozilla.org/pl/docs/Web/HTTP/Headers/Referrer-Policy">
|
||||
Referrer-Policy{" "}
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
<EmailTemplate {...{ marked_entries, clusters }} />
|
||||
<HARConverter {...{ marked_entries }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TCModel } from "@iabtcf/core";
|
||||
import ExtendedRequest from "./extended-request";
|
||||
import ExtendedRequest, { HAREntry } from "./extended-request";
|
||||
import { getMemory } from "./memory";
|
||||
import {
|
||||
getshorthost,
|
||||
@ -142,7 +142,6 @@ export class StolenDataEntry {
|
||||
} else {
|
||||
result = "id";
|
||||
}
|
||||
console.log("classifying", this.value, result, this.request.origin);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -151,6 +150,10 @@ export class StolenDataEntry {
|
||||
(entry) => (entry.classification = "id")
|
||||
);
|
||||
}
|
||||
|
||||
matchesHAREntry(har: HAREntry): boolean {
|
||||
return this.request.matchesHAREntry(har);
|
||||
}
|
||||
}
|
||||
|
||||
export class MergedStolenDataEntry {
|
||||
|
Loading…
Reference in New Issue
Block a user