Auth: Add HTTPS Reverse Proxy & Keycloak for OpenID Connect tests #782
This commit is contained in:
parent
55bee9871f
commit
dd578b7142
27 changed files with 3093 additions and 149 deletions
13
Makefile
13
Makefile
|
@ -26,9 +26,9 @@ dep: dep-tensorflow dep-js dep-go
|
|||
build: generate build-js build-go
|
||||
install: install-bin install-assets
|
||||
test: test-js test-go
|
||||
test-go: reset-test-databases run-test-go
|
||||
test-api: reset-test-databases run-test-api
|
||||
test-short: reset-test-databases run-test-short
|
||||
test-go: reset-testdb run-test-go
|
||||
test-api: reset-testdb run-test-api
|
||||
test-short: reset-testdb run-test-short
|
||||
acceptance-private-run-chromium: acceptance-private-restart acceptance-private acceptance-private-stop
|
||||
acceptance-public-run-chromium: acceptance-restart acceptance acceptance-stop
|
||||
acceptance-private-run-firefox: acceptance-private-restart acceptance-private-firefox acceptance-private-stop
|
||||
|
@ -161,9 +161,8 @@ acceptance-private-firefox:
|
|||
reset-mariadb:
|
||||
$(info Resetting photoprism database...)
|
||||
mysql < scripts/sql/reset-mariadb.sql
|
||||
reset-test-databases:
|
||||
$(info Resetting test databases...)
|
||||
mysql < scripts/sql/init-test-databases.sql
|
||||
reset-testdb:
|
||||
$(info Removing test database files...)
|
||||
find ./internal -type f -name '.test.*' -delete
|
||||
run-test-short:
|
||||
$(info Running short Go unit tests in parallel mode...)
|
||||
|
@ -242,4 +241,4 @@ fmt-go:
|
|||
go fmt ./pkg/... ./internal/... ./cmd/...
|
||||
goimports -w pkg internal cmd
|
||||
tidy:
|
||||
go mod tidy
|
||||
go mod tidy
|
|
@ -1,6 +1,6 @@
|
|||
version: '3.5'
|
||||
|
||||
## Legacy Databases Servers (for developers only)
|
||||
## Legacy Database Servers for Development & Testing
|
||||
services:
|
||||
## MariaDB 10.5.5 Database Server
|
||||
## affected by MDEV-25362: Incorrect name resolution for subqueries in ON expressions
|
||||
|
@ -11,7 +11,7 @@ services:
|
|||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
|
@ -25,7 +25,7 @@ services:
|
|||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
|
@ -39,7 +39,7 @@ services:
|
|||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
|
@ -53,7 +53,7 @@ services:
|
|||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
|
@ -67,7 +67,7 @@ services:
|
|||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
version: '3.5'
|
||||
|
||||
## Continuous integration environment (for Drone CI)
|
||||
## Integration Environment for Drone CI
|
||||
services:
|
||||
## App Server
|
||||
## App Dev Container
|
||||
## Docs: https://docs.photoprism.org/developer-guide/
|
||||
photoprism:
|
||||
build: .
|
||||
image: photoprism/photoprism:develop
|
||||
|
@ -142,23 +143,24 @@ services:
|
|||
DRONE_TARGET_BRANCH:
|
||||
|
||||
## MariaDB Database Server
|
||||
## Docs: https://mariadb.com/docs/reference/cs10.6/
|
||||
mariadb:
|
||||
image: mariadb:10.6
|
||||
command: mysqld --port=4001 --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
|
||||
expose:
|
||||
- "4001" # Database port (internal)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
MYSQL_PASSWORD: photoprism
|
||||
MYSQL_DATABASE: photoprism
|
||||
|
||||
## Dummy WebDAV Server (for testing)
|
||||
## Dummy WebDAV Server
|
||||
dummy-webdav:
|
||||
image: photoprism/dummy-webdav:20211022
|
||||
|
||||
## Dummy OpenID Connect Server (for testing)
|
||||
## Dummy OpenID Connect Server
|
||||
dummy-oidc:
|
||||
image: photoprism/dummy-oidc:20211022
|
|
@ -1,8 +1,9 @@
|
|||
version: '3.5'
|
||||
|
||||
## Stable Release (for testing only)
|
||||
## Latest Stable Release for QA
|
||||
services:
|
||||
## App Server
|
||||
## Docs: https://docs.photoprism.org/
|
||||
photoprism-latest:
|
||||
image: photoprism/photoprism:latest
|
||||
security_opt:
|
||||
|
@ -10,10 +11,20 @@ services:
|
|||
- apparmor:unconfined
|
||||
ports:
|
||||
- "2344:2342" # HTTP port (host:container)
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.photoprism-latest.loadbalancer.server.port=2342"
|
||||
- "traefik.http.routers.photoprism-latest.entrypoints=websecure"
|
||||
- "traefik.http.routers.photoprism-latest.rule=Host(`photoprism-latest.reverseproxy.dev`)"
|
||||
- "traefik.http.routers.photoprism-latest.tls.domains[0].main=reverseproxy.dev"
|
||||
- "traefik.http.routers.photoprism-latest.tls.domains[0].sans=*.reverseproxy.dev"
|
||||
- "traefik.http.routers.photoprism-latest.tls=true"
|
||||
environment:
|
||||
PHOTOPRISM_UID: ${UID:-1000}
|
||||
PHOTOPRISM_GID: ${GID:-1000}
|
||||
PHOTOPRISM_SITE_URL: "http://localhost:2344/"
|
||||
PHOTOPRISM_UID: ${UID:-1000} # User ID
|
||||
PHOTOPRISM_GID: ${GID:-1000} # Group ID
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # Admin password (min 4 characters)
|
||||
## Public server URL incl http:// or https:// and /path, :port is optional
|
||||
PHOTOPRISM_SITE_URL: "https://photoprism-latest.reverseproxy.dev/"
|
||||
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
|
||||
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
|
||||
PHOTOPRISM_SITE_DESCRIPTION: "Open-Source Photo Management"
|
||||
|
@ -28,10 +39,9 @@ services:
|
|||
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
|
||||
PHOTOPRISM_DATABASE_DRIVER: "mysql"
|
||||
PHOTOPRISM_DATABASE_SERVER: "mariadb:4001"
|
||||
PHOTOPRISM_DATABASE_NAME: "latest"
|
||||
PHOTOPRISM_DATABASE_USER: "root"
|
||||
PHOTOPRISM_DATABASE_PASSWORD: "photoprism"
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # The initial admin password (min 4 characters)
|
||||
PHOTOPRISM_DATABASE_NAME: "photoprism_latest"
|
||||
PHOTOPRISM_DATABASE_USER: "photoprism_latest"
|
||||
PHOTOPRISM_DATABASE_PASSWORD: "photoprism_latest"
|
||||
PHOTOPRISM_DISABLE_CHOWN: "false" # Disables storage permission updates on startup
|
||||
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
|
||||
PHOTOPRISM_DISABLE_WEBDAV: "false" # Disables built-in WebDAV server
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
version: '3.5'
|
||||
|
||||
## For developers only! PostgreSQL is NOT supported yet as Gorm (the ORM library) needs to be
|
||||
## upgraded first. The current version does NOT support compatible general data types:
|
||||
## https://github.com/photoprism/photoprism/issues/47
|
||||
# ATTENTION: PostgreSQL is NOT supported yet as Gorm (our ORM library) needs to be upgraded first.
|
||||
# The current Gorm version does NOT support compatible general data types:
|
||||
# https://github.com/photoprism/photoprism/issues/47
|
||||
|
||||
## Development Environment with
|
||||
## - App Dev Container
|
||||
## - PostgreSQL Database Server
|
||||
## - and Dummy Services
|
||||
services:
|
||||
## App Server
|
||||
## App Dev Container
|
||||
## Docs: https://docs.photoprism.org/developer-guide/
|
||||
photoprism:
|
||||
build: .
|
||||
image: photoprism/photoprism:develop
|
||||
|
@ -23,7 +29,10 @@ services:
|
|||
- "go-mod:/go/pkg/mod"
|
||||
shm_size: "2gb"
|
||||
environment:
|
||||
PHOTOPRISM_SITE_URL: "http://localhost:2342/"
|
||||
PHOTOPRISM_UID: ${UID:-1000} # User ID
|
||||
PHOTOPRISM_GID: ${GID:-1000} # Group ID
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # Admin password (min 4 characters)
|
||||
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public server URL incl http:// or https:// and /path, :port is option
|
||||
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
|
||||
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
|
||||
PHOTOPRISM_SITE_DESCRIPTION: "Open-Source Photo Management"
|
||||
|
@ -43,7 +52,6 @@ services:
|
|||
PHOTOPRISM_DATABASE_PASSWORD: "photoprism"
|
||||
PHOTOPRISM_TEST_DRIVER: "sqlite"
|
||||
PHOTOPRISM_TEST_DSN: ".test.db"
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # The initial admin password (min 4 characters)
|
||||
PHOTOPRISM_ASSETS_PATH: "/go/src/github.com/photoprism/photoprism/assets"
|
||||
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
|
||||
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
|
||||
|
@ -67,6 +75,7 @@ services:
|
|||
TF_CPP_MIN_LOG_LEVEL: 0 # Show TensorFlow log messages for development
|
||||
|
||||
## PostgreSQL Database Server
|
||||
## Docs: https://www.postgresql.org/docs/
|
||||
postgres:
|
||||
image: postgres:12-alpine
|
||||
ports:
|
||||
|
@ -76,11 +85,11 @@ services:
|
|||
POSTGRES_USER: photoprism
|
||||
POSTGRES_PASSWORD: photoprism
|
||||
|
||||
## Dummy WebDAV Server (for testing)
|
||||
## Dummy WebDAV Server
|
||||
dummy-webdav:
|
||||
image: photoprism/dummy-webdav:20211022
|
||||
|
||||
## Dummy OpenID Connect Server (for testing)
|
||||
## Dummy OpenID Connect Server
|
||||
dummy-oidc:
|
||||
image: photoprism/dummy-oidc:20211022
|
||||
# Expose port 9998 on host
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
version: '3.5'
|
||||
|
||||
## HTTP / HTTPS Reverse Proxy Servers (for developers only)
|
||||
services:
|
||||
## Caddy 2
|
||||
caddy:
|
||||
image: caddy:2
|
||||
depends_on:
|
||||
- photoprism
|
||||
ports:
|
||||
- "80:80" # HTTP port (host:container)
|
||||
- "443:443" # HTTPS port (host:container)
|
||||
volumes:
|
||||
- ./docker/development/caddy:/data/caddy/pki/authorities/local
|
||||
- ./docker/development/caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
|
||||
## Join shared network
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: shared
|
|
@ -1,8 +1,24 @@
|
|||
version: '3.5'
|
||||
|
||||
## Development environment with app server, database, and dummy services (for developers only)
|
||||
## Development Environment with
|
||||
## - HTTPS Reverse Proxy
|
||||
## - App Dev Container
|
||||
## - MariaDB Database Server
|
||||
## - Keycloak OpenID Connect Provider
|
||||
## - and Dummy Services
|
||||
services:
|
||||
## App Server
|
||||
## Traefik 2.5 HTTPS Reverse Proxy (https://*.reverseproxy.dev/)
|
||||
## Docs: https://doc.traefik.io/traefik/
|
||||
traefik:
|
||||
image: photoprism/traefik:20211102
|
||||
ports:
|
||||
# - "80:80" # HTTP (redirects to HTTPS)
|
||||
- "443:443" # HTTPS (required)
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock" # Host names are configured with Docker labels
|
||||
|
||||
## App Dev Container
|
||||
## Docs: https://docs.photoprism.org/developer-guide/
|
||||
photoprism:
|
||||
build: .
|
||||
image: photoprism/photoprism:develop
|
||||
|
@ -17,10 +33,25 @@ services:
|
|||
- "2343:2343" # Acceptance Test HTTP port (host:container)
|
||||
- "40000:40000" # Go Debugger (host:container)
|
||||
shm_size: "2gb"
|
||||
links:
|
||||
- "traefik:keycloak.reverseproxy.dev"
|
||||
- "traefik:photoprism.reverseproxy.dev"
|
||||
- "traefik:dummy-webdav.reverseproxy.dev"
|
||||
- "traefik:dummy-oidc.reverseproxy.dev"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.photoprism.loadbalancer.server.port=2342"
|
||||
- "traefik.http.routers.photoprism.entrypoints=websecure"
|
||||
- "traefik.http.routers.photoprism.rule=Host(`photoprism.reverseproxy.dev`)"
|
||||
- "traefik.http.routers.photoprism.tls.domains[0].main=reverseproxy.dev"
|
||||
- "traefik.http.routers.photoprism.tls.domains[0].sans=*.reverseproxy.dev"
|
||||
- "traefik.http.routers.photoprism.tls=true"
|
||||
environment:
|
||||
PHOTOPRISM_UID: ${UID:-1000}
|
||||
PHOTOPRISM_GID: ${GID:-1000}
|
||||
PHOTOPRISM_SITE_URL: "http://localhost:2342/"
|
||||
PHOTOPRISM_UID: ${UID:-1000} # User ID
|
||||
PHOTOPRISM_GID: ${GID:-1000} # Group ID
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # Admin password (min 4 characters)
|
||||
## External development server URL incl http:// or https:// and /path, :port is optional
|
||||
PHOTOPRISM_SITE_URL: "https://photoprism.reverseproxy.dev/"
|
||||
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
|
||||
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
|
||||
PHOTOPRISM_SITE_DESCRIPTION: "Open-Source Photo Management"
|
||||
|
@ -40,7 +71,6 @@ services:
|
|||
PHOTOPRISM_DATABASE_PASSWORD: "photoprism"
|
||||
PHOTOPRISM_TEST_DRIVER: "sqlite"
|
||||
PHOTOPRISM_TEST_DSN: ".test.db"
|
||||
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # The initial admin password (min 4 characters)
|
||||
PHOTOPRISM_ASSETS_PATH: "/go/src/github.com/photoprism/photoprism/assets"
|
||||
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
|
||||
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
|
||||
|
@ -62,13 +92,11 @@ services:
|
|||
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
|
||||
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
|
||||
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
|
||||
PHOTOPRISM_OIDC_ISSUER: "https://keycloak.timovolkmann.de/auth/realms/master"
|
||||
PHOTOPRISM_OIDC_CLIENT_ID: "photoprism-dev"
|
||||
PHOTOPRISM_OIDC_CLIENT_SECRET: "9d8351a0-ca01-4556-9c37-85eb634869b9"
|
||||
# PHOTOPRISM_OIDC_ISSUER: "https://accounts.google.com"
|
||||
# PHOTOPRISM_OIDC_CLIENT_ID: "86720117204-mb09c300nas5r9rid1ad0omv67nlvhck.apps.googleusercontent.com"
|
||||
# PHOTOPRISM_OIDC_CLIENT_SECRET: "WQ2-LdfhYhHd-BdpfZCYGE12"
|
||||
TF_CPP_MIN_LOG_LEVEL: 0 # Show TensorFlow log messages for development
|
||||
## OpenID Connect Provider (pre-configured for local Keycloak test server):
|
||||
PHOTOPRISM_OIDC_ISSUER_URL: "https://keycloak.reverseproxy.dev/auth/realms/master"
|
||||
PHOTOPRISM_OIDC_CLIENT_ID: "photoprism-development"
|
||||
PHOTOPRISM_OIDC_CLIENT_SECRET: "9d8351a0-ca01-4556-9c37-85eb634869b9"
|
||||
## Enable TensorFlow AVX2 support for modern Intel CPUs (requires starting the container as root):
|
||||
# PHOTOPRISM_INIT: "tensorflow-amd64-avx2"
|
||||
## Hardware video transcoding config (optional):
|
||||
|
@ -89,6 +117,7 @@ services:
|
|||
- "go-mod:/go/pkg/mod"
|
||||
|
||||
## MariaDB Database Server
|
||||
## Docs: https://mariadb.com/docs/reference/cs10.6/
|
||||
mariadb:
|
||||
image: mariadb:10.6
|
||||
command: mysqld --port=4001 --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
|
||||
|
@ -97,30 +126,67 @@ services:
|
|||
ports:
|
||||
- "4001:4001" # Database port (host:container)
|
||||
volumes:
|
||||
- "./scripts/sql/init-test-databases.sql:/docker-entrypoint-initdb.d/init-test-databases.sql"
|
||||
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
MYSQL_PASSWORD: photoprism
|
||||
MYSQL_DATABASE: photoprism
|
||||
|
||||
## Dummy WebDAV Server (for testing)
|
||||
## Keycloak OpenID Connect Provider
|
||||
## Docs: https://www.keycloak.org/getting-started/getting-started-docker
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:15.0.2
|
||||
links:
|
||||
- "traefik:photoprism.reverseproxy.dev"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.keycloak.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.keycloak.entrypoints=websecure"
|
||||
- "traefik.http.routers.keycloak.rule=Host(`keycloak.reverseproxy.dev`)"
|
||||
- "traefik.http.routers.keycloak.tls.domains[0].main=reverseproxy.dev"
|
||||
- "traefik.http.routers.keycloak.tls.domains[0].sans=*.reverseproxy.dev"
|
||||
- "traefik.http.routers.keycloak.tls=true"
|
||||
environment:
|
||||
KEYCLOAK_USER: "admin"
|
||||
KEYCLOAK_PASSWORD: "photoprism"
|
||||
KEYCLOAK_FRONTEND_URL: "https://keycloak.reverseproxy.dev/auth"
|
||||
DB_VENDOR: "mariadb"
|
||||
DB_PORT: 4001
|
||||
DB_DATABASE: "keycloak"
|
||||
DB_USER: "keycloak"
|
||||
DB_PASSWORD: "keycloak"
|
||||
|
||||
## Dummy WebDAV Server
|
||||
dummy-webdav:
|
||||
image: photoprism/dummy-webdav:20211022
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.dummy-webdav.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.dummy-webdav.entrypoints=websecure"
|
||||
- "traefik.http.routers.dummy-webdav.rule=Host(`dummy-webdav.reverseproxy.dev`)"
|
||||
- "traefik.http.routers.dummy-webdav.tls.domains[0].main=reverseproxy.dev"
|
||||
- "traefik.http.routers.dummy-webdav.tls.domains[0].sans=*.reverseproxy.dev"
|
||||
- "traefik.http.routers.dummy-webdav.tls=true"
|
||||
|
||||
## Dummy OpenID Connect Server (for testing)
|
||||
## Dummy OpenID Connect Server
|
||||
dummy-oidc:
|
||||
image: photoprism/dummy-oidc:20211022
|
||||
# Expose port 9998 on host
|
||||
# ports:
|
||||
# - "9998:9998"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.dummy-oidc.loadbalancer.server.port=9998"
|
||||
- "traefik.http.routers.dummy-oidc.entrypoints=websecure"
|
||||
- "traefik.http.routers.dummy-oidc.rule=Host(`dummy-oidc.reverseproxy.dev`)"
|
||||
- "traefik.http.routers.dummy-oidc.tls.domains[0].main=reverseproxy.dev"
|
||||
- "traefik.http.routers.dummy-oidc.tls.domains[0].sans=*.reverseproxy.dev"
|
||||
- "traefik.http.routers.dummy-oidc.tls=true"
|
||||
|
||||
## Create named volumes
|
||||
## Create named volume for Go module cache.
|
||||
volumes:
|
||||
go-mod:
|
||||
driver: local
|
||||
|
||||
## Create shared network
|
||||
## Create shared network for connecting with services in other docker-compose.yml files.
|
||||
networks:
|
||||
default:
|
||||
name: shared
|
||||
|
|
2
docker/development/caddy/.gitignore
vendored
2
docker/development/caddy/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*.crt
|
||||
*.key
|
|
@ -1,3 +0,0 @@
|
|||
*, localhost {
|
||||
reverse_proxy photoprism:2342
|
||||
}
|
71
docker/development/keycloak/client.json
Normal file
71
docker/development/keycloak/client.json
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"clientId": "photoprism-development",
|
||||
"secret": "9d8351a0-ca01-4556-9c37-85eb634869b9",
|
||||
"name": "PhotoPrism",
|
||||
"rootUrl": "https://photoprism.reverseproxy.dev/",
|
||||
"adminUrl": "https://photoprism.reverseproxy.dev/",
|
||||
"surrogateAuthRequired": false,
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": [
|
||||
"https://photoprism.reverseproxy.dev/api/v1/auth/callback"
|
||||
],
|
||||
"webOrigins": [
|
||||
"https://photoprism.reverseproxy.dev"
|
||||
],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
"standardFlowEnabled": true,
|
||||
"implicitFlowEnabled": false,
|
||||
"directAccessGrantsEnabled": true,
|
||||
"serviceAccountsEnabled": false,
|
||||
"publicClient": false,
|
||||
"frontchannelLogout": false,
|
||||
"protocol": "openid-connect",
|
||||
"attributes": {
|
||||
"id.token.as.detached.signature": "false",
|
||||
"saml.assertion.signature": "false",
|
||||
"saml.force.post.binding": "false",
|
||||
"saml.multivalued.roles": "false",
|
||||
"saml.encrypt": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false",
|
||||
"saml.server.signature": "false",
|
||||
"saml.server.signature.keyinfo.ext": "false",
|
||||
"use.refresh.tokens": "true",
|
||||
"exclude.session.state.from.auth.response": "false",
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"saml.artifact.binding": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"client_credentials.use_refresh_token": "false",
|
||||
"saml_force_name_id_format": "false",
|
||||
"require.pushed.authorization.requests": "false",
|
||||
"saml.client.signature": "false",
|
||||
"tls.client.certificate.bound.access.tokens": "false",
|
||||
"saml.authnstatement": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"saml.onetimeuse.condition": "false"
|
||||
},
|
||||
"authenticationFlowBindingOverrides": {},
|
||||
"fullScopeAllowed": true,
|
||||
"nodeReRegistrationTimeout": -1,
|
||||
"defaultClientScopes": [
|
||||
"web-origins",
|
||||
"profile",
|
||||
"roles",
|
||||
"email"
|
||||
],
|
||||
"optionalClientScopes": [
|
||||
"address",
|
||||
"phone",
|
||||
"offline_access",
|
||||
"microprofile-jwt"
|
||||
],
|
||||
"access": {
|
||||
"view": true,
|
||||
"configure": true,
|
||||
"manage": true
|
||||
}
|
||||
}
|
75
docker/development/keycloak/clients.json
Normal file
75
docker/development/keycloak/clients.json
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "photoprism-development",
|
||||
"secret": "9d8351a0-ca01-4556-9c37-85eb634869b9",
|
||||
"name": "PhotoPrism",
|
||||
"rootUrl": "https://photoprism.reverseproxy.dev/",
|
||||
"adminUrl": "https://photoprism.reverseproxy.dev/",
|
||||
"surrogateAuthRequired": false,
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": [
|
||||
"https://photoprism.reverseproxy.dev/api/v1/auth/callback"
|
||||
],
|
||||
"webOrigins": [
|
||||
"https://photoprism.reverseproxy.dev"
|
||||
],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
"standardFlowEnabled": true,
|
||||
"implicitFlowEnabled": false,
|
||||
"directAccessGrantsEnabled": true,
|
||||
"serviceAccountsEnabled": false,
|
||||
"publicClient": false,
|
||||
"frontchannelLogout": false,
|
||||
"protocol": "openid-connect",
|
||||
"attributes": {
|
||||
"id.token.as.detached.signature": "false",
|
||||
"saml.assertion.signature": "false",
|
||||
"saml.force.post.binding": "false",
|
||||
"saml.multivalued.roles": "false",
|
||||
"saml.encrypt": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false",
|
||||
"saml.server.signature": "false",
|
||||
"saml.server.signature.keyinfo.ext": "false",
|
||||
"use.refresh.tokens": "true",
|
||||
"exclude.session.state.from.auth.response": "false",
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"saml.artifact.binding": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"client_credentials.use_refresh_token": "false",
|
||||
"saml_force_name_id_format": "false",
|
||||
"require.pushed.authorization.requests": "false",
|
||||
"saml.client.signature": "false",
|
||||
"tls.client.certificate.bound.access.tokens": "false",
|
||||
"saml.authnstatement": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"saml.onetimeuse.condition": "false"
|
||||
},
|
||||
"authenticationFlowBindingOverrides": {},
|
||||
"fullScopeAllowed": true,
|
||||
"nodeReRegistrationTimeout": -1,
|
||||
"defaultClientScopes": [
|
||||
"web-origins",
|
||||
"profile",
|
||||
"roles",
|
||||
"email"
|
||||
],
|
||||
"optionalClientScopes": [
|
||||
"address",
|
||||
"phone",
|
||||
"offline_access",
|
||||
"microprofile-jwt"
|
||||
],
|
||||
"access": {
|
||||
"view": true,
|
||||
"configure": true,
|
||||
"manage": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -6,8 +6,8 @@ SOFTWARE INCLUDED
|
|||
|
||||
PhotoPrism latest, AGPL 3
|
||||
Docker CE 20.10, Apache 2
|
||||
Traefik 2.4, MIT
|
||||
MariaDB 10.5, GPL 2
|
||||
Traefik 2.5, MIT
|
||||
MariaDB 10.6, GPL 2
|
||||
Ofelia 0.3.4, MIT
|
||||
Watchtower 1.3, Apache 2
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ SOFTWARE INCLUDED
|
|||
|
||||
- [PhotoPrism latest](https://docs.photoprism.org/release-notes/), AGPL 3
|
||||
- [Docker CE 20.10](https://docs.docker.com/engine/release-notes/), Apache 2
|
||||
- [Traefik 2.4](https://github.com/traefik/traefik/releases), MIT
|
||||
- [MariaDB 10.5](https://mariadb.com/kb/en/release-notes/), GPL 2
|
||||
- [Traefik 2.5](https://github.com/traefik/traefik/releases), MIT
|
||||
- [MariaDB 10.6](https://mariadb.com/kb/en/release-notes/), GPL 2
|
||||
- [Ofelia 0.3.4](https://github.com/mcuadros/ofelia/releases), MIT
|
||||
- [Watchtower 1.3](https://github.com/containrrr/watchtower/releases), Apache 2
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ services:
|
|||
## see https://docs.photoprism.org/getting-started/proxies/traefik/
|
||||
traefik:
|
||||
restart: always
|
||||
image: traefik:v2.4
|
||||
image: traefik:v2.5
|
||||
container_name: traefik
|
||||
ports:
|
||||
- "80:80"
|
||||
|
|
10
go.mod
10
go.mod
|
@ -2,7 +2,7 @@ module github.com/photoprism/photoprism
|
|||
|
||||
require (
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
|
||||
github.com/caos/oidc v0.15.11
|
||||
github.com/caos/oidc v0.15.12
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/djherbis/times v1.5.0
|
||||
|
@ -60,8 +60,8 @@ require (
|
|||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
|
||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect
|
||||
gonum.org/v1/gonum v0.9.3
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/photoprism/go-tz.v2 v2.1.1
|
||||
|
@ -90,9 +90,9 @@ require (
|
|||
github.com/tidwall/match v1.0.3 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/appengine v1.6.6 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
|
12
go.sum
12
go.sum
|
@ -41,10 +41,10 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
|
|||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0=
|
||||
github.com/caos/oidc v0.15.10 h1:dSzkIvsZR2PSZgvBFFkLJt8A/MujsyLac1yNvBShXuw=
|
||||
github.com/caos/oidc v0.15.10/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU=
|
||||
github.com/caos/oidc v0.15.11 h1:NVhdUte5a3u6x65VARceY2mG2WOgxUcqlZunvoeTe0c=
|
||||
github.com/caos/oidc v0.15.11/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU=
|
||||
github.com/caos/oidc v0.15.12 h1:vBVOsQlFCfW7fV43acxkg2V0NHh0NWA4lWzWiJ6LgOk=
|
||||
github.com/caos/oidc v0.15.12/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
|
@ -468,6 +468,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk=
|
||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -475,6 +477,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
|
|||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -525,6 +529,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -619,6 +625,8 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
|
|||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
|
|
|
@ -496,21 +496,21 @@ var GlobalFlags = []cli.Flag{
|
|||
EnvVar: "PHOTOPRISM_FACE_MATCH_DIST",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "client-id",
|
||||
Name: "oidc-client-id",
|
||||
Usage: "OpenID Connect Client ID",
|
||||
Value: "",
|
||||
EnvVar: "PHOTOPRISM_OIDC_CLIENT_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "client-secret",
|
||||
Name: "oidc-client-secret",
|
||||
Usage: "OpenID Connect Client Secret",
|
||||
Value: "",
|
||||
EnvVar: "PHOTOPRISM_OIDC_CLIENT_SECRET",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "oidc-issuer",
|
||||
Usage: "OpenID Connect Provider/Issuer URL",
|
||||
Name: "oidc-issuer-url",
|
||||
Usage: "OpenID Connect Issuer URL",
|
||||
Value: "",
|
||||
EnvVar: "PHOTOPRISM_OIDC_ISSUER",
|
||||
EnvVar: "PHOTOPRISM_OIDC_ISSUER_URL",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package config
|
|||
import "net/url"
|
||||
|
||||
func (c *Config) OidcIssuerUrl() *url.URL {
|
||||
if c.Options().OidcIssuer == "" {
|
||||
if c.Options().OidcIssuerUrl == "" {
|
||||
return nil
|
||||
}
|
||||
res, err := url.Parse(c.Options().OidcIssuer)
|
||||
res, err := url.Parse(c.Options().OidcIssuerUrl)
|
||||
if err != nil {
|
||||
log.Debugf("error parsing oidc issuer url: %q", err)
|
||||
return nil
|
||||
|
|
|
@ -21,13 +21,10 @@ const (
|
|||
Postgres = "postgres" // TODO: Requires GORM 2.0 for generic column data types
|
||||
)
|
||||
|
||||
// Options provides a struct in which application configuration is stored.
|
||||
// Application code must use functions to get config options, for two reasons:
|
||||
//
|
||||
// 1. Some options are computed and we don't want to leak implementation details (aims at reducing refactoring overhead).
|
||||
//
|
||||
// 2. Paths might actually be dynamic later (if we build a multi-user version).
|
||||
//
|
||||
// Options provides a struct in which the application configuration is stored.
|
||||
// The application code must use functions to obtain configuration values:
|
||||
// 1. We don't want to leak implementation details to reduce refactoring overhead
|
||||
// 2. Path names can be dynamic later, for example depending on the user ID
|
||||
// See https://github.com/photoprism/photoprism/issues/50#issuecomment-433856358
|
||||
type Options struct {
|
||||
Name string `json:"-"`
|
||||
|
@ -42,6 +39,9 @@ type Options struct {
|
|||
Sponsor bool `yaml:"-" json:"-" flag:"sponsor"`
|
||||
Public bool `yaml:"Public" json:"-" flag:"public"`
|
||||
AdminPassword string `yaml:"AdminPassword" json:"-" flag:"admin-password"`
|
||||
OidcClientID string `yaml:"-" json:"-" flag:"oidc-client-id"`
|
||||
OidcClientSecret string `yaml:"-" json:"-" flag:"oidc-client-secret"`
|
||||
OidcIssuerUrl string `yaml:"-" json:"-" flag:"oidc-issuer-url"`
|
||||
ReadOnly bool `yaml:"ReadOnly" json:"ReadOnly" flag:"read-only"`
|
||||
Experimental bool `yaml:"Experimental" json:"Experimental" flag:"experimental"`
|
||||
ConfigPath string `yaml:"ConfigPath" json:"-" flag:"config-path"`
|
||||
|
@ -123,9 +123,6 @@ type Options struct {
|
|||
FaceClusterDist float64 `yaml:"-" json:"-" flag:"face-cluster-dist"`
|
||||
FaceMatchDist float64 `yaml:"-" json:"-" flag:"face-match-dist"`
|
||||
PIDFilename string `yaml:"PIDFilename" json:"-" flag:"pid-filename"`
|
||||
OidcClientID string `yaml:"OidcClientID" json:"-" flag:"client-id"`
|
||||
OidcClientSecret string `yaml:"OidcClientSecret" json:"-" flag:"client-secret"`
|
||||
OidcIssuer string `yaml:"OidcIssuer" json:"-" flag:"oidc-issuer"`
|
||||
}
|
||||
|
||||
// NewOptions creates a new configuration entity by using two methods:
|
||||
|
|
|
@ -74,7 +74,7 @@ func NewTestOptions() *Options {
|
|||
DatabaseDriver: dbDriver,
|
||||
DatabaseDsn: dbDsn,
|
||||
AdminPassword: "photoprism",
|
||||
OidcIssuer: "http://dummy-oidc:9998",
|
||||
OidcIssuerUrl: "http://dummy-oidc:9998",
|
||||
OidcClientID: "native",
|
||||
OidcClientSecret: "random",
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package form
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewFaceSearch(t *testing.T) {
|
||||
|
|
|
@ -27,21 +27,28 @@ type Client struct {
|
|||
debug bool
|
||||
}
|
||||
|
||||
func NewClient(iss *url.URL, clientId, clientSecret, siteUrl string, debug bool) (*Client, error) {
|
||||
log.Debugf("Provider Params: %s %s %s %s", iss.String(), clientId, clientSecret, siteUrl)
|
||||
func NewClient(iss *url.URL, clientId, clientSecret, siteUrl string, debug bool) (result *Client, err error) {
|
||||
log.Debugf("oidc: Provider Params: %s %s %s %s", iss.String(), clientId, clientSecret, siteUrl)
|
||||
|
||||
u, err := url.Parse(siteUrl)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
u.Path = path.Join(u.Path, "/api/v1/", RedirectPath)
|
||||
log.Debugf(u.String())
|
||||
|
||||
hashKey, err := rnd.RandomBytes(16)
|
||||
encryptKey, err := rnd.RandomBytes(16)
|
||||
if err != nil {
|
||||
log.Errorf("oidc intialization: %q", err)
|
||||
u.Path = path.Join(u.Path, "/api/v1/", RedirectPath)
|
||||
log.Debugf("oidc: %s", u.String())
|
||||
|
||||
var hashKey, encryptKey []byte
|
||||
|
||||
if hashKey, err = rnd.RandomBytes(16); err != nil {
|
||||
log.Errorf("oidc: %q (create hash key)", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if encryptKey, err = rnd.RandomBytes(16); err != nil {
|
||||
log.Errorf("oidc: %q (create encrypt key)", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -57,10 +64,12 @@ func NewClient(iss *url.URL, clientId, clientSecret, siteUrl string, debug bool)
|
|||
}
|
||||
|
||||
discover, err := client.Discover(iss.String(), httpClient)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("oidc intialization: %q", err)
|
||||
log.Errorf("oidc: %q (discover)", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range discover.CodeChallengeMethodsSupported {
|
||||
if v == oidc.CodeChallengeMethodS256 {
|
||||
options = append(options, rp.WithPKCE(cookieHandler))
|
||||
|
@ -70,11 +79,13 @@ func NewClient(iss *url.URL, clientId, clientSecret, siteUrl string, debug bool)
|
|||
scopes := strings.Split("openid profile email", " ")
|
||||
|
||||
provider, err := rp.NewRelyingPartyOIDC(iss.String(), clientId, clientSecret, u.String(), scopes, options...)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("oidc intialization: %s", err)
|
||||
log.Errorf("oidc: %s (issuer)", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("PKCE enabled: %v", provider.IsPKCE())
|
||||
|
||||
log.Debugf("oidc: PKCE enabled %v", provider.IsPKCE())
|
||||
|
||||
return &Client{
|
||||
provider,
|
||||
|
@ -94,10 +105,10 @@ func (c *Client) CodeExchangeUserInfo(ctx *gin.Context) (oidc.UserInfo, error) {
|
|||
var userinfo oidc.UserInfo
|
||||
|
||||
userinfoClosure := func(w http.ResponseWriter, r *http.Request, tokens *oidc.Tokens, state string, rp rp.RelyingParty, info oidc.UserInfo) {
|
||||
log.Infof("UserInfo: %s %s %s %s %s", info.GetEmail(), info.GetSubject(), info.GetNickname(), info.GetName(), info.GetPreferredUsername())
|
||||
log.Debugf("IDToken: %s", tokens.IDToken)
|
||||
log.Debugf("AToken: %s", tokens.AccessToken)
|
||||
log.Debugf("RToken: %s", tokens.RefreshToken)
|
||||
log.Infof("oidc: UserInfo: %s %s %s %s %s", info.GetEmail(), info.GetSubject(), info.GetNickname(), info.GetName(), info.GetPreferredUsername())
|
||||
log.Debugf("oidc: IDToken: %s", tokens.IDToken)
|
||||
log.Debugf("oidc: AToken: %s", tokens.AccessToken)
|
||||
log.Debugf("oidc: RToken: %s", tokens.RefreshToken)
|
||||
|
||||
userinfo = info
|
||||
}
|
||||
|
@ -114,7 +125,7 @@ func (c *Client) CodeExchangeUserInfo(ctx *gin.Context) (oidc.UserInfo, error) {
|
|||
//handle := rp.CodeExchangeHandler(tokeninfoClosure, c)
|
||||
handle(ctx.Writer, ctx.Request)
|
||||
|
||||
log.Debugf("current request state: %v", ctx.Writer.Status())
|
||||
log.Debugf("oidc: current request state: %v", ctx.Writer.Status())
|
||||
if sc := ctx.Writer.Status(); sc != 0 && sc != http.StatusOK {
|
||||
return nil, errors.New("oidc: couldn't exchange auth code and thus not retrieve external user info")
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package thumb
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestName_Jpeg(t *testing.T) {
|
||||
|
|
34
scripts/mariadb-init.sh
Executable file
34
scripts/mariadb-init.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Create default databases
|
||||
cat << EOF
|
||||
CREATE DATABASE IF NOT EXISTS keycloak;
|
||||
CREATE USER IF NOT EXISTS keycloak@'%' IDENTIFIED BY 'keycloak';
|
||||
GRANT ALL PRIVILEGES ON keycloak.* TO keycloak@'%';
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS photoprism_latest;
|
||||
CREATE USER IF NOT EXISTS photoprism_latest@'%' IDENTIFIED BY 'photoprism_latest';
|
||||
GRANT ALL PRIVILEGES ON photoprism_latest.* TO photoprism_latest@'%';
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS photoprism_preview;
|
||||
CREATE USER IF NOT EXISTS photoprism_preview@'%' IDENTIFIED BY 'photoprism_preview';
|
||||
GRANT ALL PRIVILEGES ON photoprism_preview.* TO photoprism_preview@'%';
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS acceptance;
|
||||
CREATE USER IF NOT EXISTS acceptance@'%' IDENTIFIED BY 'acceptance';
|
||||
GRANT ALL PRIVILEGES ON acceptance.* TO acceptance@'%';
|
||||
|
||||
EOF
|
||||
|
||||
# Create additional test databases
|
||||
for USER_ID in $(seq -f "%02g" 1 5)
|
||||
do
|
||||
echo "CREATE DATABASE IF NOT EXISTS photoprism_$USER_ID;"
|
||||
echo "CREATE USER IF NOT EXISTS photoprism_$USER_ID@'%' IDENTIFIED BY 'photoprism_$USER_ID';";
|
||||
echo "GRANT ALL PRIVILEGES ON photoprism_$USER_ID.* TO photoprism_$USER_ID@'%';"
|
||||
done
|
||||
|
||||
cat << EOF
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
EOF
|
|
@ -1,21 +0,0 @@
|
|||
CREATE DATABASE IF NOT EXISTS alpha;
|
||||
CREATE DATABASE IF NOT EXISTS beta;
|
||||
CREATE DATABASE IF NOT EXISTS gamma;
|
||||
CREATE DATABASE IF NOT EXISTS latest;
|
||||
CREATE DATABASE IF NOT EXISTS preview;
|
||||
DROP DATABASE IF EXISTS acceptance;
|
||||
CREATE DATABASE IF NOT EXISTS acceptance;
|
||||
DROP DATABASE IF EXISTS api;
|
||||
CREATE DATABASE IF NOT EXISTS api;
|
||||
DROP DATABASE IF EXISTS config;
|
||||
CREATE DATABASE IF NOT EXISTS config;
|
||||
DROP DATABASE IF EXISTS entity;
|
||||
CREATE DATABASE IF NOT EXISTS entity;
|
||||
DROP DATABASE IF EXISTS query;
|
||||
CREATE DATABASE IF NOT EXISTS query;
|
||||
DROP DATABASE IF EXISTS remote;
|
||||
CREATE DATABASE IF NOT EXISTS remote;
|
||||
DROP DATABASE IF EXISTS service;
|
||||
CREATE DATABASE IF NOT EXISTS service;
|
||||
DROP DATABASE IF EXISTS workers;
|
||||
CREATE DATABASE IF NOT EXISTS workers;
|
2700
scripts/sql/mariadb-init.sql
Normal file
2700
scripts/sql/mariadb-init.sql
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,9 @@
|
|||
DROP DATABASE IF EXISTS photoprism;
|
||||
CREATE DATABASE IF NOT EXISTS photoprism;
|
||||
|
||||
DROP DATABASE IF EXISTS acceptance;
|
||||
CREATE DATABASE IF NOT EXISTS acceptance;
|
||||
CREATE USER IF NOT EXISTS acceptance@'%' IDENTIFIED BY 'acceptance';
|
||||
GRANT ALL PRIVILEGES ON acceptance.* TO acceptance@'%';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
|
|
Loading…
Add table
Reference in a new issue