TeamVis Self-Host-Bundle v0.56.2

This commit is contained in:
TeamVis Release committed 2026-10-10 23:39:23 +02:00
1 parent f53579d3a4
commit 6da3cc2283
11 files changed
+432 -30

No files matched your search

@@ -0,0 +1,103 @@
-- Karten-Analytics: Aufbewahrungsfrist und namentliche Auswertung
-- ====================================================================
-- Zwei Datenschutz-Lücken aus 0017 werden hier geschlossen:
--
-- 1. Die dort angekündigte Aufbewahrung von 365 Tagen war nur ein
-- Kommentar — es gab keine Löschroutine, die Protokolle wuchsen
-- unbegrenzt. Jetzt: konfigurierbare Frist (Default 90 Tage) plus
-- `purge_card_view_log()`, die der Anwendungscode regelmäßig ruft
-- und die zusätzlich per pg_cron laufen kann.
--
-- 2. Die namentliche Auswertung je Beschäftigtem (Rangliste unter
-- /admin/analytics) war ohne Schalter immer aktiv. Sie ist ab
-- jetzt ein bewusstes Opt-in, Default AUS — auch für
-- Bestandsinstanzen. Wo eine Belegschaft vertreten ist, ist die
-- Auswertung mitbestimmungspflichtig (technische Einrichtung,
-- geeignet zur Verhaltens- und Leistungskontrolle); sie darf
-- deshalb nicht stillschweigend voreingestellt sein.
alter table public.site_settings
add column if not exists analytics_employee_breakdown boolean not null default false,
add column if not exists analytics_retention_days integer not null default 90;
comment on column public.site_settings.analytics_employee_breakdown is
'Namentliche Auswertung der Kartenaufrufe je Beschäftigtem im Admin-Backend. Opt-in, mitbestimmungspflichtig.';
comment on column public.site_settings.analytics_retention_days is
'Aufbewahrungsfrist für card_view_log in Tagen. Ältere Zeilen werden gelöscht.';
-- Plausibilitätsgrenzen: mindestens eine Woche (sonst ist die Statistik
-- sinnlos), höchstens zwei Jahre (darüber ist die Erforderlichkeit für
-- eine reine Aufrufzählung nicht mehr begründbar).
alter table public.site_settings
drop constraint if exists site_settings_analytics_retention_days_check;
alter table public.site_settings
add constraint site_settings_analytics_retention_days_check
check (analytics_retention_days between 7 and 730);
-- --------------------------------------------------------------------
-- Löschroutine
-- --------------------------------------------------------------------
-- Ohne Argument gilt die in site_settings hinterlegte Frist. Rückgabe
-- ist die Anzahl gelöschter Zeilen, damit ein Cron-Lauf etwas zu
-- protokollieren hat.
create or replace function public.purge_card_view_log(retention_days integer default null)
returns integer
language plpgsql
security definer
set search_path = public
as $fn$
declare
days integer;
removed integer;
begin
days := coalesce(
retention_days,
(select s.analytics_retention_days from public.site_settings s where s.singleton limit 1),
90
);
delete from public.card_view_log
where occurred_at < now() - make_interval(days => days);
get diagnostics removed = row_count;
return removed;
end;
$fn$;
comment on function public.purge_card_view_log(integer) is
'Löscht Einträge aus card_view_log, die älter als die Aufbewahrungsfrist sind. Ohne Argument gilt site_settings.analytics_retention_days.';
-- Die Funktion fasst personenbeziehbare Protokolle an — kein Zugriff
-- für anon/authenticated.
revoke all on function public.purge_card_view_log(integer) from public;
revoke all on function public.purge_card_view_log(integer) from anon;
revoke all on function public.purge_card_view_log(integer) from authenticated;
grant execute on function public.purge_card_view_log(integer) to service_role;
-- --------------------------------------------------------------------
-- Zeitplan, sofern pg_cron vorhanden ist
-- --------------------------------------------------------------------
-- Die Anwendung löscht ohnehin selbst (siehe lib/analytics.ts), das hier
-- ist der saubere Weg für Instanzen mit pg_cron: die Frist greift dann
-- auch, wenn die Karten längere Zeit nicht aufgerufen werden. Fehlt die
-- Extension oder fehlen die Rechte, bleibt es beim App-seitigen Lauf —
-- die Migration darf daran nicht scheitern.
do $cron$
begin
if exists (select 1 from pg_extension where extname = 'pg_cron') then
begin
perform cron.unschedule('teamvis-purge-card-view-log');
exception when others then
null;
end;
perform cron.schedule(
'teamvis-purge-card-view-log',
'30 3 * * *',
'select public.purge_card_view_log();'
);
end if;
exception when others then
raise notice 'pg_cron-Zeitplan nicht eingerichtet (%). Die Anwendung löscht selbst.', sqlerrm;
end;
$cron$;