Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
660c8b6
TIMAAT Weiterentwicklung #9 - categories view
NKO97 Nov 13, 2025
38a88ff
TIMAAT Weiterentwicklung #9 - categories view
NKO97 Nov 17, 2025
073cd66
TIMAAT Weiterentwicklung #9 - categories view
NKO97 Nov 17, 2025
dc4cb11
TIMAAT Weiterentwicklung #9 - Datatables integration for category sets
NKO97 Nov 17, 2025
fd2440f
TIMAAT Weiterentwicklung #9 - Datatables integration for categories
NKO97 Nov 17, 2025
1ffd90f
TIMAAT Weiterentwicklung #9 - Adding and edit of categories
NKO97 Nov 23, 2025
defffca
TIMAAT Weiterentwicklung #9 - Adding and edit of category sets
NKO97 Nov 23, 2025
d69ec20
TIMAAT Weiterentwicklung #9 - Implement category set deletion
NKO97 Nov 23, 2025
388cc12
TIMAAT Weiterentwicklung #9 - Generic datatable implementation
NKO97 Nov 24, 2025
5eaa620
TIMAAT Weiterentwicklung #9 - Implemented categories table for actors
NKO97 Nov 24, 2025
3dcb242
TIMAAT Weiterentwicklung #9 - Implemented listing structure for storages
NKO97 Nov 28, 2025
e62e7b3
TIMAAT Weiterentwicklung #9 - Added metamodel processor
NKO97 Dec 2, 2025
e59b4f9
TIMAAT Weiterentwicklung #9 - Started implementation of table column …
NKO97 Dec 3, 2025
bc14aac
Merge branch 'nko-master' into 9-umsetzung-einer-ansicht-zur-betracht…
NKO97 Dec 3, 2025
902b046
TIMAAT Weiterentwicklung #9 - Implemented column selector component
NKO97 Dec 7, 2025
0a30f49
TIMAAT Weiterentwicklung #9 - Added persisting and loading of active …
NKO97 Dec 7, 2025
19fa7d4
TIMAAT Weiterentwicklung #9 - Added col reorder plugin
NKO97 Dec 8, 2025
19242ce
TIMAAT Weiterentwicklung #9 - Added category and category set query p…
NKO97 Dec 13, 2025
dcffa19
TIMAAT Weiterentwicklung #9 - Created a generic DbStorage
NKO97 Dec 13, 2025
1195308
TIMAAT Weiterentwicklung #9 - Created a generic DbStorage
NKO97 Dec 13, 2025
9307321
TIMAAT Weiterentwicklung #9 - Showing of information message when no …
NKO97 Dec 19, 2025
bccf8ec
TIMAAT Weiterentwicklung #9 - Usage of selected categories and catego…
NKO97 Dec 19, 2025
8f23c7d
TIMAAT Weiterentwicklung #9 - Created database update & Refactored as…
NKO97 Dec 27, 2025
2968b6f
TIMAAT Weiterentwicklung #9 - Categories and category sets for actors
NKO97 Dec 28, 2025
d72472d
TIMAAT Weiterentwicklung #9 - Fixed setting of categories
NKO97 Jan 10, 2026
643f5c6
TIMAAT Weiterentwicklung #9 - Implemented endpoint segment structure …
NKO97 Jan 10, 2026
e36a652
TIMAAT Weiterentwicklung #9 - segment structure category table
NKO97 Jan 10, 2026
5556fa2
TIMAAT Weiterentwicklung #9 - Added entity type filter buttons
NKO97 Jan 11, 2026
45303a6
TIMAAT Weiterentwicklung #9 - Added types filter to entity endpoints
NKO97 Jan 11, 2026
3303b32
TIMAAT Weiterentwicklung #9 - Integrate usage of type query parameters
NKO97 Jan 11, 2026
a388832
TIMAAT Weiterentwicklung #9 - Added vertical scrolling for categories…
NKO97 Jan 11, 2026
06b78a1
TIMAAT Weiterentwicklung #9 - Added column groups
NKO97 Jan 11, 2026
4ceed56
TIMAAT Weiterentwicklung #9 - Categories content tables - Updated col…
NKO97 Jan 12, 2026
599181c
TIMAAT Weiterentwicklung #9 - Categories content tables - Implemented…
NKO97 Jan 12, 2026
ad5a401
TIMAAT Weiterentwicklung #9 - Categories content table - Ordering
NKO97 Jan 12, 2026
eb25e32
TIMAAT Weiterentwicklung #9 - Implemented thumbnail column for annota…
NKO97 Jan 13, 2026
bd8aad1
TIMAAT Weiterentwicklung #9 - Implemented authorization verification
NKO97 Jan 13, 2026
403a325
TIMAAT Weiterentwicklung #9 - Configurable search field for generic t…
NKO97 Jan 13, 2026
88c9f04
TIMAAT Weiterentwicklung #9 - Updated generic table representation to…
NKO97 Jan 13, 2026
25afede
TIMAAT Weiterentwicklung #9 - Fixed bug leading to a hiding of save a…
NKO97 Jan 13, 2026
a690885
TIMAAT Weiterentwicklung #9 - Fixed bug leading to not selectable aud…
NKO97 Jan 13, 2026
fd6868b
TIMAAT Weiterentwicklung #9 - Fixed titles in form
NKO97 Jan 13, 2026
2cf9347
TIMAAT Weiterentwicklung #9 - Fixed used query parameter to filter by…
NKO97 Jan 13, 2026
1092dca
TIMAAT Weiterentwicklung #9 - Fixed dependency bug
NKO97 Jan 13, 2026
fc534c0
TIMAAT Weiterentwicklung #9 - Fixed entrypoint script
NKO97 Jan 13, 2026
d084ca2
Update docker-image-build.yml
NKO97 Feb 26, 2026
e7af3e1
master: Increased version to 1.0.0-SNAPSHOT
NKO97 Apr 20, 2026
36497ae
TIMAAT #57 - Updated database schema
NKO97 May 12, 2026
7654e16
TIMAAT #57 - Implemented ORM
NKO97 May 12, 2026
48278e9
TIMAAT #57 - Updated database model
NKO97 May 12, 2026
3cd70ae
TIMAAT #57 - Defined new task type handling the preparation of a medi…
NKO97 May 12, 2026
5ec5fc5
TIMAAT #57 - Implemented task preparing a medium to get transcribed
NKO97 May 16, 2026
719eab0
TIMAAT #57 - Refactored task storage and state updating to use regist…
NKO97 May 16, 2026
234ef5c
TIMAAT #57 - Implemented TranscriptionService
NKO97 May 16, 2026
ae41d32
Add CLAUDE.md with build, config, and architecture guidance
NKO97 May 16, 2026
4d13d94
TIMAAT #57 - Improved engine and model sync
NKO97 May 16, 2026
147e959
TIMAAT #57 - Dependency Updates
NKO97 May 21, 2026
449b1a5
TIMAAT #57 - Fixed circular dependency error
NKO97 May 21, 2026
1f7acbb
TIMAAT #57 - Improved transcription creation flow
NKO97 May 21, 2026
cd80334
TIMAAT #57 - Implemented deletion of transcriptions
NKO97 May 24, 2026
21e5d38
TIMAAT #57 - Implemented new endpoints to modify transcription settin…
NKO97 May 24, 2026
b9aee33
TIMAAT #57 - Set first received model as default model (when not set)
NKO97 May 24, 2026
0213f57
TIMAAT #57 - Added endpoints to EndpointMedium allowing access and cr…
NKO97 May 24, 2026
e685487
TIMAAT #57 - Fixed some error occurred during first transcription task
NKO97 May 24, 2026
e89e454
TIMAAT #57 - Added transcription deletion endpoint
NKO97 May 24, 2026
ac4ab2b
TIMAAT #57 - Defined endpoint to update the default transcription of …
NKO97 May 28, 2026
e011e32
TIMAAT #57 - Defined endpoint to download transcription srt content
NKO97 May 28, 2026
a730763
TIMAAT #57 - Updated build and docker image to Java 25
NKO97 May 28, 2026
e47a711
Merge pull request #68 from NKO-Dev-Studio/57-umsetzung-der-erzeugung…
NKO97 May 28, 2026
061e9aa
TIMAAT - Added docker compose which can be used for production deploy…
NKO97 May 29, 2026
da5bcec
TIMAAT - Updated gitignore
NKO97 May 29, 2026
d19c7f8
TIMAAT - Updated webservice container to latest on prod deployment
NKO97 May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/docker-image-build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Build & Push Multi-Arch Docker Image

