Merge branch 'develop' into feature/custom-tf-model-127

This commit is contained in:
Michael Mayer 2025-08-04 09:58:18 +02:00
commit 75785ff2f3
19 changed files with 1137 additions and 513 deletions

42
NOTICE
View file

@ -9,7 +9,7 @@ The following 3rd-party software packages may be used by or distributed with
PhotoPrism. Any information relevant to third-party vendors listed below are
collected using common, reasonable means.
Date generated: 2025-07-24
Date generated: 2025-08-01
================================================================================
@ -1150,8 +1150,8 @@ THE SOFTWARE.
--------------------------------------------------------------------------------
Package: github.com/go-co-op/gocron/v2
Version: v2.16.2
License: MIT (https://github.com/go-co-op/gocron/blob/v2.16.2/LICENSE)
Version: v2.16.3
License: MIT (https://github.com/go-co-op/gocron/blob/v2.16.3/LICENSE)
MIT License
@ -1435,8 +1435,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
Package: github.com/go-logr/logr
Version: v1.4.2
License: Apache-2.0 (https://github.com/go-logr/logr/blob/v1.4.2/LICENSE)
Version: v1.4.3
License: Apache-2.0 (https://github.com/go-logr/logr/blob/v1.4.3/LICENSE)
Apache License
Version 2.0, January 2004
@ -2343,8 +2343,8 @@ SOFTWARE.
--------------------------------------------------------------------------------
Package: github.com/golang/geo
Version: v0.0.0-20250723132703-4547674171cb
License: Apache-2.0 (https://github.com/golang/geo/blob/4547674171cb/LICENSE)
Version: v0.0.0-20250731010204-92ad70d864ba
License: Apache-2.0 (https://github.com/golang/geo/blob/92ad70d864ba/LICENSE)
Apache License
@ -4430,8 +4430,8 @@ SOFTWARE.
--------------------------------------------------------------------------------
Package: github.com/olekukonko/tablewriter
Version: v1.0.8
License: MIT (https://github.com/olekukonko/tablewriter/blob/v1.0.8/LICENSE.md)
Version: v1.0.9
License: MIT (https://github.com/olekukonko/tablewriter/blob/v1.0.9/LICENSE.md)
Copyright (C) 2014 by Oleku Konko
@ -4781,8 +4781,8 @@ License: Apache-2.0 (https://github.com/pquerna/otp/blob/v1.5.0/LICENSE)
--------------------------------------------------------------------------------
Package: github.com/prometheus/client_golang/prometheus
Version: v1.22.0
License: Apache-2.0 (https://github.com/prometheus/client_golang/blob/v1.22.0/LICENSE)
Version: v1.23.0
License: Apache-2.0 (https://github.com/prometheus/client_golang/blob/v1.23.0/LICENSE)
Apache License
Version 2.0, January 2004
@ -5405,8 +5405,8 @@ License: Apache-2.0 (https://github.com/prometheus/common/blob/v0.65.0/LICENSE)
--------------------------------------------------------------------------------
Package: github.com/prometheus/procfs
Version: v0.16.0
License: Apache-2.0 (https://github.com/prometheus/procfs/blob/v0.16.0/LICENSE)
Version: v0.16.1
License: Apache-2.0 (https://github.com/prometheus/procfs/blob/v0.16.1/LICENSE)
Apache License
Version 2.0, January 2004
@ -6414,8 +6414,8 @@ License: Apache-2.0 (https://github.com/zitadel/logging/blob/v0.6.2/LICENSE)
--------------------------------------------------------------------------------
Package: github.com/zitadel/oidc/v3
Version: v3.41.0
License: Apache-2.0 (https://github.com/zitadel/oidc/blob/v3.41.0/LICENSE)
Version: v3.43.0
License: Apache-2.0 (https://github.com/zitadel/oidc/blob/v3.43.0/LICENSE)
Apache License
Version 2.0, January 2004
@ -6864,8 +6864,8 @@ License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go-instrume
--------------------------------------------------------------------------------
Package: go.opentelemetry.io/otel
Version: v1.35.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/v1.35.0/LICENSE)
Version: v1.37.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/v1.37.0/LICENSE)
Apache License
Version 2.0, January 2004
@ -7072,8 +7072,8 @@ License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/v1.
--------------------------------------------------------------------------------
Package: go.opentelemetry.io/otel/metric
Version: v1.35.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/metric/v1.35.0/metric/LICENSE)
Version: v1.37.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/metric/v1.37.0/metric/LICENSE)
Apache License
Version 2.0, January 2004
@ -7280,8 +7280,8 @@ License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/met
--------------------------------------------------------------------------------
Package: go.opentelemetry.io/otel/trace
Version: v1.35.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/trace/v1.35.0/trace/LICENSE)
Version: v1.37.0
License: Apache-2.0 (https://github.com/open-telemetry/opentelemetry-go/blob/trace/v1.37.0/trace/LICENSE)
Apache License
Version 2.0, January 2004

File diff suppressed because it is too large Load diff

View file

@ -42,17 +42,17 @@
"@eslint/js": "9.31.0",
"@lcdp/offline-plugin": "^5.1.3",
"@mdi/font": "^7.4.47",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/jest-dom": "^6.6.4",
"@testing-library/react": "^16.3.0",
"@vitejs/plugin-react": "^4.7.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vitest/browser": "^3.2.4",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"@vue/compiler-sfc": "^3.5.17",
"@vue/language-server": "^3.0.3",
"@vue/language-server": "^3.0.4",
"@vue/test-utils": "^2.4.6",
"@vvo/tzdb": "^6.178.0",
"@vvo/tzdb": "^6.179.0",
"axios": "^1.11.0",
"axios-mock-adapter": "^2.1.0",
"babel-loader": "^10.0.0",
@ -67,14 +67,14 @@
"css-loader": "^7.1.2",
"cssnano": "^7.1.0",
"easygettext": "^2.17.0",
"eslint": "^9.31.0",
"eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8",
"eslint-formatter-pretty": "^6.0.1",
"eslint-plugin-html": "^8.1.3",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.5.3",
"eslint-plugin-vue": "^10.3.0",
"eslint-plugin-vue": "^10.4.0",
"eslint-plugin-vuetify": "^2.5.2",
"eslint-webpack-plugin": "^5.0.2",
"eventsource-polyfill": "^0.9.6",
@ -101,7 +101,7 @@
"node-storage-shim": "^2.0.1",
"passive-events-support": "^1.1.0",
"photoswipe": "^5.4.4",
"playwright": "^1.54.1",
"playwright": "^1.54.2",
"postcss": "^8.5.6",
"postcss-import": "^16.1.1",
"postcss-loader": "^8.1.1",
@ -133,15 +133,15 @@
"vue-sanitize-directive": "^0.2.1",
"vue-style-loader": "^4.1.3",
"vue3-gettext": "^2.4.0",
"vuetify": "^3.9.2",
"webpack": "^5.100.2",
"vuetify": "^3.9.3",
"webpack": "^5.101.0",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "^6.0.1",
"webpack-hot-middleware": "^2.26.1",
"webpack-manifest-plugin": "^5.0.1",
"webpack-md5-hash": "^0.0.6",
"webpack-merge": "^6.0.1",
"webpack-plugin-vuetify": "^3.1.1"
"webpack-plugin-vuetify": "^3.1.2"
},
"engines": {
"node": ">= 18.0.0",

20
go.mod
View file

@ -14,7 +14,7 @@ require (
github.com/esimov/pigo v1.4.6
github.com/gin-contrib/gzip v1.2.3
github.com/gin-gonic/gin v1.10.1
github.com/golang/geo v0.0.0-20250723132703-4547674171cb
github.com/golang/geo v0.0.0-20250731010204-92ad70d864ba
github.com/google/open-location-code/go v0.0.0-20250620134813-83986da0156b
github.com/gorilla/websocket v1.5.3
github.com/gosimple/slug v1.15.0
@ -51,7 +51,7 @@ require (
golang.org/x/image v0.29.0
)
require github.com/olekukonko/tablewriter v1.0.8
require github.com/olekukonko/tablewriter v1.0.9
require github.com/google/uuid v1.6.0
@ -67,7 +67,7 @@ require (
require github.com/go-ldap/ldap/v3 v3.4.11
require (
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_golang v1.23.0
github.com/prometheus/common v0.65.0
)
@ -78,7 +78,7 @@ require golang.org/x/text v0.27.0
require (
github.com/IGLOU-EU/go-wildcard v1.0.3
github.com/davidbyttow/govips/v2 v2.16.0
github.com/go-co-op/gocron/v2 v2.16.2
github.com/go-co-op/gocron/v2 v2.16.3
github.com/pquerna/otp v1.5.0
github.com/robfig/cron/v3 v3.0.1
github.com/swaggo/files v1.0.1
@ -86,7 +86,7 @@ require (
github.com/ugjka/go-tz/v2 v2.2.6
github.com/urfave/cli/v2 v2.27.7
github.com/wamuir/graft v0.10.0
github.com/zitadel/oidc/v3 v3.41.0
github.com/zitadel/oidc/v3 v3.43.0
golang.org/x/mod v0.26.0
golang.org/x/sys v0.34.0
)
@ -108,7 +108,7 @@ require (
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
@ -137,7 +137,7 @@ require (
github.com/olekukonko/ll v0.0.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/procfs v0.16.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
@ -149,9 +149,9 @@ require (
github.com/zitadel/logging v0.6.2 // indirect
github.com/zitadel/schema v1.3.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/tools v0.34.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect

40
go.sum
View file

@ -135,8 +135,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-co-op/gocron/v2 v2.16.2 h1:r08P663ikXiulLT9XaabkLypL/W9MoCIbqgQoAutyX4=
github.com/go-co-op/gocron/v2 v2.16.2/go.mod h1:4YTLGCCAH75A5RlQ6q+h+VacO7CgjkgP0EJ+BEOXRSI=
github.com/go-co-op/gocron/v2 v2.16.3 h1:kYqukZqBa8RC2+AFAHnunmKcs9GRTjwBo8WRF3I6cbI=
github.com/go-co-op/gocron/v2 v2.16.3/go.mod h1:aTf7/+5Jo2E+cyAqq625UQ6DzpkV96b22VHIUAt6l3c=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@ -150,8 +150,8 @@ github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JS
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
@ -184,8 +184,8 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20250723132703-4547674171cb h1:3oUGTu1T90B6sCSRza33Ef/WKH0k9nsziktyDPnfP2k=
github.com/golang/geo v0.0.0-20250723132703-4547674171cb/go.mod h1:AN0OjM34c3PbjAsX+QNma1nYtJtRxl+s9MZNV7S+efw=
github.com/golang/geo v0.0.0-20250731010204-92ad70d864ba h1:cdcKyOX1tLhHeO+qXCvSatCi7gkSVy1Dz1Z+3M4MR8Y=
github.com/golang/geo v0.0.0-20250731010204-92ad70d864ba/go.mod h1:AN0OjM34c3PbjAsX+QNma1nYtJtRxl+s9MZNV7S+efw=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -330,8 +330,8 @@ github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ=
github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
@ -346,15 +346,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@ -419,8 +419,8 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBi
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zitadel/logging v0.6.2 h1:MW2kDDR0ieQynPZ0KIZPrh9ote2WkxfBif5QoARDQcU=
github.com/zitadel/logging v0.6.2/go.mod h1:z6VWLWUkJpnNVDSLzrPSQSQyttysKZ6bCRongw0ROK4=
github.com/zitadel/oidc/v3 v3.41.0 h1:mzxk23KNLKoQ4pm8lTpfVywX043IPtsHsY7D+DEFBDc=
github.com/zitadel/oidc/v3 v3.41.0/go.mod h1:vKJZJJou2Je8/6d3M+gEFVYC9NKExRuHedjwWWElVKo=
github.com/zitadel/oidc/v3 v3.43.0 h1:LokviPoiTNNPbIAMO/eb6Kq9PNWPWp0mA1oWtdLc+Qs=
github.com/zitadel/oidc/v3 v3.43.0/go.mod h1:5ki8s9CWoB4iGmtULndiVxwM8xt7IylZIaudro7jEq4=
github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@ -429,12 +429,12 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=

View file

@ -8,6 +8,7 @@ import (
"github.com/photoprism/photoprism/internal/ai/vision"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/entity/search"
"github.com/photoprism/photoprism/internal/workers"
)
@ -21,6 +22,13 @@ var VisionRunCommand = &cli.Command{
Name: "models",
Aliases: []string{"m"},
Usage: "computer vision `MODELS` to run, e.g. caption, labels, or nsfw",
Value: "caption",
},
&cli.IntFlag{
Name: "count",
Aliases: []string{"c"},
Usage: "maximum number of pictures to be processed",
Value: search.MaxResults,
},
&cli.StringFlag{
Name: "source",
@ -44,6 +52,7 @@ func visionRunAction(ctx *cli.Context) error {
filter := strings.TrimSpace(strings.Join(ctx.Args().Slice(), " "))
return worker.Start(
filter,
ctx.Int("count"),
vision.ParseTypes(ctx.String("models")),
ctx.String("source"),
ctx.Bool("force"),

View file

@ -23,6 +23,11 @@ func (c *Config) DetachServer() bool {
return c.options.DetachServer
}
// TrustedPlatform returns the trusted platform client IP address header name.
func (c *Config) TrustedPlatform() string {
return c.options.TrustedPlatform
}
// TrustedProxy returns the ranges from which reverse proxy headers can be trusted as comma-separated list.
func (c *Config) TrustedProxy() string {
return strings.Join(c.options.TrustedProxies, ", ")
@ -33,6 +38,16 @@ func (c *Config) TrustedProxies() []string {
return c.options.TrustedProxies
}
// ProxyClientHeader returns the proxy client IP address header names as comma-separated list.
func (c *Config) ProxyClientHeader() string {
return strings.Join(c.options.ProxyClientHeaders, ", ")
}
// ProxyClientHeaders returns the proxy client IP address header names, if any.
func (c *Config) ProxyClientHeaders() []string {
return c.options.ProxyClientHeaders
}
// ProxyProtoHeader returns the proxy protocol header names.
func (c *Config) ProxyProtoHeader() []string {
return c.options.ProxyProtoHeaders
@ -49,7 +64,7 @@ func (c *Config) ProxyProtoHeaders() map[string]string {
h := make(map[string]string, p+1)
if p == 0 {
h[header.ForwardedProto] = scheme.Https
h[header.XForwardedProto] = scheme.Https
return h
}

View file

@ -655,16 +655,28 @@ var Flags = CliFlags{
Usage: "ignore invalid HTTPS certificates when using a proxy",
EnvVars: EnvVars("HTTPS_PROXY_INSECURE"),
}}, {
Flag: &cli.StringFlag{
Name: "trusted-platform",
Usage: "trusted client IP header `NAME`, e.g. when running behind a cloud provider load balancer",
Value: "",
EnvVars: EnvVars("TRUSTED_PLATFORM"),
}}, {
Flag: &cli.StringSliceFlag{
Name: "trusted-proxy",
Usage: "`CIDR` ranges or IPv4/v6 addresses from which reverse proxy headers can be trusted, separated by commas",
Value: cli.NewStringSlice(header.CidrDockerInternal),
EnvVars: EnvVars("TRUSTED_PROXY"),
}}, {
Flag: &cli.StringSliceFlag{
Name: "proxy-client-header",
Usage: "proxy client IP header `NAME`, e.g. X-Forwarded-For, X-Client-IP, X-Real-IP, or CF-Connecting-IP",
Value: cli.NewStringSlice(header.XForwardedFor),
EnvVars: EnvVars("PROXY_CLIENT_HEADER"),
}}, {
Flag: &cli.StringSliceFlag{
Name: "proxy-proto-header",
Usage: "proxy protocol header `NAME`",
Value: cli.NewStringSlice(header.ForwardedProto),
Value: cli.NewStringSlice(header.XForwardedProto),
EnvVars: EnvVars("PROXY_PROTO_HEADER"),
}}, {
Flag: &cli.StringSliceFlag{

View file

@ -141,7 +141,9 @@ type Options struct {
CORSMethods string `yaml:"CORSMethods" json:"-" flag:"cors-methods"`
HttpsProxy string `yaml:"HttpsProxy" json:"HttpsProxy" flag:"https-proxy"`
HttpsProxyInsecure bool `yaml:"HttpsProxyInsecure" json:"HttpsProxyInsecure" flag:"https-proxy-insecure"`
TrustedPlatform string `yaml:"TrustedPlatform" json:"-" flag:"trusted-platform"`
TrustedProxies []string `yaml:"TrustedProxies" json:"-" flag:"trusted-proxy"`
ProxyClientHeaders []string `yaml:"ProxyClientHeaders" json:"-" flag:"proxy-client-header"`
ProxyProtoHeaders []string `yaml:"ProxyProtoHeaders" json:"-" flag:"proxy-proto-header"`
ProxyProtoHttps []string `yaml:"ProxyProtoHttps" json:"-" flag:"proxy-proto-https"`
DisableTLS bool `yaml:"DisableTLS" json:"DisableTLS" flag:"disable-tls"`

View file

@ -177,7 +177,9 @@ func (c *Config) Report() (rows [][]string, cols []string) {
// Proxy Servers.
{"https-proxy", c.HttpsProxy()},
{"https-proxy-insecure", fmt.Sprintf("%t", c.HttpsProxyInsecure())},
{"trusted-platform", c.TrustedPlatform()},
{"trusted-proxy", c.TrustedProxy()},
{"proxy-client-header", c.ProxyClientHeader()},
{"proxy-proto-header", strings.Join(c.ProxyProtoHeader(), ", ")},
{"proxy-proto-https", strings.Join(c.ProxyProtoHttps(), ", ")},

View file

@ -830,13 +830,13 @@ func searchPhotos(frm form.SearchPhotos, sess *entity.Session, resultCols string
}
}
// Limit offset and count.
if frm.Count > 0 && frm.Count <= MaxResults {
s = s.Limit(frm.Count).Offset(frm.Offset)
} else {
s = s.Limit(MaxResults).Offset(frm.Offset)
// Search result count and offset.
if frm.Count <= 0 || frm.Count > MaxResults {
frm.Count = MaxResults
}
s = s.Limit(frm.Count).Offset(frm.Offset)
// Query database.
if err = s.Scan(&results).Error; err != nil {
return results, 0, err

View file

@ -31,6 +31,6 @@ var Security = func(conf *config.Config) gin.HandlerFunc {
// Set "X-Frame-Options" header:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
c.Header(header.FrameOptions, header.DefaultFrameOptions)
c.Header(header.XFrameOptions, header.DefaultFrameOptions)
}
}

View file

@ -47,9 +47,21 @@ func Start(ctx context.Context, conf *config.Config) {
// Create new router engine without standard middleware.
router := gin.New()
// Set proxy addresses from which headers related to the client and protocol can be trusted
if err := router.SetTrustedProxies(conf.TrustedProxies()); err != nil {
log.Warnf("server: %s", err)
// Set proxy from which headers related to the client and protocol can be trusted?
if trustedProxies := conf.TrustedProxies(); len(trustedProxies) > 0 {
if err := router.SetTrustedProxies(trustedProxies); err != nil {
log.Warnf("server: %s", err)
}
router.RemoteIPHeaders = conf.ProxyClientHeaders()
}
// Set trusted platform client IP address header name?
if trustedPlatform := conf.TrustedPlatform(); trustedPlatform != "" {
router.TrustedPlatform = trustedPlatform
// Enable support for HTTP/2 without TLS.
router.UseH2C = true
}
// Register panic recovery middleware.

View file

@ -41,7 +41,7 @@ func (w *Vision) originalsPath() string {
}
// Start runs the specified model types for photos matching the search query filter string.
func (w *Vision) Start(filter string, models []string, customSrc string, force bool) (err error) {
func (w *Vision) Start(filter string, count int, models []string, customSrc string, force bool) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("vision: %s (worker panic)\nstack: %s", r, debug.Stack())
@ -83,118 +83,122 @@ func (w *Vision) Start(filter string, models []string, customSrc string, force b
start := time.Now()
done := make(map[string]bool)
limit := 1000
offset := 0
updated := 0
// Make sure count is within
if count < 1 || count > search.MaxResults {
count = search.MaxResults
}
ind := get.Index()
for {
frm := form.SearchPhotos{
Query: filter,
Primary: true,
Merged: false,
Count: limit,
Offset: offset,
Order: sortby.Added,
frm := form.SearchPhotos{
Query: filter,
Primary: true,
Merged: false,
Count: count,
Offset: offset,
Order: sortby.Added,
}
// Find photos without captions when only
// captions are updated without force flag.
if !updateLabels && !updateNsfw && !force {
frm.Caption = txt.False
}
photos, _, queryErr := search.Photos(frm)
if queryErr != nil {
return queryErr
}
if n := len(photos); n == 0 {
log.Info("vision: no pictures to process")
return nil
} else {
log.Infof("vision: processing %s", english.Plural(n, "picture", "pictures"))
}
for _, photo := range photos {
if mutex.VisionWorker.Canceled() {
return errors.New("vision: worker canceled")
}
// Find photos without captions when only
// captions are updated without force flag.
if !updateLabels && !updateNsfw && !force {
frm.Caption = txt.False
if done[photo.PhotoUID] {
continue
}
photos, _, queryErr := search.Photos(frm)
done[photo.PhotoUID] = true
if queryErr != nil {
return queryErr
photoName := path.Join(photo.PhotoPath, photo.PhotoName)
fileName := photoprism.FileName(photo.FileRoot, photo.FileName)
file, fileErr := photoprism.NewMediaFile(fileName)
if fileErr != nil {
log.Errorf("vision: failed to open %s (%s)", photoName, fileErr)
continue
}
if len(photos) == 0 {
break
m, loadErr := query.PhotoByUID(photo.PhotoUID)
if loadErr != nil {
log.Errorf("vision: failed to load %s (%s)", photoName, loadErr)
continue
}
for _, photo := range photos {
if mutex.VisionWorker.Canceled() {
return errors.New("vision: worker canceled")
changed := false
// Generate labels.
if updateLabels && (len(m.Labels) == 0 || force) {
if labels := ind.Labels(file, dataSrc); len(labels) > 0 {
m.AddLabels(labels)
changed = true
}
}
if done[photo.PhotoUID] {
continue
// Detect NSFW content.
if updateNsfw && (!photo.PhotoPrivate || force) {
if isNsfw := ind.IsNsfw(file); photo.PhotoPrivate != isNsfw {
photo.PhotoPrivate = isNsfw
changed = true
log.Infof("vision: changed private flag of %s to %t", photoName, photo.PhotoPrivate)
}
}
done[photo.PhotoUID] = true
photoName := path.Join(photo.PhotoPath, photo.PhotoName)
fileName := photoprism.FileName(photo.FileRoot, photo.FileName)
file, fileErr := photoprism.NewMediaFile(fileName)
if fileErr != nil {
log.Errorf("vision: failed to open %s (%s)", photoName, fileErr)
continue
}
m, loadErr := query.PhotoByUID(photo.PhotoUID)
if loadErr != nil {
log.Errorf("vision: failed to load %s (%s)", photoName, loadErr)
continue
}
changed := false
// Generate labels.
if updateLabels && (len(m.Labels) == 0 || force) {
if labels := ind.Labels(file, dataSrc); len(labels) > 0 {
m.AddLabels(labels)
changed = true
// Generate a caption if none exists or the force flag is used,
// and only if no caption was set or removed by a higher-priority source.
if updateCaptions && entity.SrcPriority[dataSrc] >= entity.SrcPriority[m.CaptionSrc] && (m.NoCaption() || force) {
if caption, captionErr := ind.Caption(file); captionErr != nil {
log.Warnf("vision: %s in %s (generate caption)", clean.Error(captionErr), photoName)
} else if caption.Text = strings.TrimSpace(caption.Text); caption.Text != "" {
m.SetCaption(caption.Text, dataSrc)
if updateErr := m.UpdateCaptionLabels(); updateErr != nil {
log.Warnf("vision: %s in %s (update caption labels)", clean.Error(updateErr), photoName)
}
changed = true
log.Infof("vision: changed caption of %s to %s", photoName, clean.Log(m.PhotoCaption))
}
}
// Detect NSFW content.
if updateNsfw && (!photo.PhotoPrivate || force) {
if isNsfw := ind.IsNsfw(file); photo.PhotoPrivate != isNsfw {
photo.PhotoPrivate = isNsfw
changed = true
log.Infof("vision: changed private flag of %s to %t", photoName, photo.PhotoPrivate)
}
}
// Generate a caption if none exists or the force flag is used,
// and only if no caption was set or removed by a higher-priority source.
if updateCaptions && entity.SrcPriority[dataSrc] >= entity.SrcPriority[m.CaptionSrc] && (m.NoCaption() || force) {
if caption, captionErr := ind.Caption(file); captionErr != nil {
log.Warnf("vision: %s in %s (generate caption)", clean.Error(captionErr), photoName)
} else if caption.Text = strings.TrimSpace(caption.Text); caption.Text != "" {
m.SetCaption(caption.Text, dataSrc)
if updateErr := m.UpdateCaptionLabels(); updateErr != nil {
log.Warnf("vision: %s in %s (update caption labels)", clean.Error(updateErr), photoName)
}
changed = true
log.Infof("vision: changed caption of %s to %s", photoName, clean.Log(m.PhotoCaption))
}
}
if changed {
if saveErr := m.GenerateAndSaveTitle(); saveErr != nil {
log.Infof("vision: failed to updated %s (%s)", photoName, clean.Error(saveErr))
} else {
updated++
log.Debugf("vision: updated %s", photoName)
}
if changed {
if saveErr := m.GenerateAndSaveTitle(); saveErr != nil {
log.Infof("vision: failed to updated %s (%s)", photoName, clean.Error(saveErr))
} else {
updated++
log.Debugf("vision: updated %s", photoName)
}
}
if mutex.VisionWorker.Canceled() {
return errors.New("vision: worker canceled")
}
offset += limit
}
log.Infof("vision: updated %s [%s]", english.Plural(updated, "picture", "pictures"), time.Since(start))
if updated > 0 {
log.Infof("vision: updated %s [%s]", english.Plural(updated, "photo", "photos"), time.Since(start))
updateIndex = true
}

View file

@ -1,5 +1,7 @@
package header
const (
CidrPodInternal = "10.0.0.0/8"
CidrDockerInternal = "172.16.0.0/12"
CidrCalicoInternal = "192.168.0.0/16"
)

View file

@ -8,8 +8,15 @@ const (
ReferrerPolicy = "Referrer-Policy" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
ContentTypeOptions = "X-Content-Type-Options" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
XSSProtection = "X-XSS-Protection" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
FrameOptions = "X-Frame-Options" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
ForwardedProto = "X-Forwarded-Proto" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
XFrameOptions = "X-Frame-Options" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
XForwardedProto = "X-Forwarded-Proto" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
XForwardedFor = "X-Forwarded-For" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
Forwarded = "Forwarded" // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Forwarded
XClientIP = "X-Client-IP"
XRealIP = "X-Real-IP"
XAppengineRemoteAddr = "X-Appengine-Remote-Addr"
CFConnectingIP = "CF-Connecting-IP"
FlyClientIP = "Fly-Client-IP"
)
// Standard security policies.

View file

@ -2,12 +2,9 @@
# Installs the "duf" and "muffet" admin tools on Linux.
# bash <(curl -s https://raw.githubusercontent.com/photoprism/photoprism/develop/scripts/dist/install-admin-tools.sh)
# Abort if not executed as root..
if [[ $(id -u) != "0" ]]; then
echo "Usage: run ${0##*/} as root" 1>&2
exit 1
fi
#
# This will install additional admin tools for managing Kubernetes deployments on Linux:
# bash <(curl -s https://raw.githubusercontent.com/photoprism/photoprism/develop/scripts/dist/install-k8s-tools.sh)
set -eux;
@ -19,19 +16,11 @@ then
fi
echo "Installing the duf command to check storage usage..."
GOBIN="/usr/local/bin" go install github.com/muesli/duf@latest
sudo GOBIN="/usr/local/bin" go install github.com/muesli/duf@latest
sudo ln -sf /usr/local/bin/duf /usr/local/bin/df
echo "Installing muffet, a tool for checking links..."
GOBIN="/usr/local/bin" go install github.com/raviqqe/muffet@latest
sudo GOBIN="/usr/local/bin" go install github.com/raviqqe/muffet@latest
echo "Installing petname to generate pronounceable names..."
GOBIN="/usr/local/bin" go install github.com/dustinkirkland/golang-petname/cmd/petname@latest
echo "Installing doctl for using the DigitalOcean API...."
GOBIN="/usr/local/bin" go install github.com/digitalocean/doctl/cmd/doctl@latest
echo "Installing Kustomize for Kubernetes configuration management...."
GOBIN="/usr/local/bin" go install sigs.k8s.io/kustomize/kustomize/v5@latest
# Create a symbolic link for "duf" so that it is used instead of the original "df".
ln -sf /usr/local/bin/duf /usr/local/bin/df
sudo GOBIN="/usr/local/bin" go install github.com/dustinkirkland/golang-petname/cmd/petname@latest

41
scripts/dist/install-forward-dns.sh vendored Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Installs and configures BIND 9 on Ubuntu/Debian to provide a forward DNS service for private IP address ranges.
# bash <(curl -s https://raw.githubusercontent.com/photoprism/photoprism/develop/scripts/dist/install-forward-dns.sh)
set -e
echo "Installing BIND 9..."
sudo apt -qq update
sudo apt -qq install bind9
echo "Configuring BIND 9 for use as an internal forward DNS service..."
sudo tee /etc/bind/named.conf >/dev/null <<-EOF
options{
directory "/var/cache/bind";
recursion yes;
allow-query {
10.0.0.0/8;
127.0.0.0/8;
172.16.0.0/12;
192.168.0.0/16;
fc00::/7;
fe80::/10;
};
forwarders {
8.8.8.8;
8.8.4.4;
2001:4860:4860::8888;
2001:4860:4860::8844;
};
forward only;
};
EOF
echo "Checking configuration..."
sudo named-checkconf /etc/bind/named.conf
echo "Restarting service..."
sudo service bind9 restart
echo "Done."

19
scripts/dist/install-k8s-tools.sh vendored Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Installs additional admin tools for managing Kubernetes deployments on Linux.
# bash <(curl -s https://raw.githubusercontent.com/photoprism/photoprism/develop/scripts/dist/install-k8s-tools.sh)
set -eux;
# Is Go installed?
if ! command -v go &> /dev/null
then
echo "Go must be installed to run this."
exit 1
fi
echo "Installing K9s for managing Kubernetes clusters...."
sudo GOBIN="/usr/local/bin" go install github.com/derailed/k9s@latest
echo "Installing Kustomize for Kubernetes configuration management...."
sudo GOBIN="/usr/local/bin" go install sigs.k8s.io/kustomize/kustomize/v5@latest