deutsche Zeit statt UTC

Dieser Commit ist enthalten in:
2025-06-08 20:21:58 +02:00
Ursprung f9e5823eeb
Commit f269082115
19 geänderte Dateien mit 1411 neuen und 31 gelöschten Zeilen

Datei anzeigen

@@ -48,7 +48,8 @@
"Bash(find:*)",
"Bash(openssl x509:*)",
"Bash(cat:*)",
"Bash(openssl dhparam:*)"
"Bash(openssl dhparam:*)",
"Bash(rg:*)"
],
"deny": []
}

Datei anzeigen

@@ -1211,3 +1211,84 @@ Die Session-Daten werden erst gefüllt, wenn der License Server API implementier
- ✅ CAPTCHA wird nur angezeigt wenn Keys konfiguriert sind
- ✅ Für PoC-Phase ohne CAPTCHA nutzbar
- ✅ Produktiv-ready wenn CAPTCHA-Keys eingetragen werden
### 2025-06-08: Zeitzone auf Europe/Berlin umgestellt
**Problem:**
- Alle Zeitstempel wurden in UTC gespeichert und angezeigt
- Backup-Dateinamen zeigten UTC-Zeit statt deutsche Zeit
- Verwirrung bei Zeitangaben im Admin Panel und Logs
**Lösung:**
1. **Docker Container Zeitzone konfiguriert:**
- Alle Dockerfiles mit `TZ=Europe/Berlin` und tzdata Installation
- PostgreSQL mit `PGTZ=Europe/Berlin` für Datenbank-Zeitzone
- Explizite Zeitzone-Dateien in /etc/localtime und /etc/timezone
2. **Python Code angepasst:**
- Import von `zoneinfo.ZoneInfo` für Zeitzonenunterstützung
- Alle `datetime.now()` Aufrufe mit `ZoneInfo("Europe/Berlin")`
- `.replace(tzinfo=None)` für Kompatibilität mit timezone-unaware Timestamps
3. **PostgreSQL Konfiguration:**
- `SET timezone = 'Europe/Berlin';` in init.sql
- Umgebungsvariablen TZ und PGTZ in docker-compose.yaml
4. **docker-compose.yaml erweitert:**
- `TZ: Europe/Berlin` für alle Services
**Geänderte Dateien:**
- `v2_adminpanel/Dockerfile`: Zeitzone und tzdata hinzugefügt
- `v2_postgres/Dockerfile`: Zeitzone und tzdata hinzugefügt
- `v2_nginx/Dockerfile`: Zeitzone und tzdata hinzugefügt
- `v2_lizenzserver/Dockerfile`: Zeitzone und tzdata hinzugefügt
- `v2_adminpanel/app.py`: 14 datetime.now() Aufrufe mit Zeitzone versehen
- `v2_adminpanel/init.sql`: PostgreSQL Zeitzone gesetzt
- `v2/docker-compose.yaml`: TZ Environment-Variable für alle Services
**Ergebnis:**
- ✅ Alle neuen Zeitstempel werden in deutscher Zeit (Europe/Berlin) gespeichert
- ✅ Backup-Dateinamen zeigen korrekte deutsche Zeit
- ✅ Admin Panel zeigt alle Zeiten in deutscher Zeitzone
- ✅ Automatische Anpassung bei Sommer-/Winterzeit
- ✅ Konsistente Zeitangaben über alle Komponenten
**Hinweis:** Nach diesen Änderungen müssen die Docker Container neu gebaut werden:
```bash
docker-compose down
docker-compose build
docker-compose up -d
```
### 2025-06-08: Zeitzone-Fix - PostgreSQL Timestamps
**Problem nach erster Implementierung:**
- Trotz Zeitzoneneinstellung wurden Zeiten immer noch in UTC angezeigt
- Grund: PostgreSQL Tabellen verwendeten `TIMESTAMP WITHOUT TIME ZONE`
**Zusätzliche Lösung:**
1. **Datenbankschema angepasst:**
- Alle `TIMESTAMP` Spalten auf `TIMESTAMP WITH TIME ZONE` geändert
- Betrifft: created_at, timestamp, started_at, ended_at, last_heartbeat, etc.
- Migration für bestehende Datenbanken berücksichtigt
2. **SQL-Abfragen vereinfacht:**
- `AT TIME ZONE 'Europe/Berlin'` nicht mehr nötig
- PostgreSQL handhabt Zeitzonenkonvertierung automatisch
**Geänderte Datei:**
- `v2_adminpanel/init.sql`: Alle TIMESTAMP Felder mit WITH TIME ZONE
**Wichtig:** Bei bestehenden Installationen muss die Datenbank neu initialisiert oder manuell migriert werden:
```sql
ALTER TABLE customers ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE licenses ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE sessions ALTER COLUMN started_at TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE sessions ALTER COLUMN last_heartbeat TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE sessions ALTER COLUMN ended_at TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE audit_log ALTER COLUMN timestamp TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE backup_history ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE login_attempts ALTER COLUMN first_attempt TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE login_attempts ALTER COLUMN last_attempt TYPE TIMESTAMP WITH TIME ZONE;
ALTER TABLE login_attempts ALTER COLUMN blocked_until TYPE TIMESTAMP WITH TIME ZONE;
```

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@@ -0,0 +1,624 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 14.18 (Debian 14.18-1.pgdg120+1)
-- Dumped by pg_dump version 14.18 (Debian 14.18-1.pgdg120+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
SET default_tablespace = '';
SET default_table_access_method = heap;
--
-- Name: audit_log; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.audit_log (
id integer NOT NULL,
"timestamp" timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
username text NOT NULL,
action text NOT NULL,
entity_type text NOT NULL,
entity_id integer,
old_values jsonb,
new_values jsonb,
ip_address text,
user_agent text,
additional_info text
);
ALTER TABLE public.audit_log OWNER TO adminuser;
--
-- Name: audit_log_id_seq; Type: SEQUENCE; Schema: public; Owner: adminuser
--
CREATE SEQUENCE public.audit_log_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.audit_log_id_seq OWNER TO adminuser;
--
-- Name: audit_log_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: adminuser
--
ALTER SEQUENCE public.audit_log_id_seq OWNED BY public.audit_log.id;
--
-- Name: backup_history; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.backup_history (
id integer NOT NULL,
filename text NOT NULL,
filepath text NOT NULL,
filesize bigint,
backup_type text NOT NULL,
status text NOT NULL,
error_message text,
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
created_by text NOT NULL,
tables_count integer,
records_count integer,
duration_seconds numeric,
is_encrypted boolean DEFAULT true
);
ALTER TABLE public.backup_history OWNER TO adminuser;
--
-- Name: backup_history_id_seq; Type: SEQUENCE; Schema: public; Owner: adminuser
--
CREATE SEQUENCE public.backup_history_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.backup_history_id_seq OWNER TO adminuser;
--
-- Name: backup_history_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: adminuser
--
ALTER SEQUENCE public.backup_history_id_seq OWNED BY public.backup_history.id;
--
-- Name: customers; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.customers (
id integer NOT NULL,
name text NOT NULL,
email text,
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE public.customers OWNER TO adminuser;
--
-- Name: customers_id_seq; Type: SEQUENCE; Schema: public; Owner: adminuser
--
CREATE SEQUENCE public.customers_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.customers_id_seq OWNER TO adminuser;
--
-- Name: customers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: adminuser
--
ALTER SEQUENCE public.customers_id_seq OWNED BY public.customers.id;
--
-- Name: licenses; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.licenses (
id integer NOT NULL,
license_key text NOT NULL,
customer_id integer,
license_type text NOT NULL,
valid_from date NOT NULL,
valid_until date NOT NULL,
is_active boolean DEFAULT true
);
ALTER TABLE public.licenses OWNER TO adminuser;
--
-- Name: licenses_id_seq; Type: SEQUENCE; Schema: public; Owner: adminuser
--
CREATE SEQUENCE public.licenses_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.licenses_id_seq OWNER TO adminuser;
--
-- Name: licenses_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: adminuser
--
ALTER SEQUENCE public.licenses_id_seq OWNED BY public.licenses.id;
--
-- Name: login_attempts; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.login_attempts (
ip_address character varying(45) NOT NULL,
attempt_count integer DEFAULT 0,
first_attempt timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
last_attempt timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
blocked_until timestamp without time zone,
last_username_tried text,
last_error_message text
);
ALTER TABLE public.login_attempts OWNER TO adminuser;
--
-- Name: sessions; Type: TABLE; Schema: public; Owner: adminuser
--
CREATE TABLE public.sessions (
id integer NOT NULL,
license_id integer,
session_id text NOT NULL,
ip_address text,
user_agent text,
started_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
last_heartbeat timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
ended_at timestamp without time zone,
is_active boolean DEFAULT true
);
ALTER TABLE public.sessions OWNER TO adminuser;
--
-- Name: sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: adminuser
--
CREATE SEQUENCE public.sessions_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.sessions_id_seq OWNER TO adminuser;
--
-- Name: sessions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: adminuser
--
ALTER SEQUENCE public.sessions_id_seq OWNED BY public.sessions.id;
--
-- Name: audit_log id; Type: DEFAULT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.audit_log ALTER COLUMN id SET DEFAULT nextval('public.audit_log_id_seq'::regclass);
--
-- Name: backup_history id; Type: DEFAULT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.backup_history ALTER COLUMN id SET DEFAULT nextval('public.backup_history_id_seq'::regclass);
--
-- Name: customers id; Type: DEFAULT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.customers ALTER COLUMN id SET DEFAULT nextval('public.customers_id_seq'::regclass);
--
-- Name: licenses id; Type: DEFAULT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.licenses ALTER COLUMN id SET DEFAULT nextval('public.licenses_id_seq'::regclass);
--
-- Name: sessions id; Type: DEFAULT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.sessions ALTER COLUMN id SET DEFAULT nextval('public.sessions_id_seq'::regclass);
--
-- Data for Name: audit_log; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.audit_log (id, "timestamp", username, action, entity_type, entity_id, old_values, new_values, ip_address, user_agent, additional_info) FROM stdin;
1 2025-06-07 14:40:45.833151 rac00n LOGIN user \N \N \N 172.19.0.1 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
2 2025-06-07 14:41:11.190149 rac00n LOGOUT user \N \N \N 172.19.0.1 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
3 2025-06-07 14:41:17.105596 rac00n LOGIN user \N \N \N 172.19.0.1 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
4 2025-06-07 15:15:06.256545 rac00n LOGIN user \N \N \N 172.19.0.1 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
5 2025-06-07 15:15:33.972469 rac00n LOGIN user \N \N \N 172.19.0.1 curl/8.5.0 Erfolgreiche Anmeldung
6 2025-06-07 15:15:34.109986 rac00n BACKUP database 1 \N \N 172.19.0.1 curl/8.5.0 Backup erstellt: backup_v2docker_20250607_151534_encrypted.sql.gz.enc (3640 bytes)
7 2025-06-07 15:15:43.824357 rac00n LOGIN user \N \N \N 172.19.0.1 curl/8.5.0 Erfolgreiche Anmeldung
8 2025-06-07 15:15:43.912466 rac00n BACKUP database 2 \N \N 172.19.0.1 curl/8.5.0 Backup erstellt: backup_v2docker_20250607_151543_encrypted.sql.gz.enc (3768 bytes)
9 2025-06-07 15:16:23.724322 rac00n DOWNLOAD backup 2 \N \N 172.19.0.1 curl/8.5.0 Backup heruntergeladen: backup_v2docker_20250607_151543_encrypted.sql.gz.enc
76 2025-06-08 07:55:31.892854 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
78 2025-06-08 07:59:05.01361 rac00n DOWNLOAD backup 5 \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Backup heruntergeladen: backup_v2docker_20250608_075834_encrypted.sql.gz.enc
80 2025-06-08 08:06:18.479631 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/28.0 Chrome/130.0.0.0 Mobile Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
82 2025-06-08 14:36:01.730846 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
84 2025-06-08 16:13:31.837749 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
86 2025-06-08 17:47:45.942574 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 python-requests/2.31.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
10 2025-06-07 17:01:30.363152 w@rh@mm3r LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
11 2025-06-07 17:11:08.302021 w@rh@mm3r LOGIN user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
12 2025-06-07 17:11:10.058681 w@rh@mm3r LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
13 2025-06-07 17:11:17.726581 rac00n LOGIN user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
14 2025-06-07 17:37:01.770454 rac00n LOGIN user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
15 2025-06-07 17:45:53.454599 rac00n LOGIN user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung
16 2025-06-07 17:46:45.804984 rac00n BACKUP database 3 \N \N 172.19.0.5 curl/8.5.0 Backup erstellt: backup_v2docker_20250607_174645_encrypted.sql.gz.enc (4108 bytes)
17 2025-06-07 17:54:25.805772 rac00n LOGIN user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
18 2025-06-07 17:54:30.18286 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
19 2025-06-07 18:02:18.1851 rac00n LOGIN user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung
20 2025-06-07 18:55:11.584957 system LOGIN_FAILED user \N \N \N 172.19.0.5 curl/8.5.0 IP: 172.19.0.1, User: testuser, Message: YOU FAILED
21 2025-06-07 18:55:13.112779 system LOGIN_FAILED user \N \N \N 172.19.0.5 curl/8.5.0 IP: 172.19.0.1, User: testuser, Message: WRONG! 🚫
22 2025-06-07 19:00:59.418824 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
23 2025-06-07 19:01:54.566099 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
24 2025-06-07 19:03:45.046523 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
25 2025-06-07 19:31:13.237177 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
26 2025-06-07 19:32:20.003266 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
27 2025-06-07 19:33:26.379968 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
28 2025-06-07 19:34:09.072085 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
29 2025-06-07 19:36:17.489882 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
30 2025-06-07 19:44:27.078563 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
31 2025-06-07 19:51:17.993707 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
32 2025-06-07 19:58:17.448169 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
33 2025-06-07 19:58:52.291492 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
34 2025-06-07 20:03:15.20645 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
35 2025-06-07 20:05:19.654401 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
36 2025-06-07 20:11:25.331298 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
37 2025-06-07 20:49:37.631513 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
38 2025-06-07 20:52:27.354576 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
39 2025-06-07 20:52:27.38643 rac00n EXPORT license \N \N \N 172.19.0.5 curl/8.5.0 Export aller Lizenzen als CSV
40 2025-06-07 20:54:04.783715 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
41 2025-06-07 20:56:50.950356 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
42 2025-06-07 21:06:51.653154 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 curl/8.5.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
43 2025-06-07 21:12:07.627636 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
44 2025-06-07 21:45:19.164825 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
45 2025-06-07 21:56:57.616336 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
46 2025-06-07 21:58:35.15561 rac00n CREATE license 1 \N {"valid_from": "2025-06-07", "license_key": "AF-202506T-75R4-9M9H-DFEY", "valid_until": "2025-06-13", "license_type": "test", "customer_name": "Demo Firma GmbH", "customer_email": "demo@firma.de"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
47 2025-06-07 22:01:01.548875 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
48 2025-06-07 22:01:28.294051 rac00n CREATE license 2 \N {"valid_from": "2025-06-07", "license_key": "AF-202506T-3DF2-ELJN-RQDR", "valid_until": "2025-06-20", "license_type": "test", "customer_name": "Test Kunde", "customer_email": "test@example.com"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
49 2025-06-07 22:19:17.155373 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
50 2025-06-07 22:19:29.307415 rac00n CREATE license 3 \N {"valid_from": "2025-06-07", "license_key": "AF-202506F-CRS3-PL6W-9CCP", "valid_until": "2026-06-06", "license_type": "full", "customer_name": "Test vor Restore", "customer_email": "test@restore.de"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
51 2025-06-07 22:19:36.9697 rac00n CREATE license 4 \N {"valid_from": "2025-06-07", "license_key": "AF-202506F-GGKA-CJKV-P2PF", "valid_until": "2026-06-06", "license_type": "full", "customer_name": "Test vor Restore", "customer_email": "test@restore.de"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
52 2025-06-07 22:19:51.747722 rac00n CREATE_BATCH license \N \N {"type": "full", "customer": "Müller GmbH & Co. KG", "quantity": 10} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Batch-Generierung von 10 Lizenzen
53 2025-06-07 22:23:56.496775 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
54 2025-06-07 22:24:29.52332 rac00n UPDATE customer 4 {"name": "Demo Firma GmbH", "email": "demo@firma.de"} {"name": "Demo Firma GmbH oder so ähnlich", "email": "demo@firma.de"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
55 2025-06-07 22:24:53.387461 rac00n UPDATE license 14 {"is_active": true, "valid_from": "2025-06-07", "license_key": "AF-202506F-Z6KT-QY28-CTZ9", "valid_until": "2026-06-06", "license_type": "full"} {"is_active": false, "valid_from": "2025-06-07", "license_key": "AF-202506F-Z6KT-QY28-CTZ9", "valid_until": "2026-06-06", "license_type": "full"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
56 2025-06-07 22:25:42.636503 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
57 2025-06-07 22:26:04.176345 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
58 2025-06-07 22:32:36.918402 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
59 2025-06-07 22:33:04.289738 rac00n UPDATE license 12 {"is_active": true, "valid_from": "2025-06-07", "license_key": "AF-202506F-F6E8-2KXL-7GVB", "valid_until": "2026-06-06", "license_type": "full"} {"is_active": false, "valid_from": "2025-06-07", "license_key": "AF-202506F-F6E8-2KXL-7GVB", "valid_until": "2026-06-06", "license_type": "full"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
60 2025-06-07 22:37:11.24327 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
61 2025-06-07 22:40:11.528994 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
62 2025-06-07 23:02:03.858286 system LOGIN_FAILED user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 IP: 172.19.0.1, User: rac00n, Message: YOU FAILED
63 2025-06-07 23:02:13.590411 system LOGIN_FAILED user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 IP: 172.19.0.1, User: rac00n, Message: COMPUTER SAYS NO
64 2025-06-07 23:18:04.017897 system LOGIN_FAILED user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 IP: 172.19.0.1, User: rac00n, Message: NOPE!
65 2025-06-07 23:18:45.316866 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
66 2025-06-07 23:24:10.758514 rac00n CREATE customer 6 \N {"name": "Bli Bla Blub GmbH", "email": "test@bliblablu.info"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
67 2025-06-07 23:24:10.763695 rac00n CREATE license 15 \N {"valid_from": "2025-06-08", "license_key": "AF-202506T-R5TC-9KT3-ZPRD", "valid_until": "2025-07-07", "license_type": "full", "customer_name": "Bli Bla Blub GmbH", "customer_email": "test@bliblablu.info"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
68 2025-06-07 23:25:25.589172 rac00n UPDATE license 14 {"is_active": false, "valid_from": "2025-06-07", "license_key": "AF-202506F-Z6KT-QY28-CTZ9", "valid_until": "2026-06-06", "license_type": "full"} {"is_active": false, "valid_from": "2025-06-07", "license_key": "AF-202506F-Z6KT-QY28-CTZ9", "valid_until": "2026-06-06", "license_type": "full"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
69 2025-06-07 23:25:33.134625 rac00n UPDATE license 11 {"is_active": true, "valid_from": "2025-06-07", "license_key": "AF-202506F-A6BV-6KAX-KU4J", "valid_until": "2026-06-06", "license_type": "full"} {"is_active": false, "valid_from": "2025-06-07", "license_key": "AF-202506F-A6BV-6KAX-KU4J", "valid_until": "2026-06-06", "license_type": "full"} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
70 2025-06-07 23:25:52.026955 rac00n DELETE license 14 {"license_key": "AF-202506F-Z6KT-QY28-CTZ9", "license_type": "full", "customer_name": "Müller GmbH & Co. KG"} \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
71 2025-06-07 23:26:34.32667 rac00n DELETE customer 5 {"name": "Max Mustermann", "email": "max@mustermann.de"} \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 \N
72 2025-06-07 23:27:11.170417 rac00n CREATE_BATCH license \N \N {"type": "full", "customer": "Bli Bla Blub GmbH", "quantity": 5} 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Batch-Generierung von 5 Lizenzen
73 2025-06-07 23:28:45.926809 rac00n BACKUP database 4 \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Backup erstellt: backup_v2docker_20250607_232845_encrypted.sql.gz.enc (7116 bytes)
74 2025-06-07 23:29:10.885674 rac00n DOWNLOAD backup 4 \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Backup heruntergeladen: backup_v2docker_20250607_232845_encrypted.sql.gz.enc
75 2025-06-08 07:55:19.354464 system LOGIN_FAILED user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 IP: 172.19.0.1, User: rac00n, Message: NOPE!
77 2025-06-08 07:58:34.270119 rac00n BACKUP database 5 \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Backup erstellt: backup_v2docker_20250608_075834_encrypted.sql.gz.enc (7308 bytes)
79 2025-06-08 07:59:21.636378 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
81 2025-06-08 08:51:01.683507 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/28.0 Chrome/130.0.0.0 Mobile Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
83 2025-06-08 14:36:24.980042 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
85 2025-06-08 17:21:27.353725 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
87 2025-06-08 17:49:18.527739 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 python-requests/2.31.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
88 2025-06-08 17:49:31.018007 rac00n BACKUP database 6 \N \N 172.19.0.5 python-requests/2.31.0 Backup erstellt: backup_v2docker_20250608_174930_encrypted.sql.gz.enc (7692 bytes)
89 2025-06-08 17:50:12.342288 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 python-requests/2.31.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
90 2025-06-08 18:01:50.515914 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
91 2025-06-08 18:02:24.836845 rac00n BACKUP database 7 \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Backup erstellt: backup_v2docker_20250608_200224_encrypted.sql.gz.enc (7864 bytes)
92 2025-06-08 18:02:35.914193 rac00n LOGOUT user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Abmeldung
93 2025-06-08 18:04:57.805724 system LOGOUT user \N \N \N 172.19.0.5 python-requests/2.31.0 Abmeldung
94 2025-06-08 18:04:59.88908 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 python-requests/2.31.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
95 2025-06-08 18:06:51.462396 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 python-requests/2.31.0 Erfolgreiche Anmeldung von IP: 172.19.0.1
96 2025-06-08 18:10:13.065749 rac00n LOGIN_SUCCESS user \N \N \N 172.19.0.5 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Erfolgreiche Anmeldung von IP: 172.19.0.1
\.
--
-- Data for Name: backup_history; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.backup_history (id, filename, filepath, filesize, backup_type, status, error_message, created_at, created_by, tables_count, records_count, duration_seconds, is_encrypted) FROM stdin;
1 backup_v2docker_20250607_151534_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250607_151534_encrypted.sql.gz.enc 3640 manual success \N 2025-06-07 15:15:34.003903 rac00n 5 6 0.1055765151977539 t
2 backup_v2docker_20250607_151543_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250607_151543_encrypted.sql.gz.enc 3768 manual success \N 2025-06-07 15:15:43.853153 rac00n 5 9 0.058580875396728516 t
3 backup_v2docker_20250607_174645_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250607_174645_encrypted.sql.gz.enc 4108 manual success \N 2025-06-07 17:46:45.701839 rac00n 5 19 0.10155487060546875 t
4 backup_v2docker_20250607_232845_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250607_232845_encrypted.sql.gz.enc 7116 manual success \N 2025-06-07 23:28:45.823584 rac00n 6 102 0.10189580917358398 t
5 backup_v2docker_20250608_075834_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250608_075834_encrypted.sql.gz.enc 7308 manual success \N 2025-06-08 07:58:34.205649 rac00n 6 107 0.06303167343139648 t
6 backup_v2docker_20250608_174930_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250608_174930_encrypted.sql.gz.enc 7692 manual success \N 2025-06-08 17:49:30.953077 rac00n 6 119 0.06305289268493652 t
7 backup_v2docker_20250608_200224_encrypted.sql.gz.enc /app/backups/backup_v2docker_20250608_200224_encrypted.sql.gz.enc 7864 manual success \N 2025-06-08 18:02:24.771159 rac00n 6 123 0.06486988067626953 t
\.
--
-- Data for Name: customers; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.customers (id, name, email, created_at) FROM stdin;
1 Müller GmbH & Co. KG kontakt@müller-köln.de 2025-06-07 14:39:21.554354
2 Test vor Restore test@restore.de 2025-06-07 15:16:51.26188
3 Test Kunde test@example.com 2025-06-07 21:43:48.308699
4 Demo Firma GmbH oder so ähnlich demo@firma.de 2025-06-07 21:43:48.308699
6 Bli Bla Blub GmbH test@bliblablu.info 2025-06-07 23:24:10.753449
\.
--
-- Data for Name: licenses; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.licenses (id, license_key, customer_id, license_type, valid_from, valid_until, is_active) FROM stdin;
1 AF-202506T-75R4-9M9H-DFEY 4 test 2025-06-07 2025-06-13 t
2 AF-202506T-3DF2-ELJN-RQDR 3 test 2025-06-07 2025-06-20 t
3 AF-202506F-CRS3-PL6W-9CCP 2 full 2025-06-07 2026-06-06 t
4 AF-202506F-GGKA-CJKV-P2PF 2 full 2025-06-07 2026-06-06 t
5 AF-202506F-FDZQ-MH3T-6EWP 1 full 2025-06-07 2026-06-06 t
6 AF-202506F-QYM9-58NT-SRCV 1 full 2025-06-07 2026-06-06 t
7 AF-202506F-9AVT-SY3C-KZ6H 1 full 2025-06-07 2026-06-06 t
8 AF-202506F-TS34-U93G-X74Y 1 full 2025-06-07 2026-06-06 t
9 AF-202506F-PC2K-SPEC-9MDS 1 full 2025-06-07 2026-06-06 t
10 AF-202506F-R2VL-J7YF-6XLA 1 full 2025-06-07 2026-06-06 t
13 AF-202506F-JU47-AS8Y-8VFP 1 full 2025-06-07 2026-06-06 t
12 AF-202506F-F6E8-2KXL-7GVB 1 full 2025-06-07 2026-06-06 f
15 AF-202506T-R5TC-9KT3-ZPRD 6 full 2025-06-08 2025-07-07 t
11 AF-202506F-A6BV-6KAX-KU4J 1 full 2025-06-07 2026-06-06 f
16 AF-202506F-F4WM-RUBG-RR7A 6 full 2025-06-08 2025-07-07 t
17 AF-202506F-ZFYY-D2ZG-9D2B 6 full 2025-06-08 2025-07-07 t
18 AF-202506F-KS7T-Z676-7V5L 6 full 2025-06-08 2025-07-07 t
19 AF-202506F-3NJ4-X5ET-RWY2 6 full 2025-06-08 2025-07-07 t
20 AF-202506F-B984-PHN6-BUDX 6 full 2025-06-08 2025-07-07 t
\.
--
-- Data for Name: login_attempts; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.login_attempts (ip_address, attempt_count, first_attempt, last_attempt, blocked_until, last_username_tried, last_error_message) FROM stdin;
192.168.1.50 3 2025-06-07 18:56:54.538998 2025-06-07 18:56:54.538998 2025-06-07 20:56:54.538998 attacker1 NOPE\\!
10.0.0.25 5 2025-06-07 18:56:54.538998 2025-06-07 18:56:54.538998 2025-06-08 14:56:54.538998 scanner ACCESS DENIED, TRY HARDER
192.168.100.200 7 2025-06-07 18:56:54.538998 2025-06-07 18:56:54.538998 2025-06-08 17:56:54.538998 brute_forcer YOU FAILED
\.
--
-- Data for Name: sessions; Type: TABLE DATA; Schema: public; Owner: adminuser
--
COPY public.sessions (id, license_id, session_id, ip_address, user_agent, started_at, last_heartbeat, ended_at, is_active) FROM stdin;
\.
--
-- Name: audit_log_id_seq; Type: SEQUENCE SET; Schema: public; Owner: adminuser
--
SELECT pg_catalog.setval('public.audit_log_id_seq', 96, true);
--
-- Name: backup_history_id_seq; Type: SEQUENCE SET; Schema: public; Owner: adminuser
--
SELECT pg_catalog.setval('public.backup_history_id_seq', 7, true);
--
-- Name: customers_id_seq; Type: SEQUENCE SET; Schema: public; Owner: adminuser
--
SELECT pg_catalog.setval('public.customers_id_seq', 6, true);
--
-- Name: licenses_id_seq; Type: SEQUENCE SET; Schema: public; Owner: adminuser
--
SELECT pg_catalog.setval('public.licenses_id_seq', 20, true);
--
-- Name: sessions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: adminuser
--
SELECT pg_catalog.setval('public.sessions_id_seq', 1, false);
--
-- Name: audit_log audit_log_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.audit_log
ADD CONSTRAINT audit_log_pkey PRIMARY KEY (id);
--
-- Name: backup_history backup_history_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.backup_history
ADD CONSTRAINT backup_history_pkey PRIMARY KEY (id);
--
-- Name: customers customers_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.customers
ADD CONSTRAINT customers_pkey PRIMARY KEY (id);
--
-- Name: licenses licenses_license_key_key; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.licenses
ADD CONSTRAINT licenses_license_key_key UNIQUE (license_key);
--
-- Name: licenses licenses_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.licenses
ADD CONSTRAINT licenses_pkey PRIMARY KEY (id);
--
-- Name: login_attempts login_attempts_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.login_attempts
ADD CONSTRAINT login_attempts_pkey PRIMARY KEY (ip_address);
--
-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.sessions
ADD CONSTRAINT sessions_pkey PRIMARY KEY (id);
--
-- Name: sessions sessions_session_id_key; Type: CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.sessions
ADD CONSTRAINT sessions_session_id_key UNIQUE (session_id);
--
-- Name: idx_audit_log_entity; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_audit_log_entity ON public.audit_log USING btree (entity_type, entity_id);
--
-- Name: idx_audit_log_timestamp; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_audit_log_timestamp ON public.audit_log USING btree ("timestamp" DESC);
--
-- Name: idx_audit_log_username; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_audit_log_username ON public.audit_log USING btree (username);
--
-- Name: idx_backup_history_created_at; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_backup_history_created_at ON public.backup_history USING btree (created_at DESC);
--
-- Name: idx_backup_history_status; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_backup_history_status ON public.backup_history USING btree (status);
--
-- Name: idx_login_attempts_blocked_until; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_login_attempts_blocked_until ON public.login_attempts USING btree (blocked_until);
--
-- Name: idx_login_attempts_last_attempt; Type: INDEX; Schema: public; Owner: adminuser
--
CREATE INDEX idx_login_attempts_last_attempt ON public.login_attempts USING btree (last_attempt DESC);
--
-- Name: licenses licenses_customer_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.licenses
ADD CONSTRAINT licenses_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES public.customers(id);
--
-- Name: sessions sessions_license_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: adminuser
--
ALTER TABLE ONLY public.sessions
ADD CONSTRAINT sessions_license_id_fkey FOREIGN KEY (license_id) REFERENCES public.licenses(id);
--
-- PostgreSQL database dump complete
--

Datei anzeigen

@@ -12,6 +12,8 @@ services:
POSTGRES_INITDB_ARGS: '--encoding=UTF8 --locale=de_DE.UTF-8'
POSTGRES_COLLATE: 'de_DE.UTF-8'
POSTGRES_CTYPE: 'de_DE.UTF-8'
TZ: Europe/Berlin
PGTZ: Europe/Berlin
volumes:
# Persistente Speicherung der Datenbank auf dem Windows-Host
- postgres_data:/var/lib/postgresql/data
@@ -33,6 +35,8 @@ services:
ports:
- "8443:8443"
env_file: .env
environment:
TZ: Europe/Berlin
depends_on:
- postgres
networks:
@@ -50,6 +54,8 @@ services:
restart: always
# Port-Mapping entfernt - nur über nginx erreichbar
env_file: .env
environment:
TZ: Europe/Berlin
depends_on:
- postgres
networks:
@@ -71,6 +77,8 @@ services:
ports:
- "80:80"
- "443:443"
environment:
TZ: Europe/Berlin
depends_on:
- admin-panel
- license-server

Datei anzeigen

@@ -5,15 +5,21 @@ ENV LANG=de_DE.UTF-8
ENV LC_ALL=de_DE.UTF-8
ENV PYTHONIOENCODING=utf-8
# Zeitzone auf Europe/Berlin setzen
ENV TZ=Europe/Berlin
WORKDIR /app
# System-Dependencies inkl. PostgreSQL-Tools installieren
RUN apt-get update && apt-get install -y \
locales \
postgresql-client \
tzdata \
&& sed -i '/de_DE.UTF-8/s/^# //g' /etc/locale.gen \
&& locale-gen \
&& update-locale LANG=de_DE.UTF-8 \
&& ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
&& echo "Europe/Berlin" > /etc/timezone \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

Datei anzeigen

@@ -7,6 +7,7 @@ from functools import wraps
from dotenv import load_dotenv
import pandas as pd
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import io
import subprocess
import gzip
@@ -72,7 +73,7 @@ def login_required(f):
# Prüfe ob Session abgelaufen ist
if 'last_activity' in session:
last_activity = datetime.fromisoformat(session['last_activity'])
time_since_activity = datetime.now() - last_activity
time_since_activity = datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None) - last_activity
# Debug-Logging
app.logger.info(f"Session check for {session.get('username', 'unknown')}: "
@@ -170,7 +171,7 @@ def get_or_create_encryption_key():
def create_backup(backup_type="manual", created_by=None):
"""Erstellt ein verschlüsseltes Backup der Datenbank"""
start_time = time.time()
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
timestamp = datetime.now(ZoneInfo("Europe/Berlin")).strftime("%Y%m%d_%H%M%S")
filename = f"backup_v2docker_{timestamp}_encrypted.sql.gz.enc"
filepath = BACKUP_DIR / filename
@@ -398,7 +399,7 @@ def check_ip_blocked(ip_address):
conn.close()
if result and result[0]:
if result[0] > datetime.now():
if result[0] > datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None):
return True, result[0]
return False, None
@@ -425,7 +426,7 @@ def record_failed_attempt(ip_address, username):
blocked_until = None
if new_count >= MAX_LOGIN_ATTEMPTS:
blocked_until = datetime.now() + timedelta(hours=BLOCK_DURATION_HOURS)
blocked_until = datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None) + timedelta(hours=BLOCK_DURATION_HOURS)
# E-Mail-Benachrichtigung (wenn aktiviert)
if os.getenv("EMAIL_ENABLED", "false").lower() == "true":
send_security_alert_email(ip_address, username, new_count)
@@ -505,7 +506,7 @@ def send_security_alert_email(ip_address, username, attempt_count):
IP-Adresse: {ip_address}
Versuchter Benutzername: {username}
Anzahl Versuche: {attempt_count}
Zeit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
Zeit: {datetime.now(ZoneInfo("Europe/Berlin")).strftime('%Y-%m-%d %H:%M:%S')}
Die IP-Adresse wurde für 24 Stunden gesperrt.
@@ -565,7 +566,7 @@ def generate_license_key(license_type='full'):
chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
# Datum-Teil
now = datetime.now()
now = datetime.now(ZoneInfo("Europe/Berlin"))
date_part = now.strftime('%Y%m')
type_char = 'F' if license_type == 'full' else 'T'
@@ -606,7 +607,7 @@ def login():
# Prüfen ob IP gesperrt ist
is_blocked, blocked_until = check_ip_blocked(ip_address)
if is_blocked:
time_remaining = (blocked_until - datetime.now()).total_seconds() / 3600
time_remaining = (blocked_until - datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None)).total_seconds() / 3600
error_msg = f"IP GESPERRT! Noch {time_remaining:.1f} Stunden warten."
return render_template("login.html", error=error_msg, error_type="blocked")
@@ -668,7 +669,7 @@ def login():
session.permanent = True # Aktiviert das Timeout
session['logged_in'] = True
session['username'] = username
session['last_activity'] = datetime.now().isoformat()
session['last_activity'] = datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None).isoformat()
reset_login_attempts(ip_address)
log_audit('LOGIN_SUCCESS', 'user',
additional_info=f"Erfolgreiche Anmeldung von IP: {ip_address}")
@@ -710,7 +711,7 @@ def logout():
def heartbeat():
"""Endpoint für Session Keep-Alive - aktualisiert last_activity"""
# Aktualisiere last_activity nur wenn explizit angefordert
session['last_activity'] = datetime.now().isoformat()
session['last_activity'] = datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None).isoformat()
# Force session save
session.modified = True
@@ -975,7 +976,7 @@ def dashboard():
'ip_address': event[0],
'attempt_count': event[1],
'last_attempt': event[2].strftime('%d.%m %H:%M'),
'blocked_until': event[3].strftime('%d.%m %H:%M') if event[3] and event[3] > datetime.now() else None,
'blocked_until': event[3].strftime('%d.%m %H:%M') if event[3] and event[3] > datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None) else None,
'username_tried': event[4],
'error_message': event[5]
})
@@ -1249,7 +1250,7 @@ def batch_licenses():
'licenses': generated_licenses,
'valid_from': valid_from,
'valid_until': valid_until,
'timestamp': datetime.now().isoformat()
'timestamp': datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None).isoformat()
}
flash(f'{quantity} Lizenzen erfolgreich generiert!', 'success')
@@ -1308,7 +1309,7 @@ def export_batch():
io.BytesIO(output.getvalue().encode('utf-8-sig')),
mimetype='text/csv',
as_attachment=True,
download_name=f"batch_licenses_{batch_data['customer'].replace(' ', '_')}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
download_name=f"batch_licenses_{batch_data['customer'].replace(' ', '_')}_{datetime.now(ZoneInfo('Europe/Berlin')).strftime('%Y%m%d_%H%M%S')}.csv"
)
@app.route("/licenses")
@@ -1778,7 +1779,7 @@ def export_licenses():
# Audit-Log
log_audit('EXPORT', 'license',
additional_info=f"Export aller Lizenzen als {export_format.upper()}")
filename = f'lizenzen_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
filename = f'lizenzen_export_{datetime.now(ZoneInfo("Europe/Berlin")).strftime("%Y%m%d_%H%M%S")}'
if export_format == 'csv':
# CSV Export
@@ -1859,7 +1860,7 @@ def export_customers():
# Audit-Log
log_audit('EXPORT', 'customer',
additional_info=f"Export aller Kunden als {export_format.upper()}")
filename = f'kunden_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
filename = f'kunden_export_{datetime.now(ZoneInfo("Europe/Berlin")).strftime("%Y%m%d_%H%M%S")}'
if export_format == 'csv':
# CSV Export
@@ -2108,7 +2109,7 @@ def blocked_ips():
'first_attempt': ip[2].strftime('%d.%m.%Y %H:%M'),
'last_attempt': ip[3].strftime('%d.%m.%Y %H:%M'),
'blocked_until': ip[4].strftime('%d.%m.%Y %H:%M'),
'is_active': ip[4] > datetime.now(),
'is_active': ip[4] > datetime.now(ZoneInfo("Europe/Berlin")).replace(tzinfo=None),
'last_username': ip[5],
'last_error': ip[6]
})

Datei anzeigen

@@ -1,11 +1,14 @@
-- UTF-8 Encoding für deutsche Sonderzeichen sicherstellen
SET client_encoding = 'UTF8';
-- Zeitzone auf Europe/Berlin setzen
SET timezone = 'Europe/Berlin';
CREATE TABLE IF NOT EXISTS customers (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_email UNIQUE (email)
);
@@ -17,7 +20,7 @@ CREATE TABLE IF NOT EXISTS licenses (
valid_from DATE NOT NULL,
valid_until DATE NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS sessions (
@@ -26,16 +29,16 @@ CREATE TABLE IF NOT EXISTS sessions (
session_id TEXT UNIQUE NOT NULL,
ip_address TEXT,
user_agent TEXT,
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_heartbeat TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMP,
started_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
last_heartbeat TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMP WITH TIME ZONE,
is_active BOOLEAN DEFAULT TRUE
);
-- Audit-Log-Tabelle für Änderungsprotokolle
CREATE TABLE IF NOT EXISTS audit_log (
id SERIAL PRIMARY KEY,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
username TEXT NOT NULL,
action TEXT NOT NULL,
entity_type TEXT NOT NULL,
@@ -61,7 +64,7 @@ CREATE TABLE IF NOT EXISTS backup_history (
backup_type TEXT NOT NULL, -- 'manual' oder 'scheduled'
status TEXT NOT NULL, -- 'success', 'failed', 'in_progress'
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
created_by TEXT NOT NULL,
tables_count INTEGER,
records_count INTEGER,
@@ -77,9 +80,9 @@ CREATE INDEX idx_backup_history_status ON backup_history(status);
CREATE TABLE IF NOT EXISTS login_attempts (
ip_address VARCHAR(45) PRIMARY KEY,
attempt_count INTEGER DEFAULT 0,
first_attempt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_attempt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
blocked_until TIMESTAMP NULL,
first_attempt TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
last_attempt TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
blocked_until TIMESTAMP WITH TIME ZONE NULL,
last_username_tried TEXT,
last_error_message TEXT
);
@@ -93,7 +96,7 @@ DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'licenses' AND column_name = 'created_at') THEN
ALTER TABLE licenses ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE licenses ADD COLUMN created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP;
-- Setze created_at für bestehende Einträge auf das valid_from Datum
UPDATE licenses SET created_at = valid_from WHERE created_at IS NULL;

Datei anzeigen

@@ -1,5 +1,15 @@
FROM python:3.11-slim
# Zeitzone setzen
ENV TZ=Europe/Berlin
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata \
&& ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
&& echo "Europe/Berlin" > /etc/timezone \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Placeholder für Lizenzserver

Datei anzeigen

@@ -1,5 +1,11 @@
FROM nginx:alpine
# Zeitzone setzen
ENV TZ=Europe/Berlin
RUN apk add --no-cache tzdata \
&& ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
&& echo "Europe/Berlin" > /etc/timezone
# SSL-Verzeichnis erstellen
RUN mkdir -p /etc/nginx/ssl

Datei anzeigen

@@ -1,10 +1,12 @@
FROM postgres:14
# Deutsche Locale installieren
RUN apt-get update && apt-get install -y locales \
# Deutsche Locale und Zeitzone installieren
RUN apt-get update && apt-get install -y locales tzdata \
&& sed -i '/de_DE.UTF-8/s/^# //g' /etc/locale.gen \
&& locale-gen \
&& update-locale LANG=de_DE.UTF-8 \
&& ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
&& echo "Europe/Berlin" > /etc/timezone \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
@@ -12,3 +14,7 @@ RUN apt-get update && apt-get install -y locales \
ENV LANG de_DE.UTF-8
ENV LANGUAGE de_DE:de
ENV LC_ALL de_DE.UTF-8
# Zeitzone setzen
ENV TZ=Europe/Berlin
ENV PGTZ=Europe/Berlin

Datei anzeigen

@@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"Bash(python3:*)",
"Bash(pip install:*)",
"Bash(pip3 install:*)"
],
"deny": []
}
}