on:
workflow_dispatch:
push:
branches:
- master
Expand All @@ -20,10 +21,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 11
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '11'
java-version: '25'
distribution: 'temurin'
cache: maven
- name: Build with Maven
Expand Down Expand Up @@ -62,4 +63,4 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}
8 changes: 4 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '11'
java-version: '25'
distribution: 'temurin'
cache: maven
- name: Build with Maven
Expand All @@ -28,10 +28,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '11'
java-version: '25'
distribution: 'temurin'
cache: maven
- name: Run Maven tests
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ test_output
.classpath
*.bak
.vscode/
.idea/
.project
CLAUDE.local.md
/docker/compose/.env
/docker/compose/certs/
83 changes: 83 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

TIMAAT is a Jakarta EE web application for collaborative video annotation, packaged as a WAR deployed to Tomcat 10. It is the successor to FIPOP (the persistence unit and database are still named `FIPOP`). Backend is Java + Jersey; frontend is server-served HTML + RequireJS modules in `src/main/webapp/js`.

## Build & Run

- `mvn package` — builds `target/TIMAAT.war`. Deploy by copying into Tomcat's `webapps/` directory; app is then reachable at `http://localhost:8080/TIMAAT`.
- `mvn test` — runs the JUnit 5 suite. Surefire is configured with `-javaagent:.../mockito-core.jar` (see pom.xml:67) because Mockito 5 needs the agent attached on Java 21+. Don't drop that argLine.
- Run a single test: `mvn test -Dtest=FfmpegAudioEngineTest` or `mvn test -Dtest=FfmpegAudioEngineTest#methodName`.
- Java toolchain: `pom.xml` sets `maven.compiler.release=25`, but `.github/workflows/maven.yml` still pins JDK 11 — the CI config is stale relative to the source level. Local builds need JDK 25.
- Annotation processing: EclipseLink's `CanonicalModelProcessor` runs at compile time and generates JPA static metamodel classes into `target/generated-sources/annotations`.

## Runtime configuration

The app reads `~/.timaat/timaat.properties` (Linux/macOS) or `%HOMEDRIVE%%HOMEPATH%\.timaat\timaat.properties` (Windows). Template lives at `src/main/resources/timaat-default.properties`. Required keys: `database.url`, `database.user`, `database.password`, `storage.location` (filesystem root for media), `app.ffmpeg.location`, `app.imagemagick.location`. Async task pool sizing: `app.task.coreParallelCount`, `app.task.maxParallelCount`, `app.task.queueSize`.

For Docker deployments these are surfaced as env vars (`DATABASE_USER`, `DATABASE_HOST`, `APP_TASK_MAXPARALLELCOUNT`, …) — see `docs/docker.md`. `docker/timaat-entrypoint.sh` writes the properties file from env on container start.

## Database

MySQL/MariaDB schema `FIPOP`, collation `utf8mb4_general_ci`.

- Fresh install: load `src/main/resources/database/fipop.sql`.
- Upgrade: apply `src/main/resources/database/db_update.sql` (it is idempotent across versioned blocks). Schema version lives in the `db_version` table; bump it for every schema change and document the change in `docs/database.md`.
- JPA persistence unit `FIPOP-JPA` is declared in `src/main/resources/META-INF/persistence.xml`. Every entity class in `de.bitgilde.TIMAAT.model.FIPOP` must be listed there — EclipseLink does not auto-discover. When adding an entity, add a `<class>` line.

## Architecture

### Request lifecycle

`de.bitgilde.TIMAAT.TIMAATApp` (`@ApplicationPath("timaatapp")`) is the Jersey `Application`. It explicitly enumerates resource and filter classes in `addRestResourceClasses` — new endpoints must be added there or they will 404. Filters in `rest/filter/` (`AuthenticationFilter`, `CORSFilter`, `RangeResponseFilter`) wrap every request; auth is JWT (jjwt) with Argon2 password hashing.

REST endpoints live in `de.bitgilde.TIMAAT.rest.endpoint.Endpoint*` (one class per domain area: Medium, Annotation, Analysis, Actor, Music, …). They delegate to storage components rather than holding business logic themselves.

### Dependency injection

Jersey HK2 is the DI container. All wiring lives in **one** place: `de.bitgilde.TIMAAT.di.binder.TIMAATBinder`. Singletons (file storages, engines, task service, the entity-storage layer) are bound there. When adding a new service or storage, register it in `TIMAATBinder.configure()` — endpoints get instances via `@Inject` only because of bindings here. Note the multi-contract bindings (e.g. `bind(DbTaskStorage.class).to(DbTaskStorage.class).to(TaskStorage.class).to(TaskStateUpdater.class)`) used so one implementation satisfies multiple registry lookups.

`TIMAATBinder` also constructs the `EntityManagerFactory` (it has to run before the persistence layer is touched) and exposes it as a binding.

### Storage layering

Three parallel storage concepts that are easy to confuse:

- `storage/entity/**` — DB-backed entity storage classes (`MediumStorage`, `AnnotationStorage`, `TranscriptionStorage`, …). These are the JPA access layer for the FIPOP entities.
- `storage/file/**` — filesystem storage for binary blobs (`VideoFileStorage`, `AudioFileStorage`, `ImageFileStorage`, `TranscriptionFileStorage`, `TemporaryFileStorage`). They write under `storage.location` with the layout documented in `docs/fs-storage.md` (per-medium subdirectories keyed by medium ID). When that layout changes, add a migration script under `src/main/resources/scripts/fs-migration/`.
- `db/` — low-level JDBC helpers (`DbAccessComponent`) used when JPA is too heavy.

The corresponding domain models are in `model/FIPOP/` (JPA entities, generated/maintained against the schema) and `rest/model/` (DTOs used over the wire).

### Async task framework (`service/task/`)

Long-running work (audio analysis, transcription preparation) goes through this framework rather than being run inline in a REST handler.

- `api/Task` + `TaskType` + concrete `Task` subclasses describe a unit of work.
- `storage/TaskStorageRegistry` and `storage/TaskStateUpdaterRegistry` route a task to the right persistence handler by its `TaskType`. To add a new task type: define `XxxTask`, register its `TaskStorage` and `TaskStateUpdater` bindings in `TIMAATBinder`, and register a corresponding `TaskExecutor` in `execution/TaskExecutorFactory`.
- `TaskService` is the entry point — it persists the task, then hands it to `TaskExecutorService`. On startup it resumes any tasks left in a non-terminal state.
- `TaskExecutorService` owns a thread pool sized by the `app.task.*` properties.

### Transcription (`service/transcription/`)

`TranscriptionService` orchestrates speech-to-text via the external `studio.nko-dev:speech-to-text-service-client-uni-erfurt` client. It plugs into the task framework as a `TaskStateUpdater` (see binding in `TIMAATBinder.java:87`). Transcription file output goes through `TranscriptionFileStorage`; DB rows are persisted via `TranscriptionStorage`.

### Media processing (`processing/`)

`processing/audio/FfmpegAudioEngine` and `processing/video/FfmpegVideoEngine` shell out to `ffmpeg` (path from `app.ffmpeg.location`). Audio analysis produces waveform + frequency files written via the binary readers/writers in `processing/audio/io/` — these are the only components with meaningful unit-test coverage today (`src/test/java/de/bitgilde/TIMAAT/audio/io/`).

### Realtime channels

- `notification/NotificationWebSocket` — WebSocket endpoint for user-targeted push notifications; subscriptions tracked in `UserSubscriptions`.
- `sse/EntityUpdateEventService` + `rest/endpoint/EndpointEntityUpdateEvents` — Server-Sent Events stream so the UI can react to entity changes from other sessions.

### Publication output (`publication/`)

Generates standalone publishable bundles from annotations using template files in `src/main/resources/*.template` (registered to the WAR by the war-plugin config in `pom.xml`). `PublicationAuthenticationFilter` + `PublicationServlet` serve the protected publication endpoints; they are added to the Jersey resource set alongside the REST endpoints.

## Frontend

