Merge remote-tracking branch 'origin/develop' into upgrade/vuetify-3

This commit is contained in:
Michael Mayer
2024-10-16 13:55:08 +02:00
43 changed files with 358 additions and 130 deletions

View File

@@ -1,5 +1,5 @@
# Ubuntu 24.04 LTS (Noble Numbat)
FROM photoprism/develop:240915-noble
FROM photoprism/develop:241014-noble
## Alternative Environments:
# FROM photoprism/develop:armv7 # ARMv7 (32bit)

View File

@@ -732,7 +732,7 @@ fmt-go:
gofmt -w -s pkg internal cmd
goimports -w pkg internal cmd
tidy:
go mod tidy -go=1.22
go mod tidy
users:
./photoprism users add -p photoprism -r admin -s -a test:true -n "Alice Austen" superadmin
./photoprism users ls

View File

@@ -168,7 +168,6 @@ services:
## Dummy WebDAV Server
dummy-webdav:
image: photoprism/dummy-webdav:240627
container_name: dummy-webdav
environment:
WEBDAV_USERNAME: admin
WEBDAV_PASSWORD: photoprism
@@ -185,7 +184,6 @@ services:
## Dummy OIDC Identity Provider
dummy-oidc:
image: photoprism/dummy-oidc:240627
container_name: dummy-oidc
labels:
- "traefik.enable=true"
- "traefik.http.services.dummy-oidc.loadbalancer.server.port=9998"
@@ -200,7 +198,6 @@ services:
## Docs: https://glauth.github.io/docs/
dummy-ldap:
image: glauth/glauth-plugins:latest
container_name: dummy-ldap
ports:
- "127.0.0.1:389:389"
labels:
@@ -220,7 +217,6 @@ services:
## Login with "user / photoprism" and "admin / photoprism".
keycloak:
image: quay.io/keycloak/keycloak:25.0
container_name: keycloak
command: "start-dev" # development mode, do not use this in production!
links:
- "traefik:localssl.dev"
@@ -252,7 +248,6 @@ services:
## ./photoprism client add --id=cs5cpu17n6gj2qo5 --secret=xcCbOrw6I0vcoXzhnOmXhjpVSyFq0l0e -s metrics -n Prometheus -e 60 -t 1
prometheus:
image: prom/prometheus:latest
container_name: prometheus
profiles: ["all", "auth", "prometheus"]
labels:
- "traefik.enable=true"

View File

@@ -65,7 +65,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
mkdir -p /etc/skel/.config/go && \
echo 'off 2024-08-27' > '/etc/skel/.config/go/telemetry' && \
cp -r /etc/skel/.config /root/.config && \
GOLANG_VERSION=go1.22.7 /scripts/install-go.sh && \
GOLANG_VERSION=go1.22.8 /scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias go=richgo ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \

View File

@@ -74,7 +74,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
mkdir -p /etc/skel/.config/go && \
echo 'off 2024-08-27' > '/etc/skel/.config/go/telemetry' && \
cp -r /etc/skel/.config /root/.config && \
GOLANG_VERSION=go1.22.7 /scripts/install-go.sh && \
GOLANG_VERSION=go1.22.8 /scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias go=richgo ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \

View File

@@ -75,7 +75,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
mkdir -p /etc/skel/.config/go && \
echo 'off 2024-08-27' > '/etc/skel/.config/go/telemetry' && \
cp -r /etc/skel/.config /root/.config && \
GOLANG_VERSION=go1.22.7 /scripts/install-go.sh && \
GOLANG_VERSION=go1.22.8 /scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias go=richgo ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \

View File

@@ -76,7 +76,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
mkdir -p /etc/skel/.config/go && \
echo 'off 2024-08-27' > '/etc/skel/.config/go/telemetry' && \
cp -r /etc/skel/.config /root/.config && \
GOLANG_VERSION=go1.22.7 /scripts/install-go.sh && \
GOLANG_VERSION=go1.22.8 /scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias go=richgo ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: ci@photoprism.app\n"
"PO-Revision-Date: 2024-09-13 13:26+0000\n"
"Last-Translator: DeepL <noreply-mt-deepl@weblate.org>\n"
"PO-Revision-Date: 2024-10-07 21:05+0000\n"
"Last-Translator: dtsolakis <dtsola@eranet.gr>\n"
"Language: el\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -1219,7 +1219,7 @@ msgstr "Όνομα"
#: src/page/settings/advanced.vue:18
msgid "Global Options"
msgstr "Παγκόσμιες επιλογές"
msgstr "Καθολικές Ρυθμίσεις"
#: src/options/options.js:448
msgid "Gold"