104
v2_testing/test_audit_raw.py Normale Datei
Datei anzeigen

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
from bs4 import BeautifulSoup
import time
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_raw():
"""Test audit log timezone by parsing HTML"""
session = requests.Session()
print("Audit Log Raw HTML Test")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
# Logout first
session.get(f"{base_url_local}/logout", verify=verify_ssl)
time.sleep(1)
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed")
return
print("✓ Login successful")
# Get audit log
print("\nFetching audit log...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Save raw HTML for inspection
with open("audit_log_raw.html", "w", encoding="utf-8") as f:
f.write(response.text)
print("✓ Saved raw HTML to audit_log_raw.html")
# Parse with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Find all table rows
rows = soup.find_all('tr')
print(f"✓ Found {len(rows)} table rows")
# Look for LOGIN_SUCCESS in recent entries
for i, row in enumerate(rows[:5]): # Check first 5 rows
cells = row.find_all('td')
if cells and len(cells) > 1:
timestamp_cell = cells[0].text.strip()
action_cell = cells[2].text.strip() if len(cells) > 2 else ""
if i == 0:
print(f"\nFirst row details:")
print(f" Timestamp: {timestamp_cell}")
print(f" Action: {action_cell}")
if "LOGIN_SUCCESS" in action_cell:
print(f"\nFound LOGIN_SUCCESS entry:")
print(f" Timestamp: {timestamp_cell}")
# Check if timestamp contains current Berlin hour
if berlin_now.strftime("%H:") in timestamp_cell:
print(f" ✓ Contains Berlin hour ({berlin_now.strftime('%H:')})")
elif utc_now.strftime("%H:") in timestamp_cell:
print(f" ✗ Contains UTC hour ({utc_now.strftime('%H:')})")
break
else:
print(f"✗ Failed to fetch audit log: {response.status_code}")
if __name__ == "__main__":
test_audit_raw()

Datei anzeigen

@@ -0,0 +1,113 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import time
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_simple():
"""Simple test to check audit log timestamps"""
session = requests.Session()
print("Audit Log Timezone Check")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Difference: {(berlin_now.hour - utc_now.hour) % 24} hours")
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed")
return
print("✓ Login successful")
# Create a distinctive action to find in audit log
print("\nCreating a test action...")
# Try to access customers page (this will create an audit entry)
response = session.get(f"{base_url_local}/customers", verify=verify_ssl)
# Now check audit log
print("\nChecking audit log...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Look for table rows with class="table"
# Extract just the table content
table_match = re.search(r'<table class="table[^>]*>(.*?)</table>', response.text, re.DOTALL)
if table_match:
table_content = table_match.group(1)
# Find all <tr> tags
rows = re.findall(r'<tr[^>]*>(.*?)</tr>', table_content, re.DOTALL)
print(f"✓ Found {len(rows)} audit log entries")
if rows:
# Get the first data row (skip header)
first_row = rows[1] if len(rows) > 1 else rows[0]
# Extract timestamp from first cell
timestamp_match = re.search(r'<td[^>]*>([^<]+)</td>', first_row)
if timestamp_match:
timestamp = timestamp_match.group(1).strip()
print(f"\nMost recent audit entry timestamp: {timestamp}")
# Check if it contains current Berlin hour
berlin_hour = berlin_now.strftime("%H:")
utc_hour = utc_now.strftime("%H:")
if berlin_hour in timestamp:
print(f"✓ Timestamp contains Berlin hour ({berlin_hour})")
print("✓ Audit log is using Berlin timezone!")
elif utc_hour in timestamp:
print(f"✗ Timestamp contains UTC hour ({utc_hour})")
print("✗ Audit log is still using UTC")
print("\nTo fix this:")
print("1. cd ../v2")
print("2. docker-compose down")
print("3. docker-compose build --no-cache")
print("4. docker-compose up -d")
else:
print("⚠ Could not determine timezone from timestamp")
else:
print(f"✗ Failed to fetch audit log: {response.status_code}")
if __name__ == "__main__":
test_audit_simple()

Datei anzeigen

@@ -0,0 +1,123 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import time
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_audit_timezone():
"""Test audit log timezone specifically"""
session = requests.Session()
print("Audit Log Timezone Test")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
base_url_local = base_url
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Offset: +{(berlin_now.hour - utc_now.hour) % 24} hours")
# First logout if already logged in
session.get(f"{base_url_local}/logout", verify=verify_ssl)
time.sleep(1)
# Login (this will create a new audit log entry)
print(f"\nPerforming login at {berlin_now.strftime('%H:%M:%S')} Berlin time...")
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed: {response.status_code}")
return
print("✓ Login successful")
# Immediately check audit log
print("\nChecking audit log for fresh LOGIN_SUCCESS entry...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Look for timestamps in the audit log
# Pattern to find timestamps in format YYYY-MM-DD HH:MM:SS
timestamp_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'
# Find all timestamps
timestamps = re.findall(timestamp_pattern, response.text)
if timestamps:
print(f"✓ Found {len(timestamps)} timestamps in audit log")
# Check the most recent timestamp (should be first in list)
if timestamps:
latest_timestamp = timestamps[0]
print(f"\nMost recent timestamp: {latest_timestamp}")
# Extract hour from timestamp
hour_match = re.search(r' (\d{2}):', latest_timestamp)
if hour_match:
log_hour = int(hour_match.group(1))
berlin_hour = berlin_now.hour
utc_hour = utc_now.hour
print(f" Timestamp hour: {log_hour:02d}")
print(f" Berlin hour: {berlin_hour:02d}")
print(f" UTC hour: {utc_hour:02d}")
if log_hour == berlin_hour:
print("\n✓ Audit log is using Berlin time!")
elif log_hour == utc_hour:
print("\n✗ Audit log appears to be using UTC time")
print(" → Docker containers may need to be rebuilt")
else:
print("\n⚠ Could not determine timezone (timestamp doesn't match either timezone)")
else:
print("✗ No timestamps found in audit log")
# Also check for "vor X Minuten" text which might indicate timezone
if "vor 0 Minuten" in response.text or "vor 1 Minute" in response.text:
print("\n✓ Recent entries found (German time format)")
else:
print(f"✗ Failed to access audit log: {response.status_code}")
print("\n" + "=" * 50)
print("If timestamps show UTC instead of Berlin time:")
print("1. Run: docker-compose down")
print("2. Run: docker-compose build --no-cache")
print("3. Run: docker-compose up -d")
if __name__ == "__main__":
test_audit_timezone()

159
v2_testing/test_timezone.py Normale Datei
Datei anzeigen

@@ -0,0 +1,159 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import json
import time
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
# Use external URL for testing
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
# Fallback to localhost if external URL is not accessible
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_timezone_functionality():
"""Test if timestamps are in German timezone (Europe/Berlin)"""
session = requests.Session()
print("Testing Timezone Functionality (Europe/Berlin)")
print("=" * 50)
# Test connection to external URL first
global base_url
try:
test_response = session.get(base_url, verify=True, timeout=5)
print(f"✓ Using external URL: {base_url}")
except:
base_url = fallback_url
print(f" Using fallback URL: {base_url}")
# Get current time in UTC and Berlin
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"Current UTC time: {utc_now.strftime('%Y-%m-%d %H:%M:%S %Z')}")
print(f"Current Berlin time: {berlin_now.strftime('%Y-%m-%d %H:%M:%S %Z')}")
print(f"Time difference: {(berlin_now.hour - utc_now.hour) % 24} hours")
print()
# Login
verify_ssl = base_url != fallback_url # Verify SSL for external URL only
response = session.get(f"{base_url}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"✗ Login failed: {response.status_code}")
return
print("✓ Login successful")
print()
# Test 1: Create a test license to check created_at timestamp
print("Test 1: Creating test license to check timestamps...")
# First, get a customer ID or create one
license_data = {
"customer_select": "new",
"customer_name": f"Timezone Test Customer {int(time.time())}",
"customer_email": f"timezone-test-{int(time.time())}@example.com",
"license_key": f"AF-{berlin_now.strftime('%Y%m')}T-TEST-TIME-ZONE",
"license_type": "test",
"max_sessions": "1",
"start_date": berlin_now.strftime("%Y-%m-%d"),
"duration": "1",
"duration_unit": "days"
}
response = session.post(f"{base_url}/create", data=license_data, verify=verify_ssl)
if response.status_code == 200:
print("✓ Test license created")
else:
print(f"✗ Failed to create license: {response.status_code}")
# Test 2: Check audit log for timezone
print("\nTest 2: Checking audit log timestamps...")
response = session.get(f"{base_url}/audit", verify=verify_ssl)
if response.status_code == 200:
# Extract the most recent audit log entry timestamp from HTML
if "CREATE" in response.text and license_data["license_key"] in response.text:
print("✓ Audit log entry created")
# Check if timestamps in audit log appear to be in German time
# This is a simple check - in production you'd parse the HTML properly
current_hour = berlin_now.strftime("%H:")
if current_hour in response.text:
print(f"✓ Audit log shows Berlin time (contains {current_hour})")
else:
print(f"⚠ Audit log might show UTC time (doesn't contain {current_hour})")
else:
print(f"✗ Failed to access audit log: {response.status_code}")
# Test 3: Check backup functionality for filename timezone
print("\nTest 3: Testing backup filename timezone...")
response = session.post(f"{base_url}/backup/create", verify=verify_ssl)
if response.status_code == 302: # Redirect after backup
print("✓ Backup created")
# Check backup list
response = session.get(f"{base_url}/backups", verify=verify_ssl)
if response.status_code == 200:
# Check if backup filename contains current Berlin hour
berlin_hour = berlin_now.strftime("%H")
if f"_{berlin_hour}" in response.text:
print(f"✓ Backup filename uses Berlin time (contains hour {berlin_hour})")
else:
utc_hour = utc_now.strftime("%H")
if f"_{utc_hour}" in response.text:
print(f"✗ Backup filename might use UTC time (contains hour {utc_hour})")
else:
print("⚠ Could not determine timezone from backup filename")
else:
print(f"✗ Failed to create backup: {response.status_code}")
# Test 4: Check session timestamps
print("\nTest 4: Checking session timestamps...")
response = session.get(f"{base_url}/sessions", verify=verify_ssl)
if response.status_code == 200:
print("✓ Accessed sessions page")
# Active sessions should show current time
if "Keine aktiven Sessions" not in response.text:
print("✓ Session data available")
else:
print(" No active sessions to check (this is normal)")
else:
print(f"✗ Failed to access sessions: {response.status_code}")
# Test 5: Database timezone check
print("\nTest 5: Summary")
print("-" * 30)
time_diff = (berlin_now.hour - utc_now.hour) % 24
if time_diff == 1:
print("✓ Timezone offset is +1 hour (CET - Central European Time)")
elif time_diff == 2:
print("✓ Timezone offset is +2 hours (CEST - Central European Summer Time)")
else:
print(f"⚠ Unexpected timezone offset: {time_diff} hours")
print("\nNote: All new timestamps should be in Europe/Berlin timezone")
print("Existing data might still show UTC until updated")
if __name__ == "__main__":
test_timezone_functionality()

Datei anzeigen

@@ -0,0 +1,122 @@
#!/usr/bin/env python3
import requests
import urllib3
from datetime import datetime
from zoneinfo import ZoneInfo
import re
# Disable SSL warnings for self-signed certificate
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Test configuration
base_url = "https://admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com"
fallback_url = "https://localhost:443"
admin_user = {"username": "rac00n", "password": "1248163264"}
def test_timezone_simple():
"""Simple test to verify timezone is Europe/Berlin"""
session = requests.Session()
print("Timezone Verification Test (Europe/Berlin)")
print("=" * 50)
# Test connection
try:
test_response = session.get(base_url, verify=True, timeout=5)
verify_ssl = True
print(f"✓ Using external URL: {base_url}")
except:
base_url_local = fallback_url
verify_ssl = False
print(f" Using fallback URL: {fallback_url}")
else:
base_url_local = base_url
# Show current times
utc_now = datetime.now(ZoneInfo("UTC"))
berlin_now = datetime.now(ZoneInfo("Europe/Berlin"))
print(f"\nCurrent times:")
print(f" UTC: {utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" Berlin: {berlin_now.strftime('%Y-%m-%d %H:%M:%S')}")
# Calculate offset
time_diff = (berlin_now.hour - utc_now.hour) % 24
if berlin_now.day != utc_now.day:
# Handle day boundary
if berlin_now.day > utc_now.day:
time_diff = (berlin_now.hour + 24 - utc_now.hour) % 24
else:
time_diff = (berlin_now.hour - utc_now.hour - 24) % 24
print(f" Offset: +{time_diff} hours")
# Login
response = session.get(f"{base_url_local}/login", verify=verify_ssl)
if response.status_code != 200:
print(f"\n✗ Failed to access login page: {response.status_code}")
return
login_data = {
"username": admin_user["username"],
"password": admin_user["password"]
}
response = session.post(f"{base_url_local}/login", data=login_data, verify=verify_ssl, allow_redirects=False)
if response.status_code != 302:
print(f"\n✗ Login failed: {response.status_code}")
return
print(f"\n✓ Login successful")
# Check dashboard for any timestamps
print("\nChecking for timestamps in dashboard...")
response = session.get(f"{base_url_local}/", verify=verify_ssl)
if response.status_code == 200:
# Look for time patterns in dashboard
time_pattern = r'\d{2}:\d{2}:\d{2}'
times_found = re.findall(time_pattern, response.text)
if times_found:
print(f"✓ Found {len(times_found)} timestamps in dashboard")
# Check if any match current Berlin hour
berlin_hour = berlin_now.strftime("%H:")
if any(berlin_hour in time for time in times_found):
print(f"✓ Timestamps appear to use Berlin time (found {berlin_hour}xx)")
else:
print(f" Could not confirm timezone from timestamps")
else:
print(" No timestamps found in dashboard")
# Check audit log
print("\nChecking audit log for LOGIN timestamp...")
response = session.get(f"{base_url_local}/audit", verify=verify_ssl)
if response.status_code == 200:
# Extract the most recent LOGIN entry
if "LOGIN_SUCCESS" in response.text:
# Look for timestamp near LOGIN_SUCCESS
berlin_time_str = berlin_now.strftime("%Y-%m-%d %H:")
if berlin_time_str in response.text:
print(f"✓ Audit log shows Berlin time (contains {berlin_time_str}xx)")
else:
utc_time_str = utc_now.strftime("%Y-%m-%d %H:")
if utc_time_str in response.text:
print(f"✗ Audit log might show UTC time (contains {utc_time_str}xx)")
else:
print(f" Could not determine timezone from audit log")
# Summary
print("\n" + "=" * 50)
print("Summary:")
if time_diff == 1:
print("✓ System timezone offset: +1 hour (CET - Winter time)")
elif time_diff == 2:
print("✓ System timezone offset: +2 hours (CEST - Summer time)")
else:
print(f"⚠ Unexpected timezone offset: +{time_diff} hours")
print("\nNote: The system should use Europe/Berlin timezone for all new data.")
print("Existing data created before the timezone change may still show UTC.")
if __name__ == "__main__":
test_timezone_simple()