`src/main/webapp/` is plain HTML/CSS/JS, no build step. JS is organized as RequireJS modules under `js/` with vendor libs vendored under `third-party/` (jQuery, Bootstrap, datatables, leaflet, wavesurferjs, dropzone, summernote, select2, …). The frontend talks to the backend over the `/timaatapp/*` REST API and the SSE + WebSocket channels above.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM tomcat:10.1.47-jre11-temurin-noble
FROM tomcat:10.1.47-jre25-temurin-noble
LABEL org.opencontainers.image.title="TIMAAT Web Application"
LABEL org.opencontainers.image.description="Java-based web application running on Tomcat, providing TIMAAT services."
LABEL org.opencontainers.image.version="${TIMAAT_VERSION}"
Expand Down
18 changes: 18 additions & 0 deletions docker/compose/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copy this file to ".env" (same directory as docker-compose-prod.yaml) and adjust.
# docker compose interpolates these values when constructing the stack.

# Public hostname the reverse proxy serves (used in the Traefik router rule).
TIMAAT_DOMAIN=timaat.example.org

# Host path of the Docker socket Traefik reads container labels from.
# Native Linux daemon: leave unset (defaults to /var/run/docker.sock).
# Docker Desktop (macOS/Windows): point to the per-user socket, e.g.
# DOCKER_SOCKET=/Users/<you>/.docker/run/docker.sock
DOCKER_SOCKET=/var/run/docker.sock