File diff suppressed because one or more lines are too long

View File

@@ -941,7 +941,7 @@
},
{
"Code": "us",
"Name": "USA"
"Name": "United States"
},
{
"Code": "um",

View File

@@ -51,7 +51,7 @@ export const Years = () => {
const currentYear = new Date().getUTCFullYear();
for (let i = currentYear; i >= 1750; i--) {
for (let i = currentYear; i >= 1000; i--) {
result.push({ value: i, text: i.toString().padStart(4, "0") });
}

View File

@@ -55,7 +55,7 @@ test.meta("testID", "folders-002").meta({ mode: "public" })(
await t
.typeText(albumdialog.title, "MyFolder", { replace: true })
.typeText(albumdialog.location, "USA", { replace: true })
.typeText(albumdialog.location, "United States", { replace: true })
.typeText(albumdialog.description, "Last holiday")
.typeText(albumdialog.category, "Mountains")
.pressKey("enter")
@@ -69,7 +69,7 @@ test.meta("testID", "folders-002").meta({ mode: "public" })(
.expect(Selector("div.caption").nth(1).innerText)
.contains("Mountains")
.expect(Selector("div.caption").nth(2).innerText)
.contains("USA");
.contains("United States");
await album.openNthAlbum(0);
@@ -97,7 +97,7 @@ test.meta("testID", "folders-002").meta({ mode: "public" })(
.expect(albumdialog.category.value)
.eql("Mountains")
.expect(albumdialog.location.value)
.eql("USA");
.eql("United States");
await t
.typeText(albumdialog.title, "Kanada", { replace: true })
@@ -120,7 +120,7 @@ test.meta("testID", "folders-002").meta({ mode: "public" })(
.expect(page.cardDescription.nth(0).innerText)
.notContains("We went to ski")
.expect(Selector("div.caption").nth(0).innerText)
.notContains("USA");
.notContains("United States");
}
);

40
go.mod
View File

@@ -24,7 +24,7 @@ require (
github.com/karrick/godirwalk v1.17.0
github.com/klauspost/cpuid/v2 v2.2.8
github.com/leandro-lugaresi/hub v1.1.1
github.com/leonelquinteros/gotext v1.6.1
github.com/leonelquinteros/gotext v1.7.0
github.com/lib/pq v1.10.9 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mandykoh/prism v0.35.3
@@ -38,12 +38,12 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/tensorflow/tensorflow v1.15.2
github.com/tidwall/gjson v1.17.3
github.com/tidwall/gjson v1.18.0
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6
github.com/urfave/cli v1.22.15
github.com/urfave/cli v1.22.16
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/crypto v0.27.0
golang.org/x/net v0.29.0
golang.org/x/crypto v0.28.0
golang.org/x/net v0.30.0
gonum.org/v1/gonum v0.15.1
gopkg.in/photoprism/go-tz.v2 v2.1.3
gopkg.in/yaml.v2 v2.4.0
@@ -51,7 +51,7 @@ require (
require (
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
golang.org/x/image v0.20.0
golang.org/x/image v0.21.0
)
require github.com/olekukonko/tablewriter v0.0.5
@@ -60,32 +60,32 @@ require github.com/google/uuid v1.6.0
require github.com/chzyer/readline v1.5.1 // indirect
require github.com/gabriel-vasile/mimetype v1.4.5
require github.com/gabriel-vasile/mimetype v1.4.6
require (
golang.org/x/sync v0.8.0
golang.org/x/time v0.6.0
golang.org/x/time v0.7.0
)
require github.com/go-ldap/ldap/v3 v3.4.8
require (
github.com/prometheus/client_golang v1.20.3
github.com/prometheus/common v0.59.1
github.com/prometheus/client_golang v1.20.5
github.com/prometheus/common v0.60.0
)
require github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0
require golang.org/x/text v0.18.0
require golang.org/x/text v0.19.0
require (
github.com/davidbyttow/govips/v2 v2.15.0
github.com/go-co-op/gocron/v2 v2.11.0
github.com/go-co-op/gocron/v2 v2.12.1
github.com/pquerna/otp v1.4.0
github.com/robfig/cron/v3 v3.0.1
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/zitadel/oidc/v3 v3.29.1
github.com/zitadel/oidc/v3 v3.30.1
)
require (
@@ -97,7 +97,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
@@ -137,15 +137,15 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/zitadel/logging v0.6.0 // indirect
github.com/zitadel/logging v0.6.1 // indirect
github.com/zitadel/schema v1.3.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/tools v0.24.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/tools v0.25.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
@@ -166,6 +166,6 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
)
go 1.22
go 1.22.0
toolchain go1.22.5
toolchain go1.22.7

78
go.sum
View File

@@ -18,7 +18,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
@@ -57,8 +57,8 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -119,8 +119,8 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a
github.com/esimov/pigo v1.4.6 h1:wpB9FstbqeGP/CZP+nTR52tUJe7XErq8buG+k4xCXlw=
github.com/esimov/pigo v1.4.6/go.mod h1:uqj9Y3+3IRYhFK071rxz1QYq0ePhA6+R9jrUZavi46M=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
github.com/gin-contrib/gzip v1.0.1/go.mod h1:njt428fdUNRvjuJf16tZMYZ2Yl+WQB53X5wmhDwXvC4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@@ -131,8 +131,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-co-op/gocron/v2 v2.11.0 h1:IOowNA6SzwdRFnD4/Ol3Kj6G2xKfsoiiGq2Jhhm9bvE=
github.com/go-co-op/gocron/v2 v2.11.0/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
github.com/go-co-op/gocron/v2 v2.12.1 h1:dCIIBFbzhWKdgXeEifBjHPzgQ1hoWhjS4289Hjjy1uw=
github.com/go-co-op/gocron/v2 v2.12.1/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
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=
@@ -288,8 +288,8 @@ github.com/leandro-lugaresi/hub v1.1.1 h1:zqp0HzFvj4HtqjMBXM2QF17o6PNmR8MJOChgeK
github.com/leandro-lugaresi/hub v1.1.1/go.mod h1:XEFWanhHv6Rt3XlteHMxuNDYi8dJcpJjodpqkU+BtIo=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/leonelquinteros/gotext v1.6.1 h1:PuTN8YUqHvfPZxW+fPXp7o0Fc2zN9L2wXBZrqT5MO5A=
github.com/leonelquinteros/gotext v1.6.1/go.mod h1:qQRISjoonXYFdRGrTG1LARQ38Gpibad0IPeB4hpvyyM=
github.com/leonelquinteros/gotext v1.7.0 h1:jcJmF4AXqyamP7vuw2MMIKs+O3jAEmvrc5JQiI8Ht/8=
github.com/leonelquinteros/gotext v1.7.0/go.mod h1:qJdoQuERPpccw7L70uoU+K/BvTfRBHYsisCQyFLXyvw=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
@@ -341,13 +341,13 @@ 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.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -395,8 +395,8 @@ github.com/teambition/rrule-go v1.7.2/go.mod h1:mBJ1Ht5uboJ6jexKdNUJg2NcwP8uUMNv
github.com/teambition/rrule-go v1.8.2/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4=
github.com/tensorflow/tensorflow v1.15.2 h1:7/f/A664Tml/nRJg04+p3StcrsT53mkcvmxYHXI21Qo=
github.com/tensorflow/tensorflow v1.15.2/go.mod h1:itOSERT4trABok4UOoG+X4BoKds9F3rIsySdn+Lvu90=
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
@@ -408,13 +408,13 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs=
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zitadel/logging v0.6.0 h1:t5Nnt//r+m2ZhhoTmoPX+c96pbMarqJvW1Vq6xFTank=
github.com/zitadel/logging v0.6.0/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow=
github.com/zitadel/oidc/v3 v3.29.1 h1:zriEqPK+q/G2qo911tTgh7lnzwowzOUWduWYHVDfaq8=
github.com/zitadel/oidc/v3 v3.29.1/go.mod h1:+I5BgvGO5C2ZJrQRjV34EjkyA7P3GXyYGZgXI8Sdw18=
github.com/zitadel/logging v0.6.1 h1:Vyzk1rl9Kq9RCevcpX6ujUaTYFX43aa4LkvV1TvUk+Y=
github.com/zitadel/logging v0.6.1/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow=
github.com/zitadel/oidc/v3 v3.30.1 h1:CCi9qDjleuRYbECfUoVKrrN97KdheNCHAs33X8XnIRg=
github.com/zitadel/oidc/v3 v3.30.1/go.mod h1:N5p02vx+mLUwf+WFNpDsNp+8DS8+jlgFBwpz7NIQjrg=
github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0=
github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -447,8 +447,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -457,8 +457,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -466,8 +466,8 @@ golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -488,8 +488,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -523,8 +523,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
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=
@@ -579,8 +579,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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=
@@ -604,12 +604,12 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -638,8 +638,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -1679,7 +1679,7 @@ var Rules = LabelRules{
},
"cucumber": {
Label: "vegetables",
Threshold: 0.000000,
Threshold: 0.300000,
Priority: 0,
Categories: []string{"food"},
},

View File

@@ -3723,7 +3723,7 @@ bell pepper:
cucumber:
label: vegetables
thresgold: 0.3
threshold: 0.3
categories:
- food

View File

@@ -31,12 +31,7 @@ func AddDownloadHeader(c *gin.Context, fileName string) {
c.Header(header.ContentDisposition, fmt.Sprintf("attachment; filename=%s", fileName))
}
// AddAuthTokenHeader adds an X-Auth-Token header to the response.
func AddAuthTokenHeader(c *gin.Context, authToken string) {
c.Header(header.XAuthToken, authToken)
}
// AddContentTypeHeader adds a content type header to the response.
// AddContentTypeHeader adds a "Content-Type" header to the response.
func AddContentTypeHeader(c *gin.Context, contentType string) {
c.Header(header.ContentType, contentType)
}

View File

@@ -16,7 +16,7 @@ var AuthListCommand = cli.Command{
Name: "ls",
Usage: "Lists currently authenticated users and clients",
ArgsUsage: "[search]",
Flags: append(report.CliFlags, countFlag, tokensFlag),
Flags: append(report.CliFlags, CountFlag, tokensFlag),
Action: authListAction,
}

View File

@@ -16,7 +16,7 @@ var ClientsListCommand = cli.Command{
Name: "ls",
Usage: "Lists registered client applications",
ArgsUsage: "[search]",
Flags: append(report.CliFlags, countFlag),
Flags: append(report.CliFlags, CountFlag),
Action: clientsListAction,
}

View File

@@ -71,8 +71,8 @@ var PhotoPrism = []cli.Command{
ConnectCommand,
}
// countFlag represents a CLI flag to limit the number of report rows.
var countFlag = cli.UintFlag{
// CountFlag represents a CLI flag to limit the number of report rows.
var CountFlag = cli.UintFlag{
Name: "n",
Usage: "`LIMIT` number of results",
Value: 100,

View File

@@ -79,3 +79,27 @@ var UserFlags = []cli.Flag{
Usage: UserWebDAVUsage,
},
}
// UserTokensFlag is a CLI flag for showing the security tokens in reports.
var UserTokensFlag = cli.BoolFlag{
Name: "tokens",
Usage: "show user preview and download tokens",
}
// UsersLoginFlag is a CLI flag for showing the last login timestamp in reports.
var UsersLoginFlag = cli.BoolFlag{
Name: "login, l",
Usage: "show date and time of last login",
}
// UsersCreatedFlag is a CLI flag for showing the account creation timestamp in reports.
var UsersCreatedFlag = cli.BoolFlag{
Name: "created, a",
Usage: "show account creation timestamp",
}
// UsersDeletedFlag is a CLI flag for showing deleted user accounts in reports.
var UsersDeletedFlag = cli.BoolFlag{
Name: "deleted, r",
Usage: "show deleted user accounts",
}

View File

@@ -15,7 +15,7 @@ import (
var UsersListCommand = cli.Command{
Name: "ls",
Usage: "Lists registered user accounts",
Flags: append(report.CliFlags, countFlag),
Flags: append(report.CliFlags, CountFlag, UsersLoginFlag, UsersCreatedFlag, UsersDeletedFlag),
Action: usersListAction,
}
@@ -24,10 +24,22 @@ func usersListAction(ctx *cli.Context) error {
return CallWithDependencies(ctx, func(conf *config.Config) error {
var rows [][]string
cols := []string{"UID", "Username", "Role", "Authentication", "Super Admin", "Web Login", "Last Login", "WebDAV"}
cols := []string{"UID", "Username", "Role", "Authentication", "Super Admin", "Web Login", "WebDAV"}
if ctx.Bool("login") {
cols = append(cols, "Last Login")
}
if ctx.Bool("created") {
cols = append(cols, "Created At")
}
if ctx.Bool("deleted") {
cols = append(cols, "Deleted At")
}
// Fetch users from database.
users, err := query.Users(ctx.Int("n"), 0, "", ctx.Args().First())
users, err := query.Users(ctx.Int("n"), 0, "", ctx.Args().First(), ctx.Bool("deleted"))
if err != nil {
return err
@@ -42,9 +54,6 @@ func usersListAction(ctx *cli.Context) error {
rows = make([][]string, len(users))
// Show log message.
log.Infof("found %s", english.Plural(len(users), "user", "users"))
// Display report.
for i, user := range users {
rows[i] = []string{
@@ -54,9 +63,20 @@ func usersListAction(ctx *cli.Context) error {
user.AuthInfo(),
report.Bool(user.SuperAdmin, report.Yes, report.No),
report.Bool(user.CanLogIn(), report.Enabled, report.Disabled),
report.DateTime(user.LoginAt),
report.Bool(user.CanUseWebDAV(), report.Enabled, report.Disabled),
}
if ctx.Bool("login") {
rows[i] = append(rows[i], report.DateTime(user.LoginAt))
}
if ctx.Bool("created") {
rows[i] = append(rows[i], report.DateTime(&user.CreatedAt))
}
if ctx.Bool("deleted") {
rows[i] = append(rows[i], report.DateTime(user.DeletedAt))
}
}
result, err := report.RenderFormat(rows, cols, report.CliFormat(ctx))

View File

@@ -13,7 +13,7 @@ func TestUsersListCommand(t *testing.T) {
var err error
// Create test context with flags and arguments.
ctx := NewTestContext([]string{"ls"})
ctx := NewTestContext([]string{"ls", "--login", "--created", "--deleted", "-n", "100", "--md"})
// Run command with test context.
output := capture.Output(func() {
@@ -28,11 +28,11 @@ func TestUsersListCommand(t *testing.T) {
assert.NotContains(t, output, "Monitoring")
assert.NotContains(t, output, "visitor")
})
t.Run("Friend", func(t *testing.T) {
t.Run("LastLogin", func(t *testing.T) {
var err error
// Create test context with flags and arguments.
ctx := NewTestContext([]string{"ls", "friend"})
ctx := NewTestContext([]string{"ls", "-l", "friend"})
// Run command with test context.
output := capture.Output(func() {
@@ -42,7 +42,47 @@ func TestUsersListCommand(t *testing.T) {
// Check command output for plausibility.
// t.Logf(output)
assert.NoError(t, err)
assert.Contains(t, output, "| Last Login |")
assert.Contains(t, output, " Last Login ")
assert.Contains(t, output, "friend")
assert.NotContains(t, output, "alice")
assert.NotContains(t, output, "bob")
assert.NotContains(t, output, "visitor")
})
t.Run("Created", func(t *testing.T) {
var err error
// Create test context with flags and arguments.
ctx := NewTestContext([]string{"ls", "-a", "friend"})
// Run command with test context.
output := capture.Output(func() {
err = UsersListCommand.Run(ctx)
})
// Check command output for plausibility.
// t.Logf(output)
assert.NoError(t, err)
assert.Contains(t, output, " Created At ")
assert.Contains(t, output, "friend")
assert.NotContains(t, output, "alice")
assert.NotContains(t, output, "bob")
assert.NotContains(t, output, "visitor")
})
t.Run("Deleted", func(t *testing.T) {
var err error
// Create test context with flags and arguments.
ctx := NewTestContext([]string{"ls", "-r", "friend"})
// Run command with test context.
output := capture.Output(func() {
err = UsersListCommand.Run(ctx)
})
// Check command output for plausibility.
// t.Logf(output)
assert.NoError(t, err)
assert.Contains(t, output, " Deleted At ")
assert.Contains(t, output, "friend")
assert.NotContains(t, output, "alice")
assert.NotContains(t, output, "bob")

View File

@@ -227,7 +227,7 @@ var AlbumFixtures = AlbumMap{
AlbumSlug: "california-usa",
AlbumPath: "",
AlbumType: AlbumState,
AlbumTitle: "California / USA",
AlbumTitle: "California / United States",
AlbumLocation: "",
AlbumCategory: "",
AlbumCaption: "",
@@ -251,7 +251,7 @@ var AlbumFixtures = AlbumMap{
AlbumSlug: "california-usa",
AlbumPath: "",
AlbumType: AlbumState,
AlbumTitle: "California / USA",
AlbumTitle: "California / United States",
AlbumLocation: "",
AlbumCategory: "",
AlbumCaption: "",
@@ -271,7 +271,7 @@ var AlbumFixtures = AlbumMap{
},
"california-duplicate-2": {
ID: 1000010,
AlbumUID: "as6sg6bipotaab19",
AlbumUID: "asjv2cw2eikl3cb3",
AlbumSlug: "california",
AlbumPath: "",
AlbumType: AlbumState,

View File

@@ -288,7 +288,7 @@ func TestFindAlbumBySlug(t *testing.T) {
t.Fatal("album should not be nil")
}
assert.Equal(t, "California / USA", result.AlbumTitle)
assert.Equal(t, "California / United States", result.AlbumTitle)
assert.Equal(t, "california-usa", result.AlbumSlug)
})
t.Run("NoResult", func(t *testing.T) {

View File

@@ -10,8 +10,11 @@ import (
// altCountryNames defines mapping between different names for the same country
var altCountryNames = map[string]string{
"United States of America": "USA",
"United States": "USA",
"us": "United States",
"usa": "United States",
"US": "United States",
"USA": "United States",
"United States of America": "United States",
"": "Unknown",
}

View File

@@ -15,8 +15,8 @@ func TestNewCountry(t *testing.T) {
t.Run("United States", func(t *testing.T) {
country := NewCountry("us", "United States")
assert.Equal(t, "USA", country.CountryName)
assert.Equal(t, "usa", country.CountrySlug)
assert.Equal(t, "United States", country.CountryName)
assert.Equal(t, "united-states", country.CountrySlug)
})
t.Run("Germany", func(t *testing.T) {
country := NewCountry("de", "Germany")

View File

@@ -286,7 +286,7 @@ var FileFixtures = FileMap{
PhotoID: PhotoFixtures.Pointer("Photo15").ID,
PhotoUID: PhotoFixtures.Pointer("Photo15").PhotoUID,
InstanceID: "a698ac56-6e7e-42b9-9c3e-a79ec96080ae",
FileUID: "fs6sg6bw45bn0007",
FileUID: "fsjv2dimofgp5yme",
FileName: "1990/missing.jpg",
FileRoot: RootOriginals,
OriginalName: "",
@@ -370,7 +370,7 @@ var FileFixtures = FileMap{
PhotoID: PhotoFixtures.Pointer("Photo10").ID,
PhotoUID: PhotoFixtures.Pointer("Photo10").PhotoUID,
InstanceID: "a698ac56-6e7e-42b9-9c3e-a79ec96080ag",
FileUID: "fs6sg6bw45bn0007",
FileUID: "fsjv2dbeqj9h6kws",
FileName: "Holiday/Video.mp4",
FileRoot: RootOriginals,
OriginalName: "",

View File

@@ -189,4 +189,10 @@ var DialectMySQL = Migrations{
Stage: "main",
Statements: []string{"ALTER TABLE photos MODIFY photo_lat DOUBLE;", "ALTER TABLE photos MODIFY photo_lng DOUBLE;"},
},
{
ID: "20241010-000001",
Dialect: "mysql",
Stage: "main",
Statements: []string{"UPDATE countries SET country_name = 'United States' WHERE country_name = 'USA' AND country_slug = 'usa';", "UPDATE albums SET album_location = 'United States' WHERE album_location = 'USA' AND album_type = 'state';"},
},
}

View File

@@ -105,4 +105,10 @@ var DialectSQLite3 = Migrations{
Stage: "pre",
Statements: []string{"ALTER TABLE auth_sessions RENAME COLUMN auth_domain TO auth_issuer;"},
},
{
ID: "20241010-000001",
Dialect: "sqlite3",
Stage: "main",
Statements: []string{"UPDATE countries SET country_name = 'United States' WHERE country_name = 'USA' AND country_slug = 'usa';", "UPDATE albums SET album_location = 'United States' WHERE album_location = 'USA' AND album_type = 'state';"},
},
}

View File

@@ -0,0 +1,2 @@
UPDATE countries SET country_name = 'United States' WHERE country_name = 'USA' AND country_slug = 'usa';
UPDATE albums SET album_location = 'United States' WHERE album_location = 'USA' AND album_type = 'state';

View File

@@ -0,0 +1,2 @@
UPDATE countries SET country_name = 'United States' WHERE country_name = 'USA' AND country_slug = 'usa';
UPDATE albums SET album_location = 'United States' WHERE album_location = 'USA' AND album_type = 'state';

View File

@@ -42,13 +42,14 @@ func CountUsers(registered, active bool, roles, excludeRoles []string) (count in
return count
}
// Users finds users and returns them.
func Users(limit, offset int, sortOrder, search string) (result entity.Users, err error) {
// Users finds user accounts based on the specified parameters.
func Users(limit, offset int, sortOrder, search string, deleted bool) (result entity.Users, err error) {
result = entity.Users{}
stmt := Db()
stmt := UnscopedDb()
search = strings.TrimSpace(search)
// Filter user accounts to be returned.
if search == "all" {
// Don't filter.
} else if id := txt.Int(search); id != 0 {
@@ -61,10 +62,17 @@ func Users(limit, offset int, sortOrder, search string) (result entity.Users, er
stmt = stmt.Where("id > 0")
}
// Hide deleted user accounts?
if !deleted {
stmt = stmt.Where("deleted_at IS NULL")
}
// Set result sort order.
if sortOrder == "" {
sortOrder = "id"
}
// Limit number of results.
if limit > 0 {
stmt = stmt.Limit(limit)

View File

@@ -45,28 +45,52 @@ func TestCountUsers(t *testing.T) {
func TestUsers(t *testing.T) {
t.Run("Default", func(t *testing.T) {
if results, err := Users(0, 0, "", ""); err != nil {
if results, err := Users(0, 0, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("Limit", func(t *testing.T) {
if results, err := Users(1, 0, "", ""); err != nil {
if results, err := Users(1, 0, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
}
})
t.Run("Offset", func(t *testing.T) {
if results, err := Users(0, 1, "", ""); err != nil {
if results, err := Users(2, 1, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("SearchAlice", func(t *testing.T) {
if results, err := Users(100, 0, "", "alice"); err != nil {
if results, err := Users(100, 0, "", "alice", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
if len(results) > 0 {
assert.Equal(t, 5, results[0].ID)
assert.Equal(t, "uqxetse3cy5eo9z2", results[0].UserUID)
assert.Equal(t, "alice", results[0].UserName)
}
}
})
t.Run("SearchAliceByID", func(t *testing.T) {
if results, err := Users(100, 0, "", "5", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
if len(results) > 0 {
assert.Equal(t, 5, results[0].ID)
assert.Equal(t, "uqxetse3cy5eo9z2", results[0].UserUID)
assert.Equal(t, "alice", results[0].UserName)
}
}
})
t.Run("SearchAliceByUID", func(t *testing.T) {
if results, err := Users(100, 0, "", "uqxetse3cy5eo9z2", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
@@ -78,17 +102,35 @@ func TestUsers(t *testing.T) {
}
})
t.Run("SortByID", func(t *testing.T) {
if results, err := Users(100, 0, "id", ""); err != nil {
if results, err := Users(100, 0, "id", "all", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("SearchAliceSortByID", func(t *testing.T) {
if results, err := Users(100, 0, "id", "alice"); err != nil {
if results, err := Users(100, 0, "id", "alice", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
}
})
t.Run("IncludeDeleted", func(t *testing.T) {
if results, err := Users(0, 0, "", "deleted", true); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
if len(results) > 0 {
assert.Equal(t, 10000008, results[0].ID)
assert.Equal(t, "deleted", results[0].UserName)
}
}
})
t.Run("ExcludeDeleted", func(t *testing.T) {
if results, err := Users(0, 0, "", "deleted", false); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, 0, len(results))
}
})
}

View File

@@ -27,7 +27,7 @@ func TestAlbums(t *testing.T) {
t.Fatal(err)
}
assert.Equal(t, 30, count)
assert.Equal(t, 31, count)
count, err = Albums(backupPath, false)

18
internal/server/robots.go Normal file
View File

@@ -0,0 +1,18 @@
package server
import (
"github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/header"
)
// Robots is a middleware that adds a "X-Robots-Tag" header to the response:
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#xrobotstag
var Robots = func(conf *config.Config) gin.HandlerFunc {
return func(c *gin.Context) {
// Block search engines until a public picture wall has been implemented,
// see https://github.com/photoprism/photoprism/issues/669.
c.Header(header.Robots, header.RobotsNone)
}
}

View File

@@ -44,10 +44,15 @@ func Start(ctx context.Context, conf *config.Config) {
log.Warnf("server: %s", err)
}
// Register recovery and logger middleware.
router.Use(Recovery(), Logger())
// Register panic recovery middleware.
router.Use(Recovery())
// If enabled, register compression middleware.
// Register logger middleware if debug mode is enabled.
if conf.Debug() {
router.Use(Logger())
}
// Register compression middleware if enabled in the configuration.
switch conf.HttpCompression() {
case "br", "brotli":
log.Infof("server: brotli compression is currently not supported")
@@ -73,6 +78,9 @@ func Start(ctx context.Context, conf *config.Config) {
// Register security middleware.
router.Use(Security(conf))
// Register robots tag middleware.
router.Use(Robots(conf))
// Create REST API router group.
APIv1 = router.Group(conf.BaseUri(config.ApiUri), Api(conf))

View File

@@ -238,7 +238,7 @@ var CountryNames = map[string]string{
"ua": "Ukraine",
"ae": "United Arab Emirates",
"gb": "United Kingdom",
"us": "USA",
"us": "United States",
"um": "US Minor Outlying Islands",
"uy": "Uruguay",
"uz": "Uzbekistan",

View File

@@ -941,7 +941,7 @@
},
{
"Code": "US",
"Name": "USA"
"Name": "United States"
},
{
"Code": "UM",

View File

@@ -14,7 +14,7 @@ func TestCountryName(t *testing.T) {
t.Run("us", func(t *testing.T) {
result := CountryName("us")
assert.Equal(t, "USA", result)
assert.Equal(t, "United States", result)
})
t.Run("empty", func(t *testing.T) {

View File

@@ -14,4 +14,26 @@ func TestHeader(t *testing.T) {
assert.Equal(t, "Basic", AuthBasic)
assert.Equal(t, "Bearer", AuthBearer)
})
t.Run("Cdn", func(t *testing.T) {
assert.Equal(t, "Cdn-Host", CdnHost)
assert.Equal(t, "Cdn-Mobiledevice", CdnMobileDevice)
assert.Equal(t, "Cdn-Serverzone", CdnServerZone)
assert.Equal(t, "Cdn-Serverid", CdnServerID)
assert.Equal(t, "Cdn-Connectionid", CdnConnectionID)
})
t.Run("Content", func(t *testing.T) {
assert.Equal(t, "Origin", Origin)
assert.Equal(t, "Accept-Encoding", AcceptEncoding)
assert.Equal(t, "Content-Type", ContentType)
assert.Equal(t, "application/json; charset=utf-8", ContentTypeJsonUtf8)
assert.Equal(t, "multipart/form-data", ContentTypeMultipart)
})
t.Run("Robots", func(t *testing.T) {
assert.Equal(t, "X-Robots-Tag", Robots)
assert.Equal(t, "all", RobotsAll)
assert.Equal(t, "noindex, nofollow", RobotsNone)
assert.Equal(t, "noimageindex", RobotsNoImages)
assert.Equal(t, "noindex", RobotsNoIndex)
assert.Equal(t, "nofollow", RobotsNoFollow)
})
}

18
pkg/header/robots.go Normal file
View File

@@ -0,0 +1,18 @@
package header
type RobotsRule = string
// Robots controls how pages are indexed and crawled by search engines:
// https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#xrobotstag
const (
Robots = "X-Robots-Tag"
)
// Standard Robots header values.
const (
RobotsAll RobotsRule = "all"
RobotsNone RobotsRule = "noindex, nofollow"
RobotsNoIndex RobotsRule = "noindex"
RobotsNoFollow RobotsRule = "nofollow"
RobotsNoImages RobotsRule = "noimageindex"
)

View File

@@ -109,6 +109,8 @@ var SpecialWords = map[string]string{
"pcx": "PCX",
"sct": "SCT",
"bpm": "BPM",
"fm": "FM",
"pm": "PM",
"ps": "PS",
"postscript": "PostScript",
"proraw": "ProRAW",
@@ -143,7 +145,6 @@ var SpecialWords = map[string]string{
"fullhd": "FullHD",
"ultrahd": "UltraHD",
"uwqhd": "UWQHD",
"unrwa": "UNRWA",
"nvidia": "NVIDIA",
"geforce": "GeForce",
"iphone": "iPhone",
@@ -249,4 +250,22 @@ var SpecialWords = map[string]string{
"d'honneur": "d'Honneur",
"île-de-france": "Île-de-France",
"ile-de-france": "Île-de-France",
"usni": "USNI",
"usaid": "USAID",
"thaad": "THAAD",
"unrwa": "UNRWA",
"unifil": "UNIFIL",
"irgc": "IRGC",
"cnn": "CNN",
"nbc": "NBC",
"cnbc": "CNBC",
"msnbc": "MSNBC",
"cbs": "CBS",
"bbc": "BBC",
"rbb": "RBB",
"swr": "SWR",
"ndr": "NDR",
"dw": "DW",
"rt": "RT",
"gb": "GB",
}