diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index c742676f9ac..7de6e733d0c 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Golang uses: actions/setup-go@v5 with: - go-version: "1.22.x" + go-version: "1.23.x" check-latest: true - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0a56d4c6cb9..f9df2dd03ce 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/setup-go@v5 with: - go-version: "1.22.x" + go-version: "1.23.x" - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 6e550b43b12..d5ecac7fa2d 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -28,12 +28,12 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: "1.22.x" + go-version: "1.23.x" - run: "go vet ./..." - uses: golangci/golangci-lint-action@v6 with: args: --timeout 10m --skip-dirs tests --disable errcheck --enable sqlclosecheck --enable misspell --enable gofmt --enable goimports --enable whitespace --enable gocritic - uses: dominikh/staticcheck-action@v1.3.1 with: - version: "2023.1.7" + version: "2024.1.1" install-go: false diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index edc4995b663..ff6d16da8b9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: max-parallel: 4 matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - go-version: ["1.22.x"] + go-version: ["1.23.x"] steps: - name: Set up Go uses: actions/setup-go@v5 @@ -43,7 +43,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22.x" + go-version: "1.23.x" - name: Checkout uses: actions/checkout@v4 - name: Install Postgres client diff --git a/.gitignore b/.gitignore index 13bac4e1195..ba53f67dbc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ -miniflux-* +./*.sha256 ./miniflux -*.rpm -*.deb .idea -.vscode \ No newline at end of file +.vscode +*.deb +*.rpm +miniflux-* \ No newline at end of file diff --git a/Makefile b/Makefile index e93f981430b..0925237fd02 100644 --- a/Makefile +++ b/Makefile @@ -51,33 +51,43 @@ miniflux-no-pie: linux-amd64: @ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 linux-arm64: @ CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 linux-armv7: @ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 linux-armv6: @ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 linux-armv5: @ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 darwin-amd64: @ GOOS=darwin GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 darwin-arm64: @ GOOS=darwin GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 freebsd-amd64: @ CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 openbsd-amd64: @ GOOS=openbsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go + @ sha256sum $(APP)-$@ > $(APP)-$@.sha256 windows-amd64: @ GOOS=windows GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@.exe main.go + @ sha256sum $(APP)-$@.exe > $(APP)-$@.exe.sha256 build: linux-amd64 linux-arm64 linux-armv7 linux-armv6 linux-armv5 darwin-amd64 darwin-arm64 freebsd-amd64 openbsd-amd64 windows-amd64 @@ -104,7 +114,7 @@ run: @ LOG_DATE_TIME=1 LOG_LEVEL=debug RUN_MIGRATIONS=1 CREATE_ADMIN=1 ADMIN_USERNAME=admin ADMIN_PASSWORD=test123 go run main.go clean: - @ rm -f $(APP)-* $(APP) $(APP)*.rpm $(APP)*.deb $(APP)*.exe + @ rm -f $(APP)-* $(APP) $(APP)*.rpm $(APP)*.deb $(APP)*.exe $(APP)*.sha256 test: go test -cover -race -count=1 ./... diff --git a/client/client.go b/client/client.go index 81f2401f26d..71ced695583 100644 --- a/client/client.go +++ b/client/client.go @@ -709,6 +709,10 @@ func buildFilterQueryString(path string, filter *Filter) string { values.Set("feed_id", strconv.FormatInt(filter.FeedID, 10)) } + if filter.GloballyVisible { + values.Set("globally_visible", "true") + } + for _, status := range filter.Statuses { values.Add("status", status) } diff --git a/client/model.go b/client/model.go index b6095145583..69f2c227b8a 100644 --- a/client/model.go +++ b/client/model.go @@ -283,6 +283,7 @@ type Filter struct { CategoryID int64 FeedID int64 Statuses []string + GloballyVisible bool } // EntryResultSet represents the response when fetching entries. diff --git a/go.mod b/go.mod index 35e2af9d4cb..5b2a250ad6b 100644 --- a/go.mod +++ b/go.mod @@ -10,14 +10,14 @@ require ( github.com/go-webauthn/webauthn v0.10.2 github.com/gorilla/mux v1.8.1 github.com/lib/pq v1.10.9 - github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_golang v1.20.0 github.com/tdewolff/minify/v2 v2.20.37 github.com/yuin/goldmark v1.7.4 - golang.org/x/crypto v0.25.0 - golang.org/x/net v0.27.0 - golang.org/x/oauth2 v0.21.0 - golang.org/x/term v0.22.0 - golang.org/x/text v0.16.0 + golang.org/x/crypto v0.26.0 + golang.org/x/net v0.28.0 + golang.org/x/oauth2 v0.22.0 + golang.org/x/term v0.23.0 + golang.org/x/text v0.17.0 mvdan.cc/xurls/v2 v2.5.0 ) @@ -30,18 +30,20 @@ require ( require ( github.com/andybalholm/cascadia v1.3.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/fxamacker/cbor/v2 v2.6.0 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/tdewolff/parse/v2 v2.7.15 // indirect github.com/x448/float16 v0.8.4 // indirect - golang.org/x/sys v0.22.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/sys v0.23.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect ) go 1.22 diff --git a/go.sum b/go.sum index 74508b5b530..0a90139caf2 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -32,20 +32,26 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +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.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tdewolff/minify/v2 v2.20.37 h1:Q97cx4STXCh1dlWDlNHZniE8BJ2EBL0+2b0n92BJQhw= @@ -62,8 +68,8 @@ github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -71,10 +77,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -85,28 +91,28 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= diff --git a/internal/api/api_integration_test.go b/internal/api/api_integration_test.go index 8e428b47e24..3fd98119268 100644 --- a/internal/api/api_integration_test.go +++ b/internal/api/api_integration_test.go @@ -1986,6 +1986,64 @@ func TestGetAllEntriesEndpointWithFilter(t *testing.T) { } } +func TestGetGlobalEntriesEndpoint(t *testing.T) { + testConfig := newIntegrationTestConfig() + if !testConfig.isConfigured() { + t.Skip(skipIntegrationTestsMessage) + } + + adminClient := miniflux.NewClient(testConfig.testBaseURL, testConfig.testAdminUsername, testConfig.testAdminPassword) + + regularTestUser, err := adminClient.CreateUser(testConfig.genRandomUsername(), testConfig.testRegularPassword, false) + if err != nil { + t.Fatal(err) + } + defer adminClient.DeleteUser(regularTestUser.ID) + + regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword) + + feedID, err := regularUserClient.CreateFeed(&miniflux.FeedCreationRequest{ + FeedURL: testConfig.testFeedURL, + HideGlobally: true, + }) + + if err != nil { + t.Fatal(err) + } + + feedIDEntry, err := regularUserClient.Feed(feedID) + + if err != nil { + t.Fatal(err) + } + + if feedIDEntry.HideGlobally != true { + t.Fatalf(`Expected feed to have globally_hidden set to true, was false.`) + } + + /* Not filtering on GloballyVisible should return all entries */ + feedEntries, err := regularUserClient.Entries(&miniflux.Filter{FeedID: feedID}) + + if err != nil { + t.Fatal(err) + } + + if len(feedEntries.Entries) == 0 { + t.Fatalf(`Expected entries but response contained none.`) + } + + /* Feed is hidden globally, so this should be empty */ + globallyVisibleEntries, err := regularUserClient.Entries(&miniflux.Filter{GloballyVisible: true}) + + if err != nil { + t.Fatal(err) + } + + if len(globallyVisibleEntries.Entries) != 0 { + t.Fatalf(`Expected no entries, got %d`, len(globallyVisibleEntries.Entries)) + } +} + func TestUpdateEnclosureEndpoint(t *testing.T) { testConfig := newIntegrationTestConfig() if !testConfig.isConfigured() { diff --git a/internal/api/entry.go b/internal/api/entry.go index fd06c70a418..508bbee451c 100644 --- a/internal/api/entry.go +++ b/internal/api/entry.go @@ -136,6 +136,15 @@ func (h *handler) findEntries(w http.ResponseWriter, r *http.Request, feedID int builder.WithLimit(limit) builder.WithTags(tags) builder.WithEnclosures() + + if request.HasQueryParam(r, "globally_visible") { + globallyVisible := request.QueryBoolParam(r, "globally_visible", true) + + if globallyVisible { + builder.WithGloballyVisible() + } + } + configureFilters(builder, r) entries, err := builder.GetEntries() diff --git a/internal/cli/cli.go b/internal/cli/cli.go index f56bb959a87..ca4f47bd48b 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -4,6 +4,7 @@ package cli // import "miniflux.app/v2/internal/cli" import ( + "errors" "flag" "fmt" "io" @@ -88,6 +89,23 @@ func Parse() { printErrorAndExit(err) } + if oauth2Provider := config.Opts.OAuth2Provider(); oauth2Provider != "" { + if oauth2Provider != "oidc" && oauth2Provider != "google" { + printErrorAndExit(fmt.Errorf(`unsupported OAuth2 provider: %q (Possible values are "google" or "oidc")`, oauth2Provider)) + } + } + + if config.Opts.DisableLocalAuth() { + switch { + case config.Opts.OAuth2Provider() == "" && config.Opts.AuthProxyHeader() == "": + printErrorAndExit(errors.New("DISABLE_LOCAL_AUTH is enabled but neither OAUTH2_PROVIDER nor AUTH_PROXY_HEADER is not set. Please enable at least one authentication source")) + case config.Opts.OAuth2Provider() != "" && !config.Opts.IsOAuth2UserCreationAllowed(): + printErrorAndExit(errors.New("DISABLE_LOCAL_AUTH is enabled and an OAUTH2_PROVIDER is configured, but OAUTH2_USER_CREATION is not enabled")) + case config.Opts.AuthProxyHeader() != "" && !config.Opts.IsAuthProxyUserCreationAllowed(): + printErrorAndExit(errors.New("DISABLE_LOCAL_AUTH is enabled and an AUTH_PROXY_HEADER is configured, but AUTH_PROXY_USER_CREATION is not enabled")) + } + } + if flagConfigDump { fmt.Print(config.Opts) return diff --git a/internal/config/options.go b/internal/config/options.go index d2536070b6d..303c8ff3d67 100644 --- a/internal/config/options.go +++ b/internal/config/options.go @@ -69,7 +69,9 @@ const ( defaultOAuth2ClientSecret = "" defaultOAuth2RedirectURL = "" defaultOAuth2OidcDiscoveryEndpoint = "" + defaultOauth2OidcProviderName = "OpenID Connect" defaultOAuth2Provider = "" + defaultDisableLocalAuth = false defaultPocketConsumerKey = "" defaultHTTPClientTimeout = 20 defaultHTTPClientMaxBodySize = 15 @@ -153,7 +155,9 @@ type Options struct { oauth2ClientSecret string oauth2RedirectURL string oidcDiscoveryEndpoint string + oidcProviderName string oauth2Provider string + disableLocalAuth bool pocketConsumerKey string httpClientTimeout int httpClientMaxBodySize int64 @@ -230,7 +234,9 @@ func NewOptions() *Options { oauth2ClientSecret: defaultOAuth2ClientSecret, oauth2RedirectURL: defaultOAuth2RedirectURL, oidcDiscoveryEndpoint: defaultOAuth2OidcDiscoveryEndpoint, + oidcProviderName: defaultOauth2OidcProviderName, oauth2Provider: defaultOAuth2Provider, + disableLocalAuth: defaultDisableLocalAuth, pocketConsumerKey: defaultPocketConsumerKey, httpClientTimeout: defaultHTTPClientTimeout, httpClientMaxBodySize: defaultHTTPClientMaxBodySize * 1024 * 1024, @@ -451,11 +457,21 @@ func (o *Options) OIDCDiscoveryEndpoint() string { return o.oidcDiscoveryEndpoint } +// OIDCProviderName returns the OAuth2 OIDC provider's display name +func (o *Options) OIDCProviderName() string { + return o.oidcProviderName +} + // OAuth2Provider returns the name of the OAuth2 provider configured. func (o *Options) OAuth2Provider() string { return o.oauth2Provider } +// DisableLocalAUth returns true if the local user database should not be used to authenticate users +func (o *Options) DisableLocalAuth() bool { + return o.disableLocalAuth +} + // HasHSTS returns true if HTTP Strict Transport Security is enabled. func (o *Options) HasHSTS() bool { return o.hsts @@ -692,9 +708,11 @@ func (o *Options) SortedOptions(redactSecret bool) []*Option { "OAUTH2_CLIENT_ID": o.oauth2ClientID, "OAUTH2_CLIENT_SECRET": redactSecretValue(o.oauth2ClientSecret, redactSecret), "OAUTH2_OIDC_DISCOVERY_ENDPOINT": o.oidcDiscoveryEndpoint, + "OAUTH2_OIDC_PROVIDER_NAME": o.oidcProviderName, "OAUTH2_PROVIDER": o.oauth2Provider, "OAUTH2_REDIRECT_URL": o.oauth2RedirectURL, "OAUTH2_USER_CREATION": o.oauth2UserCreationAllowed, + "DISABLE_LOCAL_AUTH": o.disableLocalAuth, "POCKET_CONSUMER_KEY": redactSecretValue(o.pocketConsumerKey, redactSecret), "POLLING_FREQUENCY": o.pollingFrequency, "FORCE_REFRESH_INTERVAL": o.forceRefreshInterval, diff --git a/internal/config/parser.go b/internal/config/parser.go index 9ea4053cb43..b443bae0ef0 100644 --- a/internal/config/parser.go +++ b/internal/config/parser.go @@ -225,8 +225,12 @@ func (p *Parser) parseLines(lines []string) (err error) { p.opts.oauth2RedirectURL = parseString(value, defaultOAuth2RedirectURL) case "OAUTH2_OIDC_DISCOVERY_ENDPOINT": p.opts.oidcDiscoveryEndpoint = parseString(value, defaultOAuth2OidcDiscoveryEndpoint) + case "OAUTH2_OIDC_PROVIDER_NAME": + p.opts.oidcProviderName = parseString(value, defaultOauth2OidcProviderName) case "OAUTH2_PROVIDER": p.opts.oauth2Provider = parseString(value, defaultOAuth2Provider) + case "DISABLE_LOCAL_AUTH": + p.opts.disableLocalAuth = parseBool(value, defaultDisableLocalAuth) case "HTTP_CLIENT_TIMEOUT": p.opts.httpClientTimeout = parseInt(value, defaultHTTPClientTimeout) case "HTTP_CLIENT_MAX_BODY_SIZE": diff --git a/internal/database/database.go b/internal/database/database.go index e5a2f3a5b3c..859aa917e5b 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -32,7 +32,7 @@ func Migrate(db *sql.DB) error { var currentVersion int db.QueryRow(`SELECT version FROM schema_version`).Scan(¤tVersion) - slog.Debug("Running database migrations", + slog.Info("Running database migrations", slog.Int("current_version", currentVersion), slog.Int("latest_version", schemaVersion), ) diff --git a/internal/fever/handler.go b/internal/fever/handler.go index 45455cf4857..ef1c39c7de3 100644 --- a/internal/fever/handler.go +++ b/internal/fever/handler.go @@ -247,7 +247,6 @@ func (h *handler) handleItems(w http.ResponseWriter, r *http.Request) { builder := h.store.NewEntryQueryBuilder(userID) builder.WithoutStatus(model.EntryStatusRemoved) builder.WithLimit(50) - builder.WithSorting("id", model.DefaultSortingDirection) switch { case request.HasQueryParam(r, "since_id"): @@ -258,6 +257,7 @@ func (h *handler) handleItems(w http.ResponseWriter, r *http.Request) { slog.Int64("since_id", sinceID), ) builder.AfterEntryID(sinceID) + builder.WithSorting("id", "ASC") } case request.HasQueryParam(r, "max_id"): maxID := request.QueryInt64Param(r, "max_id", 0) diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index 9f32999c63f..3de1e04e659 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -210,8 +210,8 @@ "page.settings.title": "Einstellungen", "page.settings.link_google_account": "Google-Konto verknüpfen", "page.settings.unlink_google_account": "Verknüpfung mit Google-Konto entfernen", - "page.settings.link_oidc_account": "OpenID-Connect-Konto verknüpfen", - "page.settings.unlink_oidc_account": "Verknüpfung mit OpenID-Connect-Konto entfernen", + "page.settings.link_oidc_account": "%s-Konto verknüpfen", + "page.settings.unlink_oidc_account": "Verknüpfung mit %s-Konto entfernen", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Aktionen", "page.settings.webauthn.passkey_name": "Name des Passkeys", @@ -225,7 +225,7 @@ ], "page.login.title": "Anmeldung", "page.login.google_signin": "Anmeldung mit Google", - "page.login.oidc_signin": "Anmeldung mit OpenID Connect", + "page.login.oidc_signin": "Anmeldung mit %s", "page.login.webauthn_login": "Melden Sie sich mit dem Passkey an", "page.login.webauthn_login.error": "Anmeldung mit Passkey nicht möglich", "page.integrations.title": "Dienste", diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index b7047da0a15..229bee7353a 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -210,8 +210,8 @@ "page.settings.title": "Ρυθμίσεις", "page.settings.link_google_account": "Σύνδεση του λογαριασμό μου Google", "page.settings.unlink_google_account": "Αποσύνδεση του λογαριασμού μου Google", - "page.settings.link_oidc_account": "Σύνδεση του λογαριασμού μου OpenID Connect", - "page.settings.unlink_oidc_account": "Αποσύνδεση του λογαριασμού μου OpenID Connect", + "page.settings.link_oidc_account": "Σύνδεση του λογαριασμού μου %s", + "page.settings.unlink_oidc_account": "Αποσύνδεση του λογαριασμού μου %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Είσοδος", "page.login.google_signin": "Συνδεθείτε με τo Google", - "page.login.oidc_signin": "Συνδεθείτε με το OpenID Connect", + "page.login.oidc_signin": "Συνδεθείτε με το %s", "page.login.webauthn_login": "Είσοδος με κωδικό πρόσβασης", "page.login.webauthn_login.error": "Δεν είναι δυνατή η σύνδεση με κωδικό πρόσβασης", "page.integrations.title": "Ενσωμάτωση", diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index f2fd6384af5..87c5af58264 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -210,8 +210,8 @@ "page.settings.title": "Settings", "page.settings.link_google_account": "Link my Google account", "page.settings.unlink_google_account": "Unlink my Google account", - "page.settings.link_oidc_account": "Link my OpenID Connect account", - "page.settings.unlink_oidc_account": "Unlink my OpenID Connect account", + "page.settings.link_oidc_account": "Link my %s account", + "page.settings.unlink_oidc_account": "Unlink my %s account", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Sign In", "page.login.google_signin": "Sign in with Google", - "page.login.oidc_signin": "Sign in with OpenID Connect", + "page.login.oidc_signin": "Sign in with %s", "page.login.webauthn_login": "Login with passkey", "page.login.webauthn_login.error": "Unable to login with passkey", "page.integrations.title": "Integrations", diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index 232d1a6cf39..a0cc10349d6 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -210,8 +210,8 @@ "page.settings.title": "Ajustes", "page.settings.link_google_account": "Vincular mi cuenta de Google", "page.settings.unlink_google_account": "Desvincular mi cuenta de Google", - "page.settings.link_oidc_account": "Vincular mi cuenta de OpenID Connect", - "page.settings.unlink_oidc_account": "Desvincular mi cuenta de OpenID Connect", + "page.settings.link_oidc_account": "Vincular mi cuenta de %s", + "page.settings.unlink_oidc_account": "Desvincular mi cuenta de %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Iniciar sesión", "page.login.google_signin": "Iniciar sesión con tu cuenta de Google", - "page.login.oidc_signin": "Iniciar sesión con tu cuenta de OpenID Connect", + "page.login.oidc_signin": "Iniciar sesión con tu cuenta de %s", "page.login.webauthn_login": "Iniciar sesión con clave de acceso", "page.login.webauthn_login.error": "No se puede iniciar sesión con la clave de paso", "page.integrations.title": "Integraciones", diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index ec9de09a469..0f3e6ea659b 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -210,8 +210,8 @@ "page.settings.title": "Asetukset", "page.settings.link_google_account": "Linkitä Google-tilini", "page.settings.unlink_google_account": "Poista Google-tilini linkitys", - "page.settings.link_oidc_account": "Linkitä OpenID Connect -tilini", - "page.settings.unlink_oidc_account": "Poista OpenID Connect -tilini linkitys", + "page.settings.link_oidc_account": "Linkitä %s -tilini", + "page.settings.unlink_oidc_account": "Poista %s -tilini linkitys", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Kirjaudu sisään", "page.login.google_signin": "Kirjaudu sisään Googlella", - "page.login.oidc_signin": "Kirjaudu sisään OpenID Connectilla", + "page.login.oidc_signin": "Kirjaudu sisään %silla", "page.login.webauthn_login": "Kirjaudu sisään salasanalla", "page.login.webauthn_login.error": "Ei voida kirjautua sisään salasanalla", "page.integrations.title": "Integraatiot", diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index 125ca165ecd..ddd4d47150f 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -210,8 +210,8 @@ "page.settings.title": "Réglages", "page.settings.link_google_account": "Associer mon compte Google", "page.settings.unlink_google_account": "Dissocier mon compte Google", - "page.settings.link_oidc_account": "Associer mon compte OpenID Connect", - "page.settings.unlink_oidc_account": "Dissocier mon compte OpenID Connect", + "page.settings.link_oidc_account": "Associer mon compte %s", + "page.settings.unlink_oidc_account": "Dissocier mon compte %s", "page.settings.webauthn.passkeys": "Clés d’accès", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Nom de la clé d’accès", @@ -225,7 +225,7 @@ ], "page.login.title": "Connexion", "page.login.google_signin": "Se connecter avec Google", - "page.login.oidc_signin": "Se connecter avec OpenID Connect", + "page.login.oidc_signin": "Se connecter avec %s", "page.login.webauthn_login": "Se connecter avec une clé d’accès", "page.login.webauthn_login.error": "Impossible de se connecter avec la clé d’accès", "page.integrations.title": "Intégrations", diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index 6c2ca393609..918062a8e0d 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -210,8 +210,8 @@ "page.settings.title": "समायोजन", "page.settings.link_google_account": "मेरा गूगल खाता जोरीय", "page.settings.unlink_google_account": "मेरा गूगल खाता हटाय", - "page.settings.link_oidc_account": "मेरा ओपन-ईद खाता जोरीय", - "page.settings.unlink_oidc_account": "मेरा ओपन-ईद खाता हटाय", + "page.settings.link_oidc_account": "मेरा ओपन-ईद खाता जोरीय (%s)", + "page.settings.unlink_oidc_account": "मेरा ओपन-ईद खाता हटाय (%s)", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "साइन इन करें", "page.login.google_signin": "गूगल के साथ साइन इन करें", - "page.login.oidc_signin": "ओपन-ईद के साथ साइन इन करें", + "page.login.oidc_signin": "ओपन-ईद के साथ साइन इन करें (%s)", "page.login.webauthn_login": "पासकी से लॉगिन करें", "page.login.webauthn_login.error": "पासकी से लॉगिन करने में असमर्थ", "page.integrations.title": "एकीकरण", diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index 555ed1ef877..e63f39c7cdf 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -201,8 +201,8 @@ "page.settings.title": "Pengaturan", "page.settings.link_google_account": "Tautkan akun Google saya", "page.settings.unlink_google_account": "Putuskan akun Google saya", - "page.settings.link_oidc_account": "Tautkan akun OpenID Connect saya", - "page.settings.unlink_oidc_account": "Putuskan akun OpenID Connect saya", + "page.settings.link_oidc_account": "Tautkan akun %s saya", + "page.settings.unlink_oidc_account": "Putuskan akun %s saya", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -215,7 +215,7 @@ ], "page.login.title": "Masuk", "page.login.google_signin": "Masuk dengan Google", - "page.login.oidc_signin": "Masuk dengan OpenID Connect", + "page.login.oidc_signin": "Masuk dengan %s", "page.login.webauthn_login": "Login with passkey", "page.login.webauthn_login.error": "Unable to login with passkey", "page.integrations.title": "Integrasi", diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index d77f03570c2..1c8f7a314f9 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -210,8 +210,8 @@ "page.settings.title": "Impostazioni", "page.settings.link_google_account": "Collega il mio account Google", "page.settings.unlink_google_account": "Scollega il mio account Google", - "page.settings.link_oidc_account": "Collega il mio account OpenID Connect", - "page.settings.unlink_oidc_account": "Scollega il mio account OpenID Connect", + "page.settings.link_oidc_account": "Collega il mio account %s", + "page.settings.unlink_oidc_account": "Scollega il mio account %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Accedi", "page.login.google_signin": "Accedi tramite Google", - "page.login.oidc_signin": "Accedi tramite OpenID Connect", + "page.login.oidc_signin": "Accedi tramite %s", "page.login.webauthn_login": "Accedi con passkey", "page.login.webauthn_login.error": "Impossibile accedere con passkey", "page.integrations.title": "Integrazioni", diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 57d62d7cba8..56ba13607a5 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -201,8 +201,8 @@ "page.settings.title": "設定", "page.settings.link_google_account": "Google アカウントと接続する", "page.settings.unlink_google_account": "Google アカウントと接続を解除する", - "page.settings.link_oidc_account": "OpenID Connect アカウントと接続する", - "page.settings.unlink_oidc_account": "OpenID Connect アカウントと接続を解除する", + "page.settings.link_oidc_account": "%s アカウントと接続する", + "page.settings.unlink_oidc_account": "%s アカウントと接続を解除する", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -215,7 +215,7 @@ ], "page.login.title": "ログイン", "page.login.google_signin": "Google アカウントでログイン", - "page.login.oidc_signin": "OpenID Connect アカウントでログイン", + "page.login.oidc_signin": "%s アカウントでログイン", "page.login.webauthn_login": "パスキーでログイン", "page.login.webauthn_login.error": "パスキーでログインできない", "page.integrations.title": "連携", diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index 30321a4949c..fc7db3e9974 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -211,8 +211,8 @@ "page.settings.title": "Instellingen", "page.settings.link_google_account": "Koppel mijn Google-account", "page.settings.unlink_google_account": "Ontkoppel mijn Google-account", - "page.settings.link_oidc_account": "Koppel mijn OpenID Connect-account", - "page.settings.unlink_oidc_account": "Ontkoppel mijn OpenID Connect-account", + "page.settings.link_oidc_account": "Koppel mijn %s-account", + "page.settings.unlink_oidc_account": "Ontkoppel mijn %s-account", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -224,7 +224,7 @@ "Verwijder %d wachtwoord", "Verwijder %d wachtwoordsleutels" ], - "page.login.oidc_signin": "Inloggen via OpenID Connect", + "page.login.oidc_signin": "Inloggen via %s", "page.login.webauthn_login": "Inloggen met wachtwoord", "page.login.webauthn_login.error": "Kan niet inloggen met wachtwoord", "page.login.google_signin": "Inloggen via Google", diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 35c99095b7a..ecd1f540cac 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -219,8 +219,8 @@ "page.settings.title": "Ustawienia", "page.settings.link_google_account": "Połącz z moim kontem Google", "page.settings.unlink_google_account": "Odłącz moje konto Google", - "page.settings.link_oidc_account": "Połącz z moim kontem OpenID Connect", - "page.settings.unlink_oidc_account": "Odłącz moje konto OpenID Connect", + "page.settings.link_oidc_account": "Połącz z moim kontem %s", + "page.settings.unlink_oidc_account": "Odłącz moje konto %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -235,7 +235,7 @@ ], "page.login.title": "Zaloguj się", "page.login.google_signin": "Zaloguj przez Google", - "page.login.oidc_signin": "Zaloguj przez OpenID Connect", + "page.login.oidc_signin": "Zaloguj przez %s", "page.login.webauthn_login": "Zaloguj się za pomocą hasła", "page.login.webauthn_login.error": "Nie można zalogować się za pomocą klucza dostępu", "page.integrations.title": "Usługi", diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index 0a6f85666aa..3c1c839098b 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -210,8 +210,8 @@ "page.settings.title": "Ajustes", "page.settings.link_google_account": "Vincular minha conta do Google", "page.settings.unlink_google_account": "Desvincular minha conta do Google", - "page.settings.link_oidc_account": "Vincular minha conta do OpenID Connect", - "page.settings.unlink_oidc_account": "Desvincular minha conta do OpenID Connect", + "page.settings.link_oidc_account": "Vincular minha conta do %s", + "page.settings.unlink_oidc_account": "Desvincular minha conta do %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -225,7 +225,7 @@ ], "page.login.title": "Iniciar Sessão", "page.login.google_signin": "Iniciar Sessão com sua conta do Google", - "page.login.oidc_signin": "Iniciar Sessão com sua conta do OpenID Connect", + "page.login.oidc_signin": "Iniciar Sessão com sua conta do %s", "page.login.webauthn_login": "Entrar com senha", "page.login.webauthn_login.error": "Não é possível fazer login com senha", "page.integrations.title": "Integrações", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index 5818e23717e..fd214374e1f 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -219,8 +219,8 @@ "page.settings.title": "Настройки", "page.settings.link_google_account": "Привязать мой Google аккаунт", "page.settings.unlink_google_account": "Отвязать мой Google аккаунт", - "page.settings.link_oidc_account": "Привязать мой OpenID Connect аккаунт", - "page.settings.unlink_oidc_account": "Отвязать мой OpenID Connect аккаунт", + "page.settings.link_oidc_account": "Привязать мой %s аккаунт", + "page.settings.unlink_oidc_account": "Отвязать мой %s аккаунт", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -235,7 +235,7 @@ ], "page.login.title": "Войти", "page.login.google_signin": "Войти с помощью Google", - "page.login.oidc_signin": "Войти с помощью OpenID Connect", + "page.login.oidc_signin": "Войти с помощью %s", "page.login.webauthn_login": "Войти с паролем", "page.login.webauthn_login.error": "Невозможно войти с паролем", "page.integrations.title": "Интеграции", diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index 3366dc7de9e..ac150d24090 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -455,7 +455,7 @@ "page.keyboard_shortcuts.toggle_read_status_next": "Okundu/okunmadı arasında geçiş yap, sonrakine odaklan", "page.keyboard_shortcuts.toggle_read_status_prev": "Okundu/okunmadı arasında geçiş yap, öncekine odaklan", "page.login.google_signin": "Google ile oturum aç", - "page.login.oidc_signin": "OpenID Connect ile oturum aç", + "page.login.oidc_signin": "%s ile oturum aç", "page.login.title": "Oturum aç", "page.login.webauthn_login": "Passkey ile giriş yap", "page.login.webauthn_login.error": "Passkey ile giriş yapılamıyor", @@ -474,10 +474,10 @@ "page.sessions.table.user_agent": "User Agent", "page.sessions.title": "Oturumlar", "page.settings.link_google_account": "Google hesabımı bağla", - "page.settings.link_oidc_account": "OpenID Connect hesabımı bağla", + "page.settings.link_oidc_account": "%s hesabımı bağla", "page.settings.title": "Ayarlar", "page.settings.unlink_google_account": "Google hesabımın bağlantısını kaldır", - "page.settings.unlink_oidc_account": "OpenID Connect hesabımın bağlantısını kaldır", + "page.settings.unlink_oidc_account": "%s hesabımın bağlantısını kaldır", "page.settings.webauthn.actions": "Eylemler", "page.settings.webauthn.added_on": "Eklendi", "page.settings.webauthn.delete": [ diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 72fc9d34776..2bebf3cd58e 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -219,8 +219,8 @@ "page.settings.title": "Налаштування ", "page.settings.link_google_account": "Підключити мій обліковий запис Google", "page.settings.unlink_google_account": "Відключити мій обліковий запис Google", - "page.settings.link_oidc_account": "Підключити мій обліковий запис OpenID Connect", - "page.settings.unlink_oidc_account": "Відключити мій обліковий запис OpenID Connect", + "page.settings.link_oidc_account": "Підключити мій обліковий запис %s", + "page.settings.unlink_oidc_account": "Відключити мій обліковий запис %s", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "Actions", "page.settings.webauthn.passkey_name": "Passkey Name", @@ -235,7 +235,7 @@ ], "page.login.title": "Вхід", "page.login.google_signin": "Увійти через Google", - "page.login.oidc_signin": "Увійти через OpenID Connect", + "page.login.oidc_signin": "Увійти через %s", "page.login.webauthn_login": "Увійти за допомогою пароля", "page.login.webauthn_login.error": "Неможливо ввійти за допомогою ключа доступу", "page.integrations.title": "Інтеграції", diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index 0d5be6f2ee3..f96342fe79b 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -201,8 +201,8 @@ "page.settings.title": "设置", "page.settings.link_google_account": "关联我的 Google 账户", "page.settings.unlink_google_account": "解除 Google 账号关联", - "page.settings.link_oidc_account": "关联我的 OpenID Connect 账户", - "page.settings.unlink_oidc_account": "解除 OpenID Connect 账号关联", + "page.settings.link_oidc_account": "关联我的 %s 账户", + "page.settings.unlink_oidc_account": "解除 %s 账号关联", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "操作", "page.settings.webauthn.passkey_name": "Passkey 名称", @@ -215,7 +215,7 @@ ], "page.login.title": "登录", "page.login.google_signin": "使用 Google 登录", - "page.login.oidc_signin": "使用 OpenID Connect 登录", + "page.login.oidc_signin": "使用 %s 登录", "page.login.webauthn_login": "使用密码登录", "page.login.webauthn_login.error": "无法使用密码登录", "page.integrations.title": "集成", diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index f0e2ea8b1b7..b2f5ea7c441 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -201,8 +201,8 @@ "page.settings.title": "設定", "page.settings.link_google_account": "關聯我的 Google 賬戶", "page.settings.unlink_google_account": "解除 Google 帳號關聯", - "page.settings.link_oidc_account": "關聯我的 OpenID Connect 賬戶", - "page.settings.unlink_oidc_account": "解除 OpenID Connect 帳號關聯", + "page.settings.link_oidc_account": "關聯我的 %s 賬戶", + "page.settings.unlink_oidc_account": "解除 %s 帳號關聯", "page.settings.webauthn.passkeys": "Passkeys", "page.settings.webauthn.actions": "操作", "page.settings.webauthn.passkey_name": "Passkey 名稱", @@ -215,7 +215,7 @@ ], "page.login.title": "登入", "page.login.google_signin": "使用 Google 登入", - "page.login.oidc_signin": "使用 OpenID Connect 登入", + "page.login.oidc_signin": "使用 %s 登入", "page.login.webauthn_login": "使用密碼登錄", "page.login.webauthn_login.error": "無法使用密碼登錄", "page.integrations.title": "整合", diff --git a/internal/reader/handler/handler.go b/internal/reader/handler/handler.go index 2663b3b5c7b..3a588b0418c 100644 --- a/internal/reader/handler/handler.go +++ b/internal/reader/handler/handler.go @@ -169,6 +169,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model subscription.BlocklistRules = feedCreationRequest.BlocklistRules subscription.KeeplistRules = feedCreationRequest.KeeplistRules subscription.UrlRewriteRules = feedCreationRequest.UrlRewriteRules + subscription.HideGlobally = feedCreationRequest.HideGlobally subscription.EtagHeader = responseHandler.ETag() subscription.LastModifiedHeader = responseHandler.LastModified() subscription.FeedURL = responseHandler.EffectiveURL() diff --git a/internal/storage/entry_query_builder.go b/internal/storage/entry_query_builder.go index 6bc475fc489..1245e1d4cba 100644 --- a/internal/storage/entry_query_builder.go +++ b/internal/storage/entry_query_builder.go @@ -402,13 +402,13 @@ func (e *EntryQueryBuilder) GetEntryIDs() ([]int64, error) { query := ` SELECT e.id - FROM + FROM entries e LEFT JOIN feeds f ON - f.id=e.feed_id - WHERE + f.id=e.feed_id + WHERE %s %s ` diff --git a/internal/template/functions.go b/internal/template/functions.go index cfbfc53d785..a084db86c70 100644 --- a/internal/template/functions.go +++ b/internal/template/functions.go @@ -32,13 +32,15 @@ type funcMap struct { // Map returns a map of template functions that are compiled during template parsing. func (f *funcMap) Map() template.FuncMap { return template.FuncMap{ - "formatFileSize": formatFileSize, - "dict": dict, - "hasKey": hasKey, - "truncate": truncate, - "isEmail": isEmail, - "baseURL": config.Opts.BaseURL, - "rootURL": config.Opts.RootURL, + "formatFileSize": formatFileSize, + "dict": dict, + "hasKey": hasKey, + "truncate": truncate, + "isEmail": isEmail, + "baseURL": config.Opts.BaseURL, + "rootURL": config.Opts.RootURL, + "disableLocalAuth": config.Opts.DisableLocalAuth, + "oidcProviderName": config.Opts.OIDCProviderName, "hasOAuth2Provider": func(provider string) bool { return config.Opts.OAuth2Provider() == provider }, diff --git a/internal/template/templates/views/login.html b/internal/template/templates/views/login.html index 56b8ac74602..ff642231eba 100644 --- a/internal/template/templates/views/login.html +++ b/internal/template/templates/views/login.html @@ -5,6 +5,7 @@ {{ define "content"}}
+ {{ if not disableLocalAuth }}
@@ -22,6 +23,7 @@
+ {{ end }} {{ if .webAuthnEnabled }}
{{ else if hasOAuth2Provider "oidc" }} {{ end }}
diff --git a/internal/template/templates/views/settings.html b/internal/template/templates/views/settings.html index ce60a808b64..99ac5863fdb 100644 --- a/internal/template/templates/views/settings.html +++ b/internal/template/templates/views/settings.html @@ -15,6 +15,7 @@

