diff --git a/db.sh b/db.sh new file mode 100755 index 0000000..ca2c6f5 --- /dev/null +++ b/db.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# db.sh - Manage database containers + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +usage() { + echo "Usage: $0 [--clean] [--users]" + echo "" + echo "Options:" + echo " mysql|mssql Which database to start" + echo " --clean Delete volumes and start fresh" + echo " --users Only import test users (database must be running)" + exit 1 +} + +# Parse parameters +DB="" +CLEAN=false +USERS_ONLY=false + +for arg in "$@"; do + case $arg in + mysql|mssql) + DB=$arg + ;; + --clean) + CLEAN=true + ;; + --users) + USERS_ONLY=true + ;; + *) + usage + ;; + esac +done + +[ -z "$DB" ] && usage + +# Import users only +if [ "$USERS_ONLY" = true ]; then + if [ "$DB" = "mysql" ]; then + echo "==> Importing users into MySQL..." + DB_USER=$(grep SPRING_DATASOURCE_USERNAME .env | cut -d= -f2) + DB_PASS=$(grep SPRING_DATASOURCE_PASSWORD .env | cut -d= -f2) + podman exec -i lcc-mysql-local mysql -u"${DB_USER}" -p"${DB_PASS}" lcc \ + < src/test/resources/master_data/users.sql + echo "==> Users imported!" +elif [ "$DB" = "mssql" ]; then + echo "==> Importing users into MSSQL..." + DB_PASS=$(grep DB_ROOT_PASSWORD .env.mssql | cut -d= -f2) + podman exec -e "SQLCMDPASSWORD=${DB_PASS}" lcc-mssql-local /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U sa -d lcc -C \ + -i /dev/stdin < src/test/resources/master_data/users_mssql.sql + echo "==> Users imported!" +fi + exit 0 +fi + +echo "==> Stopping all DB containers..." +podman-compose --profile mssql down 2>/dev/null || true + +if [ "$CLEAN" = true ]; then + echo "==> Deleting volumes..." + podman volume rm lcc_tool_mysql-data-local 2>/dev/null || true + podman volume rm lcc_tool_mssql-data-local 2>/dev/null || true +fi + +echo "==> Linking .env -> .env.$DB" +rm -f .env +ln -s .env.$DB .env + +# Check if volume exists (for init decision) +VOLUME_EXISTS=false +if [ "$DB" = "mysql" ]; then + podman volume exists lcc_tool_mysql-data-local 2>/dev/null && VOLUME_EXISTS=true +elif [ "$DB" = "mssql" ]; then + podman volume exists lcc_tool_mssql-data-local 2>/dev/null && VOLUME_EXISTS=true +fi + +echo "==> Starting $DB..." +if [ "$DB" = "mysql" ]; then + podman-compose up -d mysql + + echo "==> Waiting for MySQL..." + until podman exec lcc-mysql-local mysqladmin ping -h localhost --silent 2>/dev/null; do + sleep 2 + done + echo "==> MySQL is ready!" + +elif [ "$DB" = "mssql" ]; then + podman-compose --profile mssql up -d mssql + + echo "==> Waiting for MSSQL..." + until [ "$(podman inspect -f '{{.State.Health.Status}}' lcc-mssql-local 2>/dev/null)" = "healthy" ]; do + sleep 2 + done + echo "==> MSSQL is ready!" + + if [ "$VOLUME_EXISTS" = false ]; then + echo "==> New volume detected, creating database..." + DB_PASS=$(grep DB_ROOT_PASSWORD .env | cut -d= -f2) + podman exec lcc-mssql-local /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U sa -P "${DB_PASS}" -C \ + -Q "IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'lcc') CREATE DATABASE lcc" + echo "==> Database 'lcc' created!" + fi +fi + +echo "==> Done! .env points to .env.$DB" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index bfdf50c..22f72bf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,11 +28,10 @@ services: container_name: lcc-mssql-local environment: ACCEPT_EULA: "Y" - MSSQL_SA_PASSWORD: ${DB_ROOT_PASSWORD:-YourStrong@Passw0rd123} + MSSQL_SA_PASSWORD: ${DB_ROOT_PASSWORD} MSSQL_PID: "Developer" volumes: - mssql-data-local:/var/opt/mssql - - ./docker/mssql-init.sql:/docker-init/mssql-init.sql:ro ports: - "1433:1433" networks: @@ -47,30 +46,6 @@ services: profiles: - mssql # Startet nur mit: docker-compose --profile mssql up - # MSSQL Init (führt Init-Skript aus) - mssql-init: - image: mcr.microsoft.com/mssql/server:2022-latest - container_name: lcc-mssql-init - depends_on: - mssql: - condition: service_healthy - environment: - MSSQL_SA_PASSWORD: ${DB_ROOT_PASSWORD:-YourStrong@Passw0rd123} - volumes: - - ./docker/mssql-init.sql:/init.sql:ro - command: > - /bin/bash -c " - echo 'Waiting for MSSQL to be ready...' && - sleep 5 && - echo 'Running initialization script...' && - /opt/mssql-tools18/bin/sqlcmd -S mssql -U sa -P \"$$MSSQL_SA_PASSWORD\" -i /init.sql -C && - echo 'Database initialization complete!' || echo 'Initialization failed or database already exists' - " - networks: - - lcc-network-local - profiles: - - mssql - lcc-app: #image: git.avatic.de/avatic/lcc:latest # Oder für lokales Bauen: diff --git a/docker/mssql-entrypoint.sh b/docker/mssql-entrypoint.sh deleted file mode 100644 index a871b7d..0000000 --- a/docker/mssql-entrypoint.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# Wait for SQL Server to start -echo "Waiting for SQL Server to start..." -sleep 30s - -# Run the initialization script -echo "Running initialization script..." -/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -i /docker-init/mssql-init.sql -C - -echo "Initialization complete!" diff --git a/docker/mssql-init.sql b/docker/mssql-init.sql deleted file mode 100644 index 39005ec..0000000 --- a/docker/mssql-init.sql +++ /dev/null @@ -1,25 +0,0 @@ --- MSSQL Database Initialization Script --- This script runs automatically when the container starts - -IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'lcc') -BEGIN - CREATE DATABASE lcc; - PRINT 'Database lcc created successfully'; -END -ELSE -BEGIN - PRINT 'Database lcc already exists'; -END -GO - -USE lcc; -GO - --- Optional: Create login/user if needed (for non-sa access) --- IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'lcc_user') --- BEGIN --- CREATE LOGIN lcc_user WITH PASSWORD = 'YourStrong@Passw0rd123'; --- CREATE USER lcc_user FOR LOGIN lcc_user; --- ALTER ROLE db_owner ADD MEMBER lcc_user; --- END --- GO diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index e7552ea..218eac1 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -10,7 +10,6 @@ "dependencies": { "@phosphor-icons/vue": "^2.2.1", "@vueuse/core": "^13.6.0", - "azure-maps-control": "^3.6.1", "chart.js": "^4.5.0", "leaflet": "^1.9.4", "loglevel": "^1.9.2", @@ -43,27 +42,6 @@ "node": ">=6.0.0" } }, - "node_modules/@azure/msal-browser": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.39.0.tgz", - "integrity": "sha512-kks/n2AJzKUk+DBqZhiD+7zeQGBl+WpSOQYzWy6hff3bU0ZrYFqr4keFLlzB5VKuKZog0X59/FGHb1RPBDZLVg==", - "license": "MIT", - "dependencies": { - "@azure/msal-common": "13.3.3" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@azure/msal-common": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.3.tgz", - "integrity": "sha512-n278DdCXKeiWhLwhEL7/u9HRMyzhUXLefeajiknf6AmEedoiOiv2r5aRJ7LXdT3NGPyubkdIbthaJlVtmuEqvA==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -95,7 +73,6 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -980,46 +957,6 @@ "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", "license": "MIT" }, - "node_modules/@mapbox/jsonlint-lines-primitives": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", - "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mapbox/mapbox-gl-supported": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz", - "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@mapbox/unitbezier": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", - "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", - "license": "BSD-2-Clause" - }, - "node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.4.0.tgz", - "integrity": "sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw==", - "license": "ISC", - "dependencies": { - "@mapbox/jsonlint-lines-primitives": "~2.0.2", - "@mapbox/unitbezier": "^0.0.1", - "json-stringify-pretty-compact": "^4.0.0", - "minimist": "^1.2.8", - "quickselect": "^2.0.0", - "rw": "^1.3.3", - "tinyqueue": "^3.0.0" - }, - "bin": { - "gl-style-format": "dist/gl-style-format.mjs", - "gl-style-migrate": "dist/gl-style-migrate.mjs", - "gl-style-validate": "dist/gl-style-validate.mjs" - } - }, "node_modules/@phosphor-icons/vue": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@phosphor-icons/vue/-/vue-2.2.1.tgz", @@ -1345,12 +1282,6 @@ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", - "license": "MIT" - }, "node_modules/@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", @@ -1696,18 +1627,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/azure-maps-control": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/azure-maps-control/-/azure-maps-control-3.6.1.tgz", - "integrity": "sha512-EqJ96GOjUcCG9XizUbyqDu92x3KKT9C9AwRL3hmPicQjn00ql7em6RbBqJYO4nvIoH53DG6MOITj9t/zv1mQYg==", - "license": "SEE LICENSE.TXT", - "dependencies": { - "@azure/msal-browser": "^2.32.1", - "@mapbox/mapbox-gl-supported": "^2.0.1", - "@maplibre/maplibre-gl-style-spec": "^20.0.0", - "@types/geojson": "^7946.0.14" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1761,7 +1680,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -1817,7 +1735,6 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", "license": "MIT", - "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -2371,12 +2288,6 @@ "node": ">=6" } }, - "node_modules/json-stringify-pretty-compact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", - "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", - "license": "MIT" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -2447,15 +2358,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -2700,12 +2602,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/quickselect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", - "license": "ISC" - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2789,12 +2685,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", - "license": "BSD-3-Clause" - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -2915,12 +2805,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyqueue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", - "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", - "license": "ISC" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3018,7 +2902,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz", "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -3250,7 +3133,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.21", "@vue/compiler-sfc": "3.5.21", diff --git a/src/frontend/vite.config.js b/src/frontend/vite.config.js index 8a25c07..48a561e 100644 --- a/src/frontend/vite.config.js +++ b/src/frontend/vite.config.js @@ -35,6 +35,7 @@ export default defineConfig({ }, }, server: { + host: true, proxy: { '/api': { target: 'http://localhost:8080', @@ -48,4 +49,4 @@ export default defineConfig({ } } } -}) \ No newline at end of file +})