# Host directory that contains the externally provided TLS certificate + key.
# It is bind-mounted read-only into the reverse-proxy container at /certs.
# Expected files inside this directory (rename in traefik/dynamic/tls.yaml if different):
# - timaat.crt (full certificate chain, PEM)
# - timaat.key (private key, PEM)
TIMAAT_TLS_CERT_DIR=/etc/ssl/timaat
104 changes: 104 additions & 0 deletions docker/compose/docker-compose-prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: timaat
services:
db:
image: mariadb:11.4
ports:
- "3306:3306"
networks:
- timaat-backend
command: --lower_case_table_names=1
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/database-root-password
volumes:
- db-data:/var/lib/mysql
secrets:
- database-root-password
healthcheck:
test: [ "CMD-SHELL", "mariadb-admin ping -u root --password=$(cat /run/secrets/database-root-password)" ]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
webservice:
image: christophguentherunierfurt/timaat:latest
pull_policy: always
networks:
- timaat-backend
# No host port binding anymore - the webservice is only reachable through the
# Traefik reverse proxy on the internal timaat-backend network.
expose:
- "8080"
environment:
DATABASE_USER: root
DATABASE_PASSWORD_FILE: /run/secrets/database-root-password
DATABASE_HOST: db
DATABASE_PORT: 3306
volumes:
- file-storage:/var/lib/timaat/storage
secrets:
- database-root-password
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
# Route incoming HTTPS traffic for the configured host to this service.
- "traefik.http.routers.timaat.rule=Host(`${TIMAAT_DOMAIN}`)"
- "traefik.http.routers.timaat.entrypoints=websecure"
- "traefik.http.routers.timaat.tls=true"
# Forward to the container's internal HTTP port 8080.
- "traefik.http.services.timaat.loadbalancer.server.port=8080"
- "traefik.http.routers.timaat.middlewares=owasp-secure-headers@file"
# Redirect requests to the host root ("/") to the application context
# path ("/TIMAAT/"). The more specific Path(`/`) rule wins over the bare
# Host rule above by Traefik's automatic priority (longer rule = higher).
- "traefik.http.routers.timaat-root.rule=Host(`${TIMAAT_DOMAIN}`) && Path(`/`)"
- "traefik.http.routers.timaat-root.entrypoints=websecure"
- "traefik.http.routers.timaat-root.tls=true"
- "traefik.http.routers.timaat-root.service=timaat"
- "traefik.http.routers.timaat-root.middlewares=redirect-root-to-timaat@file"
reverse-proxy:
image: traefik:v3.7.1
networks:
- timaat-backend
ports:
# Only HTTPS is exposed to the host; the proxy listens on 443 internally
# and is published on the host's port 443.
- "443:443"
command:
# Do NOT expose the API/dashboard.
- "--api.dashboard=false"
- "--api.insecure=false"
# Single HTTPS entrypoint on port 443.
- "--entrypoints.websecure.address=:443"
# Docker provider: read router/service/middleware definitions from labels,
# but only for containers that explicitly opt in (traefik.enable=true).
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=timaat-backend"
# File provider: TLS certificate material is configured via a mounted
# dynamic configuration file.
- "--providers.file.directory=/etc/traefik/dynamic"
- "--providers.file.watch=true"
# Keep logs lean and do not advertise version information anywhere.
- "--log.level=INFO"
- "--accesslog=false"
volumes:
- "${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro"
# Dynamic TLS configuration (references the certificate paths inside the container).
- ./traefik/dynamic:/etc/traefik/dynamic:ro
# Externally provided certificate + key, mounted from a host path supplied
# via the TIMAAT_TLS_CERT_DIR variable (see .env.example).
- "${TIMAAT_TLS_CERT_DIR}:/certs:ro"
depends_on:
- webservice
networks:
timaat-backend:
driver: bridge
attachable: false
volumes:
db-data:
file-storage:
secrets:
database-root-password:
file: passwords/database-root-password.txt
37 changes: 37 additions & 0 deletions docker/compose/traefik/dynamic/middlewares.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Traefik dynamic configuration: HTTP middlewares.
#
# OWASP recommended secure response headers.
# https://github.com/OWASP/www-project-secure-headers/blob/master/ci/headers_add.json
#
# Referenced from the webservice router as "owasp-secure-headers@file".
http:
middlewares:
owasp-secure-headers:
headers:
customResponseHeaders:
Cache-Control: "no-store, max-age=0"
Clear-Site-Data: "\"cache\",\"cookies\",\"storage\""
# 'unsafe-inline' on script-src/style-src is required because the app
# ships inline <script>/<style> blocks and style="..." attributes.
# Prefer migrating to nonces/hashes later to drop 'unsafe-inline'.
Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests"
Cross-Origin-Embedder-Policy: "require-corp"
Cross-Origin-Opener-Policy: "same-origin"
Cross-Origin-Resource-Policy: "same-origin"
Permissions-Policy: "accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), unload=()"
Referrer-Policy: "no-referrer"
Strict-Transport-Security: "max-age=63072000; includeSubDomains"
X-Content-Type-Options: "nosniff"
X-DNS-Prefetch-Control: "off"
X-Frame-Options: "deny"
X-Permitted-Cross-Domain-Policies: "none"
# Strip server-identifying headers (empty value removes the header).
Server: ""
X-Powered-By: ""
# Redirect the host root ("/") to the application context path ("/TIMAAT/").
# Referenced from the timaat-root router as "redirect-root-to-timaat@file".
redirect-root-to-timaat:
redirectRegex:
regex: "^https?://([^/]+)/?$"
replacement: "https://${1}/TIMAAT/"
permanent: true
15 changes: 15 additions & 0 deletions docker/compose/traefik/dynamic/tls.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Traefik dynamic configuration: TLS certificate material.
#
# The certificate and key are provided EXTERNALLY. The host directory that
# contains them is mounted into the reverse-proxy container at /certs via the
# TIMAAT_TLS_CERT_DIR variable (see docker-compose-prod.yaml / .env.example).
# Adjust the file names below if your certificate/key are named differently.
tls:
stores:
default:
defaultCertificate:
certFile: /certs/timaat.crt
keyFile: /certs/timaat.key
certificates:
- certFile: /certs/timaat.crt
keyFile: /certs/timaat.key
4 changes: 1 addition & 3 deletions docker/timaat-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ for var in "${required_vars[@]}"; do
fi
done
echo "Verify database and create or upgrade schema (if necessary)"
if [ "$(mysql -u"${DATABASE_USER}" -p"${DATABASE_PASSWORD}" -h"${DATABASE_HOST}" -P"${DATABASE_PORT}" -N -s -e \
"SELECT COUNT(*) FROM information_schema.tables WHERE \
table_schema='${DATABASE_SCHEMA_NAME}' AND table_name='db_version';")" -eq 1 ]; then
if [ "$(mysql -u"${DATABASE_USER}" -p"${DATABASE_PASSWORD}" -h"${DATABASE_HOST}" -P"${DATABASE_PORT}" -N -s -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DATABASE_SCHEMA_NAME}' AND table_name='db_version';")" -eq 1 ]; then
echo "Database schema already exists. Executing schema update when necessary."
mysql -u"${DATABASE_USER}" -p"${DATABASE_PASSWORD}" -h"${DATABASE_HOST}" -P"${DATABASE_PORT}" ${DATABASE_SCHEMA_NAME} < /var/lib/timmat/sql/db_update.sql
else
Expand Down
Loading
Loading