{{ t "page.settings.title" }}

{{ end }} + {{ if not disableLocalAuth }}
{{ t "form.prefs.fieldset.authentication_settings" }} @@ -38,9 +39,9 @@

{{ t "page.settings.title" }}

{{ else if hasOAuth2Provider "oidc" }}
{{ if .user.OpenIDConnectID }} - {{ t "page.settings.unlink_oidc_account" }} + {{ t "page.settings.unlink_oidc_account" oidcProviderName }} {{ else }} - {{ t "page.settings.link_oidc_account" }} + {{ t "page.settings.link_oidc_account" oidcProviderName }} {{ end }}
{{ end }} @@ -49,6 +50,7 @@

{{ t "page.settings.title" }}

+ {{ end }} {{ if .webAuthnEnabled }}
diff --git a/internal/ui/form/settings.go b/internal/ui/form/settings.go index b4ac41cc0c1..8b79ba88e66 100644 --- a/internal/ui/form/settings.go +++ b/internal/ui/form/settings.go @@ -7,6 +7,7 @@ import ( "net/http" "strconv" + "miniflux.app/v2/internal/config" "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" ) @@ -86,7 +87,9 @@ func ExtractMarkAsReadBehavior(behavior MarkReadBehavior) (markReadOnView, markR // Merge updates the fields of the given user. func (s *SettingsForm) Merge(user *model.User) *model.User { - user.Username = s.Username + if !config.Opts.DisableLocalAuth() { + user.Username = s.Username + } user.Theme = s.Theme user.Language = s.Language user.Timezone = s.Timezone @@ -120,7 +123,7 @@ func (s *SettingsForm) Merge(user *model.User) *model.User { // Validate makes sure the form values are valid. func (s *SettingsForm) Validate() *locale.LocalizedError { - if s.Username == "" || s.Theme == "" || s.Language == "" || s.Timezone == "" || s.EntryDirection == "" || s.DisplayMode == "" || s.DefaultHomePage == "" { + if (s.Username == "" && !config.Opts.DisableLocalAuth()) || s.Theme == "" || s.Language == "" || s.Timezone == "" || s.EntryDirection == "" || s.DisplayMode == "" || s.DefaultHomePage == "" { return locale.NewLocalizedError("error.settings_mandatory_fields") } diff --git a/internal/ui/login_check.go b/internal/ui/login_check.go index b870cf5739e..eb3c672041b 100644 --- a/internal/ui/login_check.go +++ b/internal/ui/login_check.go @@ -21,9 +21,18 @@ import ( func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) { clientIP := request.ClientIP(r) sess := session.New(h.store, request.SessionID(r)) - authForm := form.NewAuthForm(r) - view := view.New(h.tpl, r, sess) + + if config.Opts.DisableLocalAuth() { + slog.Warn("blocking local auth login attempt, local auth is disabled", + slog.String("client_ip", clientIP), + slog.String("user_agent", r.UserAgent()), + ) + html.OK(w, r, view.Render("login")) + return + } + + authForm := form.NewAuthForm(r) view.Set("errorMessage", locale.NewLocalizedError("error.bad_credentials").Translate(request.UserLanguage(r))) view.Set("form", authForm) diff --git a/internal/ui/oauth2_unlink.go b/internal/ui/oauth2_unlink.go index 83b1fcfa361..e10cb5a459f 100644 --- a/internal/ui/oauth2_unlink.go +++ b/internal/ui/oauth2_unlink.go @@ -7,6 +7,7 @@ import ( "log/slog" "net/http" + "miniflux.app/v2/internal/config" "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" @@ -15,6 +16,14 @@ import ( ) func (h *handler) oauth2Unlink(w http.ResponseWriter, r *http.Request) { + if config.Opts.DisableLocalAuth() { + slog.Warn("blocking oauth2 unlink attempt, local auth is disabled", + slog.String("user_agent", r.UserAgent()), + ) + html.Redirect(w, r, route.Path(h.router, "login")) + return + } + printer := locale.NewPrinter(request.UserLanguage(r)) provider := request.RouteStringParam(r, "provider") if provider == "" { diff --git a/internal/ui/static_javascript.go b/internal/ui/static_javascript.go index f2fb89fc125..36061ce94ea 100644 --- a/internal/ui/static_javascript.go +++ b/internal/ui/static_javascript.go @@ -6,6 +6,7 @@ package ui // import "miniflux.app/v2/internal/ui" import ( "fmt" "net/http" + "strings" "time" "miniflux.app/v2/internal/http/request" @@ -15,6 +16,9 @@ import ( "miniflux.app/v2/internal/ui/static" ) +const licensePrefix = "//@license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt Apache-2.0\n" +const licenseSuffix = "\n//@license-end" + func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) { filename := request.RouteStringParam(r, "name") etag, found := static.JavascriptBundleChecksums[filename] @@ -31,6 +35,10 @@ func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) { contents = append([]byte(variables), contents...) } + // cloning the prefix since `append` mutates its first argument + contents = append([]byte(strings.Clone(licensePrefix)), contents...) + contents = append(contents, []byte(licenseSuffix)...) + b.WithHeader("Content-Type", "text/javascript; charset=utf-8") b.WithBody(contents) b.Write() diff --git a/miniflux.1 b/miniflux.1 index 4edd0ff740c..a2302fae7da 100644 --- a/miniflux.1 +++ b/miniflux.1 @@ -442,11 +442,24 @@ OpenID Connect discovery endpoint\&. .br Default is empty\&. .TP +.B OAUTH2_OIDC_PROVIDER_NAME +Name to display for the OIDC provider\&. +.br +Default is OpenID Connect\&. +.TP .B OAUTH2_PROVIDER Possible values are "google" or "oidc"\&. .br Default is empty\&. .TP +.B DISABLE_LOCAL_AUTH +Only use oauth2 for auth\&. +.br +When set to true, the username/password form is hidden from the login screen, and the +options to change username/password or unlink oauth2 account are hidden from the settings page. +.br +Default is false\&. +.TP .B OAUTH2_REDIRECT_URL OAuth2 redirect URL\&. .br diff --git a/packaging/debian/Dockerfile b/packaging/debian/Dockerfile index 3a6fccce1c3..eea82ec7928 100644 --- a/packaging/debian/Dockerfile +++ b/packaging/debian/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.22-bookworm AS build +FROM docker.io/golang:1.23-bookworm AS build ENV DEBIAN_FRONTEND=noninteractive diff --git a/packaging/docker/alpine/Dockerfile b/packaging/docker/alpine/Dockerfile index 2eb71e43d80..3988e2b3726 100644 --- a/packaging/docker/alpine/Dockerfile +++ b/packaging/docker/alpine/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/golang:alpine3.19 AS build +FROM docker.io/library/golang:alpine3.20 AS build RUN apk add --no-cache build-base git make ADD . /go/src/app WORKDIR /go/src/app @@ -15,7 +15,7 @@ LABEL org.opencontainers.image.source=https://github.com/miniflux/v2 LABEL org.opencontainers.image.documentation=https://miniflux.app/docs/ EXPOSE 8080 -ENV LISTEN_ADDR 0.0.0.0:8080 +ENV LISTEN_ADDR=0.0.0.0:8080 RUN apk --no-cache add ca-certificates tzdata COPY --from=build /go/src/app/miniflux /usr/bin/miniflux USER 65534 diff --git a/packaging/docker/distroless/Dockerfile b/packaging/docker/distroless/Dockerfile index a40808913e7..b1d6fbfac01 100644 --- a/packaging/docker/distroless/Dockerfile +++ b/packaging/docker/distroless/Dockerfile @@ -14,6 +14,6 @@ LABEL org.opencontainers.image.source=https://github.com/miniflux/v2 LABEL org.opencontainers.image.documentation=https://miniflux.app/docs/ EXPOSE 8080 -ENV LISTEN_ADDR 0.0.0.0:8080 +ENV LISTEN_ADDR=0.0.0.0:8080 COPY --from=build /go/src/app/miniflux /usr/bin/miniflux CMD ["/usr/bin/miniflux"]