deutsche Zeit statt UTC
Dieser Commit ist enthalten in:
@@ -48,7 +48,8 @@
|
||||
"Bash(find:*)",
|
||||
"Bash(openssl x509:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(openssl dhparam:*)"
|
||||
"Bash(openssl dhparam:*)",
|
||||
"Bash(rg:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
|
||||
81
JOURNAL.md
81
JOURNAL.md
@@ -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;
|
||||
```
|
||||
1
backups/backup_v2docker_20250608_075834_encrypted.sql.gz.enc
Normale Datei
1
backups/backup_v2docker_20250608_075834_encrypted.sql.gz.enc
Normale Datei
Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist
1
backups/backup_v2docker_20250608_174930_encrypted.sql.gz.enc
Normale Datei
1
backups/backup_v2docker_20250608_174930_encrypted.sql.gz.enc
Normale Datei
Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist
1
backups/backup_v2docker_20250608_200224_encrypted.sql.gz.enc
Normale Datei
1
backups/backup_v2docker_20250608_200224_encrypted.sql.gz.enc
Normale Datei
Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist
624
v2/backup_before_timezone_change.sql
Normale Datei
624
v2/backup_before_timezone_change.sql
Normale Datei
@@ -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
|
||||
--
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/*
|
||||
|
||||
|
||||
@@ -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]
|
||||
})
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
10
v2_testing/.claude/settings.local.json
Normale Datei
10
v2_testing/.claude/settings.local.json
Normale Datei
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(python3:*)",
|
||||
"Bash(pip install:*)",
|
||||
"Bash(pip3 install:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
}
|
||||
104
v2_testing/test_audit_raw.py
Normale Datei
104
v2_testing/test_audit_raw.py
Normale Datei
@@ -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()
|
||||
113
v2_testing/test_audit_simple.py
Normale Datei
113
v2_testing/test_audit_simple.py
Normale Datei
@@ -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()
|
||||
123
v2_testing/test_audit_timezone.py
Normale Datei
123
v2_testing/test_audit_timezone.py
Normale Datei
@@ -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
159
v2_testing/test_timezone.py
Normale Datei
@@ -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()
|
||||
122
v2_testing/test_timezone_simple.py
Normale Datei
122
v2_testing/test_timezone_simple.py
Normale Datei
@@ -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()
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren