Compare commits

..

93 Commits

Author SHA1 Message Date
Viktor Scharf
b39dfabba5 update contributing.md file 2026-02-27 12:28:45 +01:00
dependabot[bot]
6cdf229979 build(deps): bump github.com/kovidgoyal/imaging from 1.8.19 to 1.8.20
Bumps [github.com/kovidgoyal/imaging](https://github.com/kovidgoyal/imaging) from 1.8.19 to 1.8.20.
- [Release notes](https://github.com/kovidgoyal/imaging/releases)
- [Commits](https://github.com/kovidgoyal/imaging/compare/v1.8.19...v1.8.20)

---
updated-dependencies:
- dependency-name: github.com/kovidgoyal/imaging
  dependency-version: 1.8.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 18:38:29 +01:00
Mahdi Baghbani
d7cb432b4d fix(ocm): allow insecure tls for wayf discovery (#2404)
* fix(ocm): allow insecure tls for wayf discovery

Signed-off-by: Mahdi Baghbani <mahdi-baghbani@azadehafzar.io>
2026-02-26 14:44:38 +01:00
Florian Schade
b69b9cd569 fix: simplify subject.session key parsing 2026-02-25 14:02:09 +01:00
Florian Schade
e8ecbd7af1 refactor: make the logout mode private 2026-02-25 14:02:09 +01:00
Florian Schade
fd614eacf1 fix: use base64 record keys to prevent separator clashes with subjects or sessionIds that contain a dot 2026-02-25 14:02:09 +01:00
Florian Schade
910298aa05 chore: change naming 2026-02-25 14:02:09 +01:00
Florian Schade
7350050a05 test: add more backchannellogout tests 2026-02-25 14:02:09 +01:00
Florian Schade
f72e3f1e32 chore: cleanup backchannel logout pr for review 2026-02-25 14:02:09 +01:00
Florian Schade
0c62c45494 enhancement: document idp side-effects 2026-02-25 14:02:09 +01:00
Florian Schade
f6553498f6 enhancement: finalize backchannel logout 2026-02-25 14:02:09 +01:00
Christian Richter
6a0fd89475 refactor deletion
Co-authored-by: Jörn Dreyer <j.dreyer@opencloud.eu>
Co-authored-by: Michael Barz <m.barz@opencloud.eu>
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-02-25 14:02:09 +01:00
Christian Richter
cb38aaab16 create mapping in cache for subject => sessionid
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-02-25 14:02:09 +01:00
Christian Richter
762062bfa3 add mapping to backchannel logout for subject => sessionid
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-02-25 14:02:09 +01:00
Christian Richter
291265afb0 add additional validation to logout token
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
Co-authored-by: Michael Barz <m.barz@opencloud.eu>
2026-02-25 14:02:09 +01:00
opencloudeu
49a018e973 [tx] updated from transifex 2026-02-24 00:12:39 +00:00
Ralf Haferkamp
372bb04ee8 chore(idp): Bump dependencies
The axios bump addresses CVE-2025-7783
2026-02-23 09:38:12 +01:00
dependabot[bot]
b7eb6f768d build(deps): bump github.com/grpc-ecosystem/grpc-gateway/v2
Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.27.7 to 2.28.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.27.7...v2.28.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-version: 2.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 09:34:09 +01:00
dependabot[bot]
e13ba4af06 build(deps): bump github.com/open-policy-agent/opa from 1.13.1 to 1.13.2
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.13.1 to 1.13.2.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.13.1...v1.13.2)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 09:31:49 +01:00
Jannik Stehle
2a2e882a59 Merge pull request #2377 from opencloud-eu/feat/web-adjust-surface-colors
feat(web): change surface colors to more modern ones
2026-02-23 07:34:59 +01:00
opencloudeu
42e9c27174 [tx] updated from transifex 2026-02-22 00:13:15 +00:00
Jannik Stehle
02d73157c1 feat(web): change surface colors to more modern ones 2026-02-20 16:13:32 +01:00
dependabot[bot]
801a4ce8c4 build(deps): bump google.golang.org/grpc from 1.78.0 to 1.79.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.78.0 to 1.79.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.78.0...v1.79.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 18:27:12 +01:00
dependabot[bot]
74ff47e4c2 build(deps): bump github.com/onsi/ginkgo/v2 from 2.28.0 to 2.28.1
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.28.0 to 2.28.1.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.28.0...v2.28.1)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.28.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 17:04:06 +01:00
dependabot[bot]
5851db3d93 build(deps): bump go.opentelemetry.io/contrib/zpages
Bumps [go.opentelemetry.io/contrib/zpages](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.64.0 to 0.65.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.64.0...zpages/v0.65.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/zpages
  dependency-version: 0.65.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 13:27:49 +01:00
Ralf Haferkamp
6dde2839df fix(oidc_auth): Fix userinfo cache expiration logic
When the userinfo claims store in the usercache is found to be expired,
do not return an error but ignore the cached entry and force a
re-verification of the access token (either via parsing the JWT again or
via a UserInfo lookup).
This is required for setups with non-JWT access tokes where the expiry
date set in the cached claims does not reflect the actual token expiry,
but just the CacheTTL.

Fixes: #1493
2026-02-19 13:17:17 +01:00
Ralf Haferkamp
212846f2f4 fix(idp): Remove kpop dependency
The built package (https://download.kopano.io/community/kapp:/kpop-2.7.2.tgz)
seems to be no longer available and upstream lico already switched away
from it quite a while ago.

Fixes: #2364
2026-02-19 12:16:30 +01:00
opencloudeu
4447893aeb [tx] updated from transifex 2026-02-18 00:15:57 +00:00
Jörn Friedrich Dreyer
cd655f3ac7 Add openCloudEducationExternalId to user 2026-02-17 17:57:39 +01:00
dependabot[bot]
44d2f95fa6 build(deps): bump golang.org/x/net from 0.49.0 to 0.50.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.49.0 to 0.50.0.
- [Commits](https://github.com/golang/net/compare/v0.49.0...v0.50.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.50.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 16:53:59 +01:00
dependabot[bot]
d0edd5bf99 build(deps): bump github.com/go-resty/resty/v2 from 2.17.1 to 2.17.2
Bumps [github.com/go-resty/resty/v2](https://github.com/go-resty/resty) from 2.17.1 to 2.17.2.
- [Release notes](https://github.com/go-resty/resty/releases)
- [Commits](https://github.com/go-resty/resty/compare/v2.17.1...v2.17.2)

---
updated-dependencies:
- dependency-name: github.com/go-resty/resty/v2
  dependency-version: 2.17.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 16:51:33 +01:00
Alex
cdb942a093 feat: app-registry adjust default mime-types (#2354) 2026-02-17 16:39:55 +01:00
Ralf Haferkamp
342cb3df95 adr(webfinger): Align example config with implementation 2026-02-17 12:13:43 +01:00
Ralf Haferkamp
78703806e4 feat(webfinger): add fallbacks for CLIENT_ID and SCOPE setting
This adds the variables 'OC_OIDC_CLIENT_ID' and
'OC_OIDC_CLIENT_SCOPES' as fallbacks for the platform specific settings.

For backwards compatibility with the "old" settings for the 'web'
service we also allow 'WEB_OIDC_CLIENT_ID' and 'WEB_OIDC_SCOPE' for the
"web" platform.
2026-02-17 10:41:35 +01:00
Ralf Haferkamp
4f1aca6d90 feat(webfinger): use webfinger properties instead new relations
This works the previous commits so that clients can add an addtional
'platform' query parameter to the webfinger request that  can be used
to query the oidc client id and list of scopes that the clients need
to use when connecting to the IDP.

This also removes the non-standard issuer relatation introduced in a
previous commit as we can just introduce new relations in the
http://openid.net name space.

For IDP like Authentik that create a separate issuer url per Client
(Application in Authentik's terms) it is suggested to just configure
as single Client and use that id for all platforms (i.e. setting
'WEBFINGER_ANDROID_OIDC_CLIENT_ID', 'WEBFINGER_DESKTOP_OIDC_CLIENT_ID',
'WEBFINGER_IOS_OIDC_CLIENT_ID' and 'WEBFINGER_WEB_OIDC_CLIENT_ID' to
same value.

Related: #2088
Related: https://github.com/opencloud-eu/desktop/issues/246
2026-02-17 10:41:35 +01:00
Ralf Haferkamp
24aaeb46ba chore(webfinger): Simplify weird Query parameter extraction loop 2026-02-17 10:41:35 +01:00
pat-s
daeae1f443 feat(webfinger): support desktop and mobile specific OIDC client_id 2026-02-17 10:41:35 +01:00
pat-s
84da592c88 feat(webfinger): add desktop-specific OIDC issuer support 2026-02-17 10:41:35 +01:00
dependabot[bot]
5058e2ffc2 build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.64.0 to 0.65.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.64.0...zpages/v0.65.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.65.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 09:25:43 +01:00
dependabot[bot]
5daeada697 build(deps): bump github.com/open-policy-agent/opa from 1.12.3 to 1.13.1
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.12.3 to 1.13.1.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.12.3...v1.13.1)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 09:02:30 +01:00
opencloudeu
4e9eb596f0 [tx] updated from transifex 2026-02-17 00:17:42 +00:00
Ralf Haferkamp
a1b6f534f7 adr(webfinger): Change status to accepted 2026-02-16 17:40:19 +01:00
Ralf Haferkamp
815b049321 adr(webfinger): Apply suggestions from code review
Co-authored-by: Benedikt Kulmann <benedikt@kulmann.biz>
2026-02-16 17:40:19 +01:00
Ralf Haferkamp
2bf4f2e12e adr(webfinger): Document OIDC client parameter discovery 2026-02-16 17:40:19 +01:00
OpenCloud Devops
edb917b74a 🎉 Release 5.1.0 (#2300) 2026-02-16 15:31:10 +01:00
Andre Duffeck
2fdb87291e Merge pull request #2348 from aduffeck/bump-reva-v2.42.4
[full-ci] Bump reva v2.42.4
2026-02-16 14:11:04 +01:00
Benedikt Kulmann
153fdeeac0 Merge pull request #2349 from opencloud-eu/bump-web-5.1.0
[full-ci] chore: bump web to v5.1.0
2026-02-16 12:51:34 +01:00
André Duffeck
2043dee745 Bump opencloud version 2026-02-16 11:02:50 +01:00
Benedikt Kulmann
5be98670f4 chore: bump web to v5.1.0 2026-02-16 11:01:47 +01:00
André Duffeck
97da8655b7 Bump reva 2026-02-16 10:53:20 +01:00
opencloudeu
e698a35aef [tx] updated from transifex 2026-02-16 00:16:53 +00:00
opencloudeu
d867665dc1 [tx] updated from transifex 2026-02-15 00:16:35 +00:00
opencloudeu
e0b465342f [tx] updated from transifex 2026-02-14 00:16:38 +00:00
Thomas Schweiger
8f3714f08f Merge pull request #2333 from opencloud-eu/fix/fix-typo-in-var-description
fix: fix typo in variable description
2026-02-12 18:13:02 +01:00
Michael Barz
1c493ec46b fix: include sessionID in sse logout event (#2327) 2026-02-12 17:21:09 +01:00
Thomas Schweiger
bac83c4729 fix: fix typo in variable description 2026-02-12 16:48:12 +01:00
Thomas Schweiger
b4af917ab3 Merge pull request #2332 from opencloud-eu/fix/fix-typo-in-gateway-service-docu
fix: fix typo in gateway service documentation
2026-02-12 16:24:48 +01:00
Thomas Schweiger
2f7422538b fix: fix typo in gateway service documentation 2026-02-12 15:43:00 +01:00
opencloudeu
d14ae65eba [tx] updated from transifex 2026-02-12 00:16:05 +00:00
André Duffeck
ae3582afa3 Bump reva 2026-02-11 10:05:53 +01:00
dependabot[bot]
99aba9cfa1 build(deps): bump github.com/gabriel-vasile/mimetype
Bumps [github.com/gabriel-vasile/mimetype](https://github.com/gabriel-vasile/mimetype) from 1.4.12 to 1.4.13.
- [Release notes](https://github.com/gabriel-vasile/mimetype/releases)
- [Commits](https://github.com/gabriel-vasile/mimetype/compare/v1.4.12...v1.4.13)

---
updated-dependencies:
- dependency-name: github.com/gabriel-vasile/mimetype
  dependency-version: 1.4.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-11 09:25:13 +01:00
dependabot[bot]
0cf2d8b785 build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace
Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.39.0 to 1.40.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.39.0...v1.40.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace
  dependency-version: 1.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-11 09:22:59 +01:00
opencloudeu
1c80721aff [tx] updated from transifex 2026-02-11 00:15:55 +00:00
Christian Richter
63a0458307 vendor mod tidy
Signed-off-by: Christian Richter <c.richter@opencloud.eu>

 Conflicts:
	go.sum
	vendor/modules.txt
2026-02-10 10:45:09 +01:00
Christian Richter
6f7160556f fix tests
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-02-10 10:45:09 +01:00
Christian Richter
7d5d8f3484 adapt graph service
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
Co-authored-by: Ralf Haferkamp <r.haferkamp@opencloud.eu>
2026-02-10 10:45:09 +01:00
Christian Richter
f24041725b Bump traefik to 3.6.7 & adapt initilize_users.go & bump librgraph-api-go
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
Co-authored-by: Ralf Haferkamp <r.haferkamp@opencloud.eu>

# Conflicts:
#	go.mod
2026-02-10 10:45:09 +01:00
Christian Richter
5877bfa8a2 initial skel for external tenant id
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-02-10 10:45:09 +01:00
Artur Neumann
13ae67b02c Merge pull request #2257 from opencloud-eu/checkVersionPlaceholderReadyReleaseGo
ci: check version placeholder in release PR
2026-02-10 14:52:26 +05:45
Viktor Scharf
464c528634 update reva after merge #514 (#2309) 2026-02-10 09:12:41 +01:00
Viktor Scharf
564805bf94 fix: make file urls (#2304) 2026-02-09 14:31:58 +01:00
Ralf Haferkamp
c33850f213 Reapply "adapt test for #514 (#2255)" (#2305)
This reverts commit f21207ed96.
2026-02-09 14:23:24 +01:00
VicDeo
ab9c4d8f23 Sanitize web config only once 2026-02-09 14:09:33 +01:00
dependabot[bot]
8c725823f7 build(deps): bump github.com/go-chi/chi/v5 from 5.2.4 to 5.2.5
Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.4 to 5.2.5.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.4...v5.2.5)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-version: 5.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 09:05:12 +01:00
OpenCloud Devops
673f606abf 🎉 Release 5.0.2 (#2230)
* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2

* 🎉 Release 5.0.2
2026-02-05 17:26:50 +01:00
Viktor Scharf
1e432b717e reva-bump-2.42.3 (#2276) 2026-02-05 16:51:58 +01:00
Viktor Scharf
2bf70a6f70 reva-bump-2.42.2 2026-02-05 12:29:10 +01:00
Ralf Haferkamp
f21207ed96 Revert "adapt test for #514 (#2255)"
This reverts commit 400dc9f8ae.
2026-02-05 10:33:26 +01:00
Viktor Scharf
400dc9f8ae adapt test for #514 (#2255) 2026-02-03 19:51:33 +01:00
Ralf Haferkamp
0639304e96 docs(proxy): Clarify PROXY_OIDC_USERINFO_CACHE_TTL value
Try to make it more precise when that value is actually relevant.

Closes: #2252
2026-02-03 15:36:37 +01:00
Artur Neumann
be5d504b97 ci: check version placeholder in release PR 2026-02-03 15:42:34 +05:45
opencloudeu
7a0bbd93b4 [tx] updated from transifex 2026-02-03 00:14:43 +00:00
Viktor Scharf
567e8a7e8c api-test: upload-rename-download file with back slash (#2239) 2026-02-02 07:59:51 +01:00
opencloudeu
158c920e3d [tx] updated from transifex 2026-02-01 00:13:47 +00:00
dependabot[bot]
032900bd9c build(deps): bump github.com/grpc-ecosystem/grpc-gateway/v2
Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.27.5 to 2.27.6.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.27.5...v2.27.6)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-version: 2.27.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-29 17:43:50 +01:00
Artur Neumann
663fe3740b Merge pull request #2236 from opencloud-eu/checkForVersionPlaceholders
ci: check for version placeholders
2026-01-29 18:25:42 +05:45
Artur Neumann
4a83b34b91 ci: check for version placeholders 2026-01-29 16:42:38 +05:45
Alex
8b4c218a5f chore: change target path for docs automation (#2235) 2026-01-29 11:05:45 +01:00
Sawjan Gurung
70623d6007 Merge pull request #2041 from opencloud-eu/test/test-hook-failure
[full-ci][tests-only] test: add hook failures to the test failures list
2026-01-29 10:08:25 +05:45
opencloudeu
cad6a61120 [tx] updated from transifex 2026-01-29 00:13:28 +00:00
Michael Flemming
754f0fa5b7 Merge pull request #2229 from opencloud-eu/fix_docs_gen_path
fix path and trigger for docsGenPr
2026-01-28 18:03:15 +01:00
Michael 'Flimmy' Flemming
38cf037a11 fix path and trigger for docsGenPr 2026-01-28 17:53:11 +01:00
Saw-jan
cd408c6923 test: add hook failures to the test failures list
Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com>
2026-01-28 11:29:48 +05:45
596 changed files with 60861 additions and 68724 deletions

View File

@@ -1,4 +1,4 @@
# The test runner source for UI tests
WEB_COMMITID=980964ccafe81cba6742cead151ac2d61408dae3
WEB_COMMITID=05cf6c25e32aeedf0901fcd5e6d43f7646310ef2
WEB_BRANCH=main

View File

@@ -497,7 +497,8 @@ def main(ctx):
is_release_pr = (ctx.build.event == "pull_request" and ctx.build.sender == "openclouders" and "🎉 release" in ctx.build.title.lower())
if is_release_pr:
return licenseCheck(ctx)
return checkVersionPlaceholder() + \
licenseCheck(ctx)
build_release_helpers = \
readyReleaseGo()
@@ -1817,6 +1818,27 @@ def dockerReleases(ctx):
return pipelines
def checkVersionPlaceholder():
return [{
"name": "check-version-placeholder",
"steps": [
{
"name": "check-version-placeholder",
"image": OC_CI_ALPINE,
"commands": [
"grep -r -e '%%NEXT%%' -e '%%NEXT_PRODUCTION_VERSION%%' %s/services %s/pkg > next_version.txt" % (
dirs["base"],
dirs["base"],
),
'if [ -s next_version.txt ]; then echo "replace version placeholders"; cat next_version.txt; exit 1; fi',
],
},
],
"when": [
event["pull_request"],
],
}]
def dockerRelease(ctx, repo, build_type):
build_args = {
"REVISION": "%s" % ctx.build.commit,
@@ -2230,7 +2252,7 @@ def genDocsPr(ctx):
"MY_TARGET_BRANCH": "${CI_COMMIT_BRANCH##stable-}",
},
"commands": [
'export DOC_GIT_TARGET_FOLDER="$$(if [ \"$$MY_TARGET_BRANCH\" = \"main\" ]; then echo \"tmpdocs/docs/dev/_static/env-vars/\"; else echo \"tmpdocs/versioned_docs/version-$${MY_TARGET_BRANCH}/dev/_static/env-vars/\"; fi)"',
'export DOC_GIT_TARGET_FOLDER="$$(if [ \"$$MY_TARGET_BRANCH\" = \"main\" ]; then echo \"tmpdocs/docs/_static/env-vars/\"; else echo \"tmpdocs/versioned_docs/version-$${MY_TARGET_BRANCH}/_static/env-vars/\"; fi)"',
'echo "$${CI_SSH_KEY}" > /root/id_rsa && chmod 600 /root/id_rsa',
'git config --global user.email "devops@opencloud.eu"',
'git config --global user.name "openclouders"',
@@ -2255,8 +2277,8 @@ def genDocsPr(ctx):
},
{
"event": "cron",
"branch": "[main]",
"cron": "nightly *",
"branch": "main",
"cron": "nightly*",
},
],
}]

View File

@@ -1,5 +1,59 @@
# Changelog
## [5.1.0](https://github.com/opencloud-eu/opencloud/releases/tag/v5.1.0) - 2026-02-16
### ❤️ Thanks to all contributors! ❤️
@ScharfViktor, @VicDeo, @aduffeck, @dragonchaser, @individual-it, @kulmann, @micbar, @rhafer, @schweigisito
### 🐛 Bug Fixes
- [full-ci] Bump reva v2.42.4 [[#2348](https://github.com/opencloud-eu/opencloud/pull/2348)]
- fix: fix typo in variable description [[#2333](https://github.com/opencloud-eu/opencloud/pull/2333)]
- fix: include sessionID in sse logout event [[#2327](https://github.com/opencloud-eu/opencloud/pull/2327)]
- fix: fix typo in gateway service documentation [[#2332](https://github.com/opencloud-eu/opencloud/pull/2332)]
- Sanitize web config only once [[#2286](https://github.com/opencloud-eu/opencloud/pull/2286)]
### 📈 Enhancement
- external tenant id [[#2258](https://github.com/opencloud-eu/opencloud/pull/2258)]
### 📚 Documentation
- fix: make file urls [[#2304](https://github.com/opencloud-eu/opencloud/pull/2304)]
### 📦️ Dependencies
- build(deps): bump github.com/gabriel-vasile/mimetype from 1.4.12 to 1.4.13 [[#2316](https://github.com/opencloud-eu/opencloud/pull/2316)]
- build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace from 1.39.0 to 1.40.0 [[#2279](https://github.com/opencloud-eu/opencloud/pull/2279)]
- update reva after merge #514 [[#2309](https://github.com/opencloud-eu/opencloud/pull/2309)]
- build(deps): bump github.com/go-chi/chi/v5 from 5.2.4 to 5.2.5 [[#2278](https://github.com/opencloud-eu/opencloud/pull/2278)]
## [5.0.2](https://github.com/opencloud-eu/opencloud/releases/tag/v5.0.2) - 2026-02-05
### ❤️ Thanks to all contributors! ❤️
@AlexAndBear, @ScharfViktor, @flimmy, @individual-it, @rhafer, @saw-jan
### 🐛 Bug Fixes
- [full-ci] reva-bump-2.42.3 [[#2276](https://github.com/opencloud-eu/opencloud/pull/2276)]
### ✅ Tests
- adapt test for #514 [[#2255](https://github.com/opencloud-eu/opencloud/pull/2255)]
- api-test: upload-rename-download file with back slash [[#2239](https://github.com/opencloud-eu/opencloud/pull/2239)]
- [full-ci][tests-only] test: add hook failures to the test failures list [[#2041](https://github.com/opencloud-eu/opencloud/pull/2041)]
### 📚 Documentation
- docs(proxy): Clarify PROXY_OIDC_USERINFO_CACHE_TTL value [[#2256](https://github.com/opencloud-eu/opencloud/pull/2256)]
### 📦️ Dependencies
- [full-ci] reva-bump-2.42.2 [[#2270](https://github.com/opencloud-eu/opencloud/pull/2270)]
- build(deps): bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.27.5 to 2.27.6 [[#2238](https://github.com/opencloud-eu/opencloud/pull/2238)]
## [5.0.1](https://github.com/opencloud-eu/opencloud/releases/tag/v5.0.1) - 2026-01-28
### ❤️ Thanks to all contributors! ❤️

View File

@@ -40,7 +40,7 @@ but it should be easily transferable to other (sub)projects.
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
For general questions, please refer to [OpenCloud's FAQs](https://opencloud.eu/faq/) or check the [project page](https://github.com/opencloud-eu) for communication channels.
For general questions, please refer to [OpenCloud's FAQs](https://docs.opencloud.eu/docs/admin/resources/faq/) or check the [project page](https://github.com/opencloud-eu) for communication channels.
## What to know before getting started
@@ -55,7 +55,7 @@ The OpenCloud project follows the strict GitHub workflow of development as brief
### OpenCloud Company, Engineering Partners and Community
OpenCloud is largely created by developers who are employed by the [OpenCloud company](https://opencloud.eu), which is located in Germany.
It is providing support for OpenCloud for customers mainly in the EU. In addition, there are engineering partners who also work full-time on OpenCloud related code, for example, on the component [REVA](https://github.com/cs3org/reva/).
It is providing support for OpenCloud for customers mainly in the EU. In addition, there are engineering partners who also work full-time on OpenCloud related code, for example, on the component [REVA](https://github.com/opencloud-eu/reva/).
Because of that fact, the pace that the development is moving forward is sometimes high for people who are not willing and/or able to spend a comparable amount of time to contribute.
Even though this can be a challenge, it should not scare anybody away. Here is our clear commitment that we feel honored by everybody who is interested in our work and improves it, no matter how big the contribution might be.
@@ -113,7 +113,7 @@ Explain the problem and include additional details to help maintainers reproduce
Provide more context by answering these questions:
* **Did the problem start happening recently** (e.g. after updating to a new version) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version?** What's the most recent version in which the problem doesn't happen? You can find more information about how to set up [test environments](https://docs.opencloud.eu/devel/testing) in the [developer documentation](https://docs.opencloud.eu/docs/dev/intro).
* If the problem started happening recently, **can you reproduce the problem in an older version?** What's the most recent version in which the problem doesn't happen? You can find more information about how to set up in the [Getting Started guide](https://docs.opencloud.eu/docs/admin/getting-started).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment as asked for in the template.
@@ -146,9 +146,8 @@ Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com
Unsure where to begin contributing to OpenCloud? You can start by looking through these `Needs-help` issues:
* The [Good first issue](https://github.com/opencloud-eu/opencloud/labels/Topic%3Agood-first-issue) label marks good items to start with.
* [Tests needed](https://github.com/opencloud-eu/opencloud/labels/Interaction%3ANeeds-tests) - issues which would benefit from a test.
* [Help wanted issues](https://github.com/opencloud-eu/opencloud/labels/Interaction%3ANeeds-help) - issues which should be a bit more involved.
* The [Good first issue](https://github.com/opencloud-eu/opencloud/labels/Type%3Agood-first-issue) label marks good items to start with.
* The [Feature Request](https://github.com/opencloud-eu/opencloud/issues?q=state%3Aopen%20label%3AType%3AFeature-Request) label lists features the community would like to see implemented.
It is fine to pick one of the lists following personal preference.
While not perfect, the number of comments is a reasonable proxy for the impact a given change will have.
@@ -221,7 +220,7 @@ To help you find issues and pull requests, each label can be used in search link
The labels are loosely grouped by their purpose, but it's not required that every issue has a label from every group or that an issue can't have more than one label from the same group.
The list here contains all the more general categories of issues which are followed by a colon and a specific value.
For example, severity 1 looks like `Severity:sev1-critical`.
For example, severity 1 looks like `Priority:p1-urgent`.
#### Platform
@@ -257,7 +256,7 @@ Categorizes the issue to also indicate the type of the issue.
#### Status
The status in the ticket life cycle. Keep an eye on that one, especially for the `Waiting-for-Feedback` tag which might indicate that the reporter is asked for feedback.
The status in the ticket life cycle. Keep an eye on that one, especially for the `Status:Needs-Review` tag which might indicate that the reporter is asked for feedback.
#### Interaction

View File

@@ -83,7 +83,7 @@ help:
@echo "Please use 'make <target>' where <target> is one of the following:"
@echo
@echo -e "${GREEN}Testing with test suite natively installed:${RESET}\n"
@echo -e "${PURPLE}\tdocs: https://opencloud.dev/opencloud/development/testing/#testing-with-test-suite-natively-installed${RESET}\n"
@echo -e "${PURPLE}\ttests: https://github.com/opencloud-eu/opencloud/blob/main/tests/README.md#running-test-suite-in-local-environment${RESET}\n"
@echo -e "\tmake test-acceptance-api\t\t${BLUE}run API acceptance tests${RESET}"
@echo -e "\tmake clean-tests\t\t\t${BLUE}delete API tests framework dependencies${RESET}"
@echo
@@ -92,17 +92,11 @@ help:
@echo -e "${RED}You also should have a look at other available Makefiles:${RESET}"
@echo
@echo -e "${GREEN}opencloud:${RESET}\n"
@echo -e "${PURPLE}\tdocs: https://opencloud.dev/opencloud/development/build/${RESET}\n"
@echo -e "${PURPLE}\tdocs: https://github.com/opencloud-eu/opencloud/blob/main/README.md#build-opencloud${RESET}\n"
@echo -e "\tsee ./opencloud/Makefile"
@echo -e "\tor run ${YELLOW}make -C opencloud help${RESET}"
@echo
@echo -e "${GREEN}Documentation:${RESET}\n"
@echo -e "${PURPLE}\tdocs: https://opencloud.dev/opencloud/development/build-docs/${RESET}\n"
@echo -e "\tsee ./docs/Makefile"
@echo -e "\tor run ${YELLOW}make -C docs help${RESET}"
@echo
@echo -e "${GREEN}Testing with test suite in docker:${RESET}\n"
@echo -e "${PURPLE}\tdocs: https://opencloud.dev/opencloud/development/testing/#testing-with-test-suite-in-docker${RESET}\n"
@echo -e "${PURPLE}\ttests: https://github.com/opencloud-eu/opencloud/blob/main/tests/README.md#running-test-suite-in-docker${RESET}\n"
@echo -e "\tsee ./tests/acceptance/docker/Makefile"
@echo -e "\tor run ${YELLOW}make -C tests/acceptance/docker help${RESET}"
@echo

View File

@@ -24,6 +24,7 @@ var demoTenants = []tenantWithUsers{
{
tenant: libregraph.EducationSchool{
DisplayName: libregraph.PtrString("Famous Coders"),
ExternalId: libregraph.PtrString("famouscodersExternalID"),
},
users: []libregraph.EducationUser{
{
@@ -41,6 +42,7 @@ var demoTenants = []tenantWithUsers{
{
tenant: libregraph.EducationSchool{
DisplayName: libregraph.PtrString("Scientists"),
ExternalId: libregraph.PtrString("scientistsExternalID"),
},
users: []libregraph.EducationUser{
{

View File

@@ -9,7 +9,7 @@ services:
- "traefik.http.services.opencloud.loadbalancer.server.port=9200"
- "traefik.http.routers.opencloud.${TRAEFIK_SERVICES_TLS_CONFIG}"
traefik:
image: traefik:v3.3.1
image: traefik:v3.6.7
# release notes: https://github.com/traefik/traefik/releases
networks:
opencloud-net:

View File

@@ -32,7 +32,7 @@ olcObjectClasses: ( openCloudOid:1.2.3 NAME 'openCloudEducationUser'
DESC 'OpenCloud education user objectclass'
SUP openCloudUser
AUXILIARY
MAY ( userClass $ openCloudMemberOfSchool ) )
MAY ( openCloudEducationExternalId $ userClass $ openCloudMemberOfSchool ) )
olcObjectClasses: ( openCloudOid:1.2.4 NAME 'openCloudEducationClass'
DESC 'OpenCloud education class objectclass'
SUP openCloudObject
@@ -42,4 +42,4 @@ olcObjectClasses: ( openCloudOid:1.2.5 NAME 'openCloudEducationSchool'
DESC 'OpenCloud education school objectclass'
SUP openCloudObject
AUXILIARY
MAY ( openCloudEducationSchoolNumber $ openCloudEducationSchoolTerminationTimestamp ) )
MAY ( openCloudEducationSchoolNumber $ openCloudEducationSchoolTerminationTimestamp $ openCloudEducationExternalId) )

View File

@@ -0,0 +1,89 @@
---
title: "Discover OIDC Client configuration via WebFinger"
---
* Status: accepted
* Deciders: [@TheOneRing @kulmann @rhafer @dragotin]
* Date: 2026-02-02
Reference: https://github.com/opencloud-eu/opencloud/pull/2072, https://github.com/opencloud-eu/desktop/issues/217
## Context and Problem Statement
Up to now our client applications used hard-coded OIDC client configurations.
So it is not possible to change the client id that a client should use or the
list of scopes that a client needs to request. This makes it hard to integrate
OpenCloud with various existing identity providers. For example:
- Authentik basically creates a different issuer URL for each client. As OpenCloud
can only work with a single issuer URL, all OpenCloud clients need to use the
same client id to work with Authentik.
- Some IDPs (kanidm) are not able to work with user-supplied client ids. They generate
client ids automatically and do not allow to specify them manually.
- To make features like automatic role assignment work, clients need to request
specific scopes, depending on which exact IDP is used.
## Decision Drivers
* Support broader set of IDPs
* avoid any manual configuration adjustments on the client side
## Decision
Enhance the WebFinger service in OpenCloud to provide platform-specific OIDC
discovery, enabling clients to query for the correct OIDC `client_id` and
`scopes` based on their application type (e.g., web, desktop, android, ios).
This is achieved by allowing an additional `platform` query parameter to be used
when querying the WebFinger endpoint. The response will include the appropriate
`client_id` and `scopes` in the `properties` section of the response.
This is implemented in a backward-compatible way, so existing clients that do not
specify the `platform` parameter will continue to receive just the issuer information.
## Example
### Client Request
```
GET /.well-known/webfinger?resource=https://cloud.opencloud.test&rel=http://openid.net/specs/connect/1.0/issuer&platform=desktop
```
### Server Response
```json
{
"subject": "https://cloud.opencloud.test",
"links": [{
"rel": "http://openid.net/specs/connect/1.0/issuer",
"href": "https://idp.example.com"
}],
"properties": {
"http://opencloud.eu/ns/oidc/client_id": "desktop-client-id",
"http://opencloud.eu/ns/oidc/scopes": ["openid", "profile", "email", "offline_access"]
}
}
```
### Server configuration (suggestion)
To configure the OpenCloud server a couple of new config settings need to be introduced. This would
be two new settings per client, e.g.:
```
WEBFINGER_ANDROID_OIDC_CLIENT_ID
WEBFINGER_ANDROID_OIDC_CLIENT_SCOPES
WEBFINGER_DESKTOP_OIDC_CLIENT_ID
WEBFINGER_DESKTOP_OIDC_CLIENT_SCOPES
WEBFINGER_IOS_OIDC_CLIENT_ID
WEBFINGER_IOS_OIDC_CLIENT_SCOPES
WEBFINGER_WEB_OIDC_CLIENT_ID
WEBFINGER_WEB_OIDC_CLIENT_SCOPES
```
Additionally for backwards compatibility the existing `WEB_OIDC_CLIENT_ID` and
`WEB_OIDC_CLIENT_SCOPE` settings should be used as fallback for the `web`
platform. Also we should make it easy to configure the same settings for all
platforms at once by using `OC_OIDC_CLIENT_ID` and `OC_OIDC_CLIENT_SCOPE` as
fallback for all platforms if the platform-specific settings are not set.

102
go.mod
View File

@@ -18,9 +18,9 @@ require (
github.com/davidbyttow/govips/v2 v2.16.0
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/gabriel-vasile/mimetype v1.4.12
github.com/gabriel-vasile/mimetype v1.4.13
github.com/ggwhite/go-masker v1.1.0
github.com/go-chi/chi/v5 v5.2.4
github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/render v1.0.3
github.com/go-jose/go-jose/v3 v3.0.4
github.com/go-ldap/ldap/v3 v3.4.12
@@ -34,38 +34,38 @@ require (
github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus v1.2.0
github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0
github.com/go-playground/validator/v10 v10.30.1
github.com/go-resty/resty/v2 v2.17.1
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/go-resty/resty/v2 v2.17.2
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/golang/protobuf v1.5.4
github.com/google/go-cmp v0.7.0
github.com/google/go-tika v0.3.1
github.com/google/uuid v1.6.0
github.com/gookit/config/v2 v2.2.7
github.com/gorilla/mux v1.8.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.5
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0
github.com/invopop/validation v0.8.0
github.com/jellydator/ttlcache/v2 v2.11.1
github.com/jellydator/ttlcache/v3 v3.4.0
github.com/jinzhu/now v1.1.5
github.com/justinas/alice v1.2.0
github.com/kovidgoyal/imaging v1.8.19
github.com/kovidgoyal/imaging v1.8.20
github.com/leonelquinteros/gotext v1.7.2
github.com/libregraph/idm v0.5.0
github.com/libregraph/lico v0.66.0
github.com/mitchellh/mapstructure v1.5.0
github.com/mna/pigeon v1.3.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/nats-io/nats-server/v2 v2.12.3
github.com/nats-io/nats-server/v2 v2.12.4
github.com/nats-io/nats.go v1.48.0
github.com/oklog/run v1.2.0
github.com/olekukonko/tablewriter v1.1.3
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.27.5
github.com/onsi/gomega v1.39.0
github.com/open-policy-agent/opa v1.12.3
github.com/onsi/ginkgo/v2 v2.28.1
github.com/onsi/gomega v1.39.1
github.com/open-policy-agent/opa v1.13.2
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76
github.com/opencloud-eu/reva/v2 v2.42.1
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260204102724-10bcda1b3068
github.com/opencloud-eu/reva/v2 v2.42.4
github.com/opensearch-project/opensearch-go/v4 v4.6.0
github.com/orcaman/concurrent-map v1.0.0
github.com/pkg/errors v0.9.1
@@ -95,24 +95,24 @@ require (
github.com/xhit/go-simple-mail/v2 v2.16.0
go-micro.dev/v4 v4.11.0
go.etcd.io/bbolt v1.4.3
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0
go.opentelemetry.io/contrib/zpages v0.64.0
go.opentelemetry.io/otel v1.39.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0
go.opentelemetry.io/otel/sdk v1.39.0
go.opentelemetry.io/otel/trace v1.39.0
golang.org/x/crypto v0.47.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0
go.opentelemetry.io/contrib/zpages v0.65.0
go.opentelemetry.io/otel v1.40.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0
go.opentelemetry.io/otel/sdk v1.40.0
go.opentelemetry.io/otel/trace v1.40.0
golang.org/x/crypto v0.48.0
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
golang.org/x/image v0.35.0
golang.org/x/net v0.49.0
golang.org/x/oauth2 v0.34.0
golang.org/x/image v0.36.0
golang.org/x/net v0.50.0
golang.org/x/oauth2 v0.35.0
golang.org/x/sync v0.19.0
golang.org/x/term v0.39.0
golang.org/x/text v0.33.0
google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516
google.golang.org/grpc v1.78.0
golang.org/x/term v0.40.0
golang.org/x/text v0.34.0
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57
google.golang.org/grpc v1.79.1
google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
@@ -130,7 +130,7 @@ require (
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.5 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
github.com/agnivade/levenshtein v1.2.1 // indirect
github.com/ajg/form v1.5.1 // indirect
@@ -181,7 +181,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/crewjam/saml v0.4.14 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
@@ -208,7 +208,7 @@ require (
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-git/go-git/v5 v5.13.2 // indirect
github.com/go-git/go-git/v5 v5.16.5 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-kit/log v0.2.1 // indirect
@@ -241,8 +241,8 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/gomodule/redigo v1.9.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.7 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
github.com/google/renameio/v2 v2.0.1 // indirect
github.com/gookit/goutil v0.7.1 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
@@ -261,7 +261,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/juliangruber/go-intersect v1.1.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.18.2 // indirect
github.com/klauspost/compress v1.18.3 // indirect
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
github.com/klauspost/crc32 v1.3.0 // indirect
github.com/kovidgoyal/go-parallel v1.1.1 // indirect
@@ -271,9 +271,8 @@ require (
github.com/lestrrat-go/dsig v1.0.0 // indirect
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.1 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.12 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.2 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.13 // indirect
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/libregraph/oidc-go v1.1.0 // indirect
github.com/longsleep/go-metrics v1.0.0 // indirect
@@ -287,7 +286,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.33 // indirect
github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b // indirect
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 // indirect
github.com/miekg/dns v1.1.57 // indirect
github.com/miekg/dns v1.1.68 // indirect
github.com/mileusna/useragent v1.3.5 // indirect
github.com/minio/crc64nvme v1.1.1 // indirect
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect
@@ -328,9 +327,9 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/cachecontrol v0.2.0 // indirect
github.com/prometheus/alertmanager v0.30.1 // indirect
github.com/prometheus/alertmanager v0.31.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.4 // indirect
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/prometheus/statsd_exporter v0.22.8 // indirect
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
@@ -339,9 +338,9 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/samber/lo v1.51.0 // indirect
github.com/samber/slog-common v0.19.0 // indirect
github.com/samber/slog-zerolog/v2 v2.9.0 // indirect
github.com/samber/lo v1.52.0 // indirect
github.com/samber/slog-common v0.20.0 // indirect
github.com/samber/slog-zerolog/v2 v2.9.1 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/segmentio/kafka-go v0.4.50 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
@@ -353,7 +352,7 @@ require (
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 // indirect
github.com/spf13/cast v1.10.0 // indirect
@@ -369,7 +368,7 @@ require (
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
github.com/trustelem/zxcvbn v1.0.1 // indirect
github.com/urfave/cli/v2 v2.27.7 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
github.com/valyala/fastjson v1.6.7 // indirect
github.com/vektah/gqlparser/v2 v2.5.31 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wk8/go-ordered-map v1.0.0 // indirect
@@ -384,20 +383,21 @@ require (
go.etcd.io/etcd/client/v3 v3.6.7 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
go.opentelemetry.io/otel/metric v1.40.0 // indirect
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/mod v0.32.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.40.0 // indirect
golang.org/x/tools v0.41.0 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/ini.v1 v1.67.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect

225
go.sum
View File

@@ -91,8 +91,8 @@ github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzS
github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
@@ -272,8 +272,8 @@ github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1n
github.com/cs3org/go-cs3apis v0.0.0-20250908152307-4ca807afe54e h1:fC/BWMVWNFlSbzvSp2xTaH0qpJiq7ScRrOsCzpgi1xI=
github.com/cs3org/go-cs3apis v0.0.0-20250908152307-4ca807afe54e/go.mod h1:DedpcqXl193qF/08Y04IO0PpxyyMu8+GrkD6kWK2MEQ=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -287,8 +287,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjY
github.com/deepmap/oapi-codegen v1.3.11/go.mod h1:suMvK7+rKlx3+tpa8ByptmvoXbAV70wERKTOGH3hLp0=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
github.com/dgraph-io/badger/v4 v4.8.0 h1:JYph1ChBijCw8SLeybvPINizbDKWZ5n/GYbz2yhN/bs=
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
github.com/dgraph-io/badger/v4 v4.9.0 h1:tpqWb0NewSrCYqTvywbcXOhQdWcqephkVkbBmaaqHzc=
github.com/dgraph-io/badger/v4 v4.9.0/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0=
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
@@ -327,8 +327,8 @@ github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0o
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/egirna/icap v0.0.0-20181108071049-d5ee18bd70bc h1:6IxmRbXV8WXVkcYcTzkU219A3UZeNMX/e6X2sve1wXA=
github.com/egirna/icap v0.0.0-20181108071049-d5ee18bd70bc/go.mod h1:FdVN2WHg7zOHhJ7kZQdDorfFhIfqZaHttjAzDDvAXHE=
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/emvi/iso-639-1 v1.1.1 h1:7jrl1Sqw9ZYWmCOaH+cpQotLbGr/khwlLPXlBvE8WXU=
@@ -350,16 +350,16 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0=
github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gdexlab/go-render v1.0.1 h1:rxqB3vo5s4n1kF0ySmoNeSPRYkEsyHgln4jFIQY7v0U=
github.com/gdexlab/go-render v1.0.1/go.mod h1:wRi5nW2qfjiGj4mPukH4UV0IknS1cHD4VgFTmJX5JzM=
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
@@ -381,8 +381,8 @@ github.com/go-asn1-ber/asn1-ber v1.4.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
@@ -393,8 +393,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -461,8 +461,8 @@ github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
github.com/go-resty/resty/v2 v2.17.1 h1:x3aMpHK1YM9e4va/TMDRlusDDoZiQ+ViDu/WpA6xTM4=
github.com/go-resty/resty/v2 v2.17.1/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk=
github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -504,8 +504,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -575,8 +575,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-tika v0.3.1 h1:l+jr10hDhZjcgxFRfcQChRLo1bPXQeLFluMyvDhXTTA=
github.com/google/go-tika v0.3.1/go.mod h1:DJh5N8qxXIl85QkqmXknd+PeeRkUOTbvwyYf7ieDz6c=
github.com/google/go-tpm v0.9.7 h1:u89J4tUUeDTlH8xxC3CTW7OHZjbjKoHdQ9W7gCUhtxA=
github.com/google/go-tpm v0.9.7/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -587,8 +587,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.1 h1:HyOM6qd9gF9sf15AvhbptGHUnaLTpEI9akAFFU3VyW0=
github.com/google/renameio/v2 v2.0.1/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
@@ -624,8 +624,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vb
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.5 h1:jP1RStw811EvUDzsUQ9oESqw2e4RqCjSAD9qIL8eMns=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.5/go.mod h1:WXNBZ64q3+ZUemCMXD9kYnr56H7CgZxDBHCVwstfl3s=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -730,8 +730,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
@@ -747,8 +747,8 @@ github.com/kovidgoyal/go-parallel v1.1.1 h1:1OzpNjtrUkBPq3UaqrnvOoB2F9RttSt811ui
github.com/kovidgoyal/go-parallel v1.1.1/go.mod h1:BJNIbe6+hxyFWv7n6oEDPj3PA5qSw5OCtf0hcVxWJiw=
github.com/kovidgoyal/go-shm v1.0.0 h1:HJEel9D1F9YhULvClEHJLawoRSj/1u/EDV7MJbBPgQo=
github.com/kovidgoyal/go-shm v1.0.0/go.mod h1:Yzb80Xf9L3kaoB2RGok9hHwMIt7Oif61kT6t3+VnZds=
github.com/kovidgoyal/imaging v1.8.19 h1:zWJdQqF2tfSKjvoB7XpLRhVGbYsze++M0iaqZ4ZkhNk=
github.com/kovidgoyal/imaging v1.8.19/go.mod h1:I0q8RdoEuyc4G8GFOF9CaluTUHQSf68d6TmsqpvfRI8=
github.com/kovidgoyal/imaging v1.8.20 h1:74GZ7C2rIm3rqmGEjK1GvvPOOnJ0SS5iDOa6Flfo0b0=
github.com/kovidgoyal/imaging v1.8.20/go.mod h1:d3phGYkTChGYkY4y++IjpHgUGhWGELDc2NEQAqxwZZg=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -777,12 +777,10 @@ github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7
github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc/v3 v3.0.1 h1:3n7Es68YYGZb2Jf+k//llA4FTZMl3yCwIjFIk4ubevI=
github.com/lestrrat-go/httprc/v3 v3.0.1/go.mod h1:2uAvmbXE4Xq8kAUjVrZOq1tZVYYYs5iP62Cmtru00xk=
github.com/lestrrat-go/jwx/v3 v3.0.12 h1:p25r68Y4KrbBdYjIsQweYxq794CtGCzcrc5dGzJIRjg=
github.com/lestrrat-go/jwx/v3 v3.0.12/go.mod h1:HiUSaNmMLXgZ08OmGBaPVvoZQgJVOQphSrGr5zMamS8=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/httprc/v3 v3.0.2 h1:7u4HUaD0NQbf2/n5+fyp+T10hNCsAnwKfqn4A4Baif0=
github.com/lestrrat-go/httprc/v3 v3.0.2/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0=
github.com/lestrrat-go/jwx/v3 v3.0.13 h1:AdHKiPIYeCSnOJtvdpipPg/0SuFh9rdkN+HF3O0VdSk=
github.com/lestrrat-go/jwx/v3 v3.0.13/go.mod h1:2m0PV1A9tM4b/jVLMx8rh6rBl7F6WGb3EG2hufN9OQU=
github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss=
github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg=
github.com/libregraph/idm v0.5.0 h1:tDMwKbAOZzdeDYMxVlY5PbSqRKO7dbAW9KT42A51WSk=
@@ -849,8 +847,8 @@ github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3v
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/mileusna/useragent v1.3.5 h1:SJM5NzBmh/hO+4LGeATKpaEX9+b4vcGg2qXGLiNGDws=
github.com/mileusna/useragent v1.3.5/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
@@ -916,8 +914,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g=
github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
github.com/nats-io/nats-server/v2 v2.12.3 h1:KRv+1n7lddMVgkJPQer+pt36TcO0ENxjilBmeWdjcHs=
github.com/nats-io/nats-server/v2 v2.12.3/go.mod h1:MQXjG9WjyXKz9koWzUc3jYUMKD8x3CLmTNy91IQQz3Y=
github.com/nats-io/nats-server/v2 v2.12.4 h1:ZnT10v2LU2Xcoiy8ek9X6Se4YG8EuMfIfvAEuFVx1Ts=
github.com/nats-io/nats-server/v2 v2.12.4/go.mod h1:5MCp/pqm5SEfsvVZ31ll1088ZTwEUdvRX1Hmh/mTTDg=
github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U=
github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.12 h1:nssm7JKOG9/x4J8II47VWCL1Ds29avyiQDRn0ckMvDc=
@@ -952,25 +950,25 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE=
github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
github.com/open-policy-agent/opa v1.12.3 h1:qe3m/w52baKC/HJtippw+hYBUKCzuBCPjB+D5P9knfc=
github.com/open-policy-agent/opa v1.12.3/go.mod h1:RnDgm04GA1RjEXJvrsG9uNT/+FyBNmozcPvA2qz60M4=
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
github.com/open-policy-agent/opa v1.13.2 h1:c72l7DhxP4g8DEUBOdaU9QBKyA24dZxCcIuZNRZ0yP4=
github.com/open-policy-agent/opa v1.13.2/go.mod h1:M3Asy9yp1YTusUU5VQuENDe92GLmamIuceqjw+C8PHY=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a h1:Sakl76blJAaM6NxylVkgSzktjo2dS504iDotEFJsh3M=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+lP5lUUIzjRGDg93WrQfZJZCaV1ZP3KeyXi8bzY=
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI=
github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9 h1:dIftlX03Bzfbujhp9B54FbgER0VBDWJi/w8RBxJlzxU=
github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9/go.mod h1:JWyDC6H+5oZRdUJUgKuaye+8Ph5hEs6HVzVoPKzWSGI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76 h1:vD/EdfDUrv4omSFjrinT8Mvf+8D7f9g4vgQ2oiDrVUI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
github.com/opencloud-eu/reva/v2 v2.42.1 h1:QUZOLSfAhb7bw+qsVSFMFY644rUz4/NtnOiJ0QQxj2o=
github.com/opencloud-eu/reva/v2 v2.42.1/go.mod h1:pv+w23JG0/qJweZbTzNNev//YEvlUML1L/2iXgKGkkg=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260204102724-10bcda1b3068 h1:i09YEVYbiUBMhxyak93REn/ZJOTRhAN4I3PXp2nCXgU=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260204102724-10bcda1b3068/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
github.com/opencloud-eu/reva/v2 v2.42.4 h1:e1jNg5IGtRul7JUnrqMIa4lYFjAfbGzNZaSSJL/4h5U=
github.com/opencloud-eu/reva/v2 v2.42.4/go.mod h1:uYGfaWGUxQOKnLSbu8tFUHBz2AFib263VGfyapuxILA=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@@ -1022,8 +1020,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om
github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k=
github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/alertmanager v0.30.1 h1:427prmCHuy1rMmV7fl/TVQFh5A/78XQ/Mp+TsswZNGM=
github.com/prometheus/alertmanager v0.30.1/go.mod h1:93PBumcTLr/gNtNtM0m7BcCffbvYP5bKuLBWiOnISaA=
github.com/prometheus/alertmanager v0.31.1 h1:eAmIC42lzbWslHkMt693T36qdxfyZULswiHr681YS3Q=
github.com/prometheus/alertmanager v0.31.1/go.mod h1:zWPQwhbLt2ybee8rL921UONeQ59Oncash+m/hGP17tU=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
@@ -1056,8 +1054,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc=
github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI=
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
github.com/prometheus/procfs v0.0.0-20170703101242-e645f4e5aaa8/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -1103,12 +1101,12 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/samber/slog-common v0.19.0 h1:fNcZb8B2uOLooeYwFpAlKjkQTUafdjfqKcwcC89G9YI=
github.com/samber/slog-common v0.19.0/go.mod h1:dTz+YOU76aH007YUU0DffsXNsGFQRQllPQh9XyNoA3M=
github.com/samber/slog-zerolog/v2 v2.9.0 h1:6LkOabJmZdNLaUWkTC3IVVA+dq7b/V0FM6lz6/7+THI=
github.com/samber/slog-zerolog/v2 v2.9.0/go.mod h1:gnQW9VnCfM34v2pRMUIGMsZOVbYLqY/v0Wxu6atSVGc=
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/samber/slog-common v0.20.0 h1:WaLnm/aCvBJSk5nR5aXZTFBaV0B47A+AEaEOiZDeUnc=
github.com/samber/slog-common v0.20.0/go.mod h1:+Ozat1jgnnE59UAlmNX1IF3IByHsODnnwf9jUcBZ+m8=
github.com/samber/slog-zerolog/v2 v2.9.1 h1:RMOq8XqzfuGx1X0TEIlS9OXbbFmqLY2/wJppghz66YY=
github.com/samber/slog-zerolog/v2 v2.9.1/go.mod h1:DQYYve14WgCRN/XnKeHl4266jXK0DgYkYXkfZ4Fp98k=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
@@ -1142,8 +1140,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
@@ -1196,6 +1194,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
@@ -1246,8 +1245,8 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fastjson v1.6.7 h1:ZE4tRy0CIkh+qDc5McjatheGX2czdn8slQjomexVpBM=
github.com/valyala/fastjson v1.6.7/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vektah/gqlparser/v2 v2.5.31 h1:YhWGA1mfTjID7qJhd1+Vxhpk5HTgydrGU9IgkWBTJ7k=
@@ -1311,30 +1310,30 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 h1:RN3ifU8y4prNWeEnQp2kRRHz8UwonAEYZl8tUzHEXAk=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0/go.mod h1:habDz3tEWiFANTo6oUE99EmaFUrCNYAAg3wiVmusm70=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ=
go.opentelemetry.io/contrib/zpages v0.64.0 h1:iMybqKVR8AHHxFX4DuEWJ9dY75+9E7+IPwUK3Ll7NxM=
go.opentelemetry.io/contrib/zpages v0.64.0/go.mod h1:DnkiyoQ7Yx/NmmKn10b6M2YBXreUqq0qhFa/kYgSZME=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0/go.mod h1:Rp0EXBm5tfnv0WL+ARyO/PHBEaEAT8UUHQ6AGJcSq6c=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0/go.mod h1:MZ1T/+51uIVKlRzGw1Fo46KEWThjlCBZKl2LzY5nv4g=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
go.opentelemetry.io/contrib/zpages v0.65.0 h1:mi6aZS4PRSDIOYmr8DB7mdKpuyL+Q7ivIhbq2UV+NrQ=
go.opentelemetry.io/contrib/zpages v0.65.0/go.mod h1:eMI6Q53htJ08b8+QxQsIjofw+oUSsT4ieNGu5fcimoU=
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 h1:MzfofMZN8ulNqobCmCAVbqVL5syHw+eB2qPRkCMA/fQ=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0/go.mod h1:E73G9UFtKRXrxhBsHtG00TB5WxX57lpsQzogDkqBTz8=
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -1377,8 +1376,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
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.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
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=
@@ -1394,8 +1393,8 @@ golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScy
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.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
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=
@@ -1420,8 +1419,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.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
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=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1474,8 +1473,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
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.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
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=
@@ -1483,8 +1482,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1587,8 +1586,8 @@ 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.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1600,8 +1599,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1616,8 +1615,8 @@ 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.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
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.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1680,8 +1679,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.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1745,10 +1744,10 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 h1:vmC/ws+pLzWjj/gzApyoZuSVrDtF1aod4u/+bbj8hgM=
google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1764,8 +1763,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU=
google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -1801,6 +1800,8 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k=
gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss=
gopkg.in/ns1/ns1-go.v2 v2.4.4/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYhsPk=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=

View File

@@ -34,7 +34,7 @@ var (
// LatestTag is the latest released version plus the dev meta version.
// Will be overwritten by the release pipeline
// Needs a manual change for every tagged release
LatestTag = "5.0.1+dev"
LatestTag = "5.1.0+dev"
// Date indicates the build date.
// This has been removed, it looks like you can only replace static strings with recent go versions

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jörn Friedrich Dreyer <jfd@butonic.de>, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Elías Martín, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-25 00:11+0000\n"
"POT-Creation-Date: 2026-02-14 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Broglia, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
# iikaka88, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-27 00:11+0000\n"
"POT-Creation-Date: 2026-02-16 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Last-Translator: iikaka88, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Junghyuk Kwon <kwon@junghy.uk>, 2025\n"
"Language-Team: Korean (https://app.transifex.com/opencloud-eu/teams/204053/ko/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-12 00:08+0000\n"
"POT-Creation-Date: 2026-02-22 00:12+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/opencloud-eu/teams/204053/nl/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Mário Machado, 2025\n"
"Language-Team: Portuguese (https://app.transifex.com/opencloud-eu/teams/204053/pt/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-12 00:08+0000\n"
"POT-Creation-Date: 2026-02-22 00:12+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Lulufox, 2025\n"
"Language-Team: Russian (https://app.transifex.com/opencloud-eu/teams/204053/ru/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-28 00:12+0000\n"
"POT-Creation-Date: 2026-02-17 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>, 2025\n"
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-26 00:11+0000\n"
"POT-Creation-Date: 2026-02-15 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Quan Tran, 2025\n"
"Language-Team: Vietnamese (https://app.transifex.com/opencloud-eu/teams/204053/vi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: YQS Yang, 2025\n"
"Language-Team: Chinese (https://app.transifex.com/opencloud-eu/teams/204053/zh/)\n"

View File

@@ -46,21 +46,21 @@ func defaultMimeTypeConfig() []config.MimeTypeConfig {
{
MimeType: "application/vnd.oasis.opendocument.text",
Extension: "odt",
Name: "OpenDocument",
Name: "Document",
Description: "OpenDocument text document",
AllowCreation: true,
},
{
MimeType: "application/vnd.oasis.opendocument.spreadsheet",
Extension: "ods",
Name: "OpenSpreadsheet",
Name: "Spreadsheet",
Description: "OpenDocument spreadsheet document",
AllowCreation: true,
},
{
MimeType: "application/vnd.oasis.opendocument.presentation",
Extension: "odp",
Name: "OpenPresentation",
Name: "Presentation",
Description: "OpenDocument presentation document",
AllowCreation: true,
},
@@ -69,28 +69,24 @@ func defaultMimeTypeConfig() []config.MimeTypeConfig {
Extension: "docx",
Name: "Microsoft Word",
Description: "Microsoft Word document",
AllowCreation: true,
},
{
MimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.form",
Extension: "docxf",
Name: "Form Document",
Description: "Form Document",
AllowCreation: true,
},
{
MimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
Extension: "xlsx",
Name: "Microsoft Excel",
Description: "Microsoft Excel document",
AllowCreation: true,
},
{
MimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
Extension: "pptx",
Name: "Microsoft PowerPoint",
Description: "Microsoft PowerPoint document",
AllowCreation: true,
},
{
MimeType: "application/vnd.jupyter",

View File

@@ -16,4 +16,5 @@ type FileEvent struct {
type BackchannelLogout struct {
UserID string `json:"userid"`
Timestamp string `json:"timestamp"`
SessionID string `json:"sessionid"`
}

View File

@@ -300,5 +300,6 @@ func backchannelLogoutEvent(e events.BackchannelLogout) (string, []string, Backc
return "backchannel-logout", []string{e.Executant.GetOpaqueId()}, BackchannelLogout{
UserID: e.Executant.GetOpaqueId(),
Timestamp: e.Timestamp.String(),
SessionID: e.SessionId,
}
}

View File

@@ -172,7 +172,7 @@ type OCDav struct {
type NameValidation struct {
InvalidChars []string `yaml:"invalid_chars" env:"OCDAV_NAME_VALIDATION_INVALID_CHARS;FRONTENT_OCDAV_NAME_VALIDATION_INVALID_CHARS" desc:"List of characters that are not allowed in file or folder names." introductionVersion:"%%NEXT%%"`
MaxLength int `yaml:"max_length" env:"OCDAV_NAME_VALIDATION_MAX_LENGTH;FRONTENT_OCDAV_NAME_VALIDATION_MAX_LENGTH" desc:"Max lenght og file or folder names." introductionVersion:"%%NEXT%%"`
MaxLength int `yaml:"max_length" env:"OCDAV_NAME_VALIDATION_MAX_LENGTH;FRONTENT_OCDAV_NAME_VALIDATION_MAX_LENGTH" desc:"Max length of file or folder names." introductionVersion:"%%NEXT%%"`
}
type CacheWarmupDrivers struct {

View File

@@ -104,7 +104,7 @@ SHARING_PUBLIC_JSONCS3_PROVIDER_ADDR="unix:/var/run/opencloud/storage-system.soc
## Storage Registry
In order to add another storage provider the CS3 storage registry that is running as part of the CS3 gateway hes to be made aware of it. The easiest cleanest way to do it is to set `GATEWAY_STORAGE_REGISTRY_CONFIG_JSON=/path/to/storages.json` and list all storage providers like this:
In order to add another storage provider the CS3 storage registry that is running as part of the CS3 gateway has to be made aware of it. The easiest and cleanest way to do it is to set `GATEWAY_STORAGE_REGISTRY_CONFIG_JSON=/path/to/storages.json` and list all storage providers like this:
```json
{
@@ -172,4 +172,4 @@ In order to add another storage provider the CS3 storage registry that is runnin
}
```
In the above replace `{storage-users-mount-uuid}` with the mount UUID that was generated for the storage-users service. You can find it in the `config.yaml` generated on by `opencloud init`. The last entry `eu.opencloud.api.storage-hello` and its `providerid` `"hello-storage-id"` are an example for in additional storage provider, in this case running `hellofs`, an example minimal storage driver.
In the above replace `{storage-users-mount-uuid}` with the mount UUID that was generated for the storage-users service. You can find it in the `config.yaml` generated on by `opencloud init`. The last entry `eu.opencloud.api.storage-hello` and its `providerid` `"hello-storage-id"` are an example for an additional storage provider, in this case running `hellofs`, an example minimal storage driver.

View File

@@ -7,8 +7,8 @@ import (
"github.com/go-ldap/ldap/v3"
"github.com/libregraph/idm/pkg/ldapdn"
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
libregraph "github.com/opencloud-eu/libre-graph-api-go"
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
)
type educationClassAttributeMap struct {

View File

@@ -34,6 +34,7 @@ type educationConfig struct {
type schoolAttributeMap struct {
displayName string
schoolNumber string
externalId string
id string
terminationDate string
}
@@ -48,9 +49,10 @@ const (
)
var (
errNotSet = errors.New("attribute not set")
errSchoolNameExists = errorcode.New(errorcode.NameAlreadyExists, "A school with that name is already present")
errSchoolNumberExists = errorcode.New(errorcode.NameAlreadyExists, "A school with that number is already present")
errNotSet = errors.New("attribute not set")
errSchoolNameExists = errorcode.New(errorcode.NameAlreadyExists, "A school with that name is already present")
errSchoolNumberExists = errorcode.New(errorcode.NameAlreadyExists, "A school with that number is already present")
errSchoolExternalIdExists = errorcode.New(errorcode.NameAlreadyExists, "A school with that external id is already present")
)
func defaultEducationConfig() educationConfig {
@@ -105,6 +107,7 @@ func newSchoolAttributeMap() schoolAttributeMap {
return schoolAttributeMap{
displayName: "ou",
schoolNumber: "openCloudEducationSchoolNumber",
externalId: "openCloudEducationExternalId",
id: "openCloudUUID",
terminationDate: "openCloudEducationSchoolTerminationTimestamp",
}
@@ -121,11 +124,11 @@ func (i *LDAP) CreateEducationSchool(ctx context.Context, school libregraph.Educ
// Check that the school number is not already used
if school.HasSchoolNumber() {
_, err := i.getSchoolByNumber(school.GetSchoolNumber())
switch err {
case nil:
switch {
case err == nil:
logger.Debug().Err(errSchoolNumberExists).Str("schoolNumber", school.GetSchoolNumber()).Msg("duplicate school number")
return nil, errSchoolNumberExists
case ErrNotFound:
case errors.Is(err, ErrNotFound):
break
default:
logger.Error().Err(err).Str("schoolNumber", school.GetSchoolNumber()).Msg("error looking up school by number")
@@ -133,6 +136,21 @@ func (i *LDAP) CreateEducationSchool(ctx context.Context, school libregraph.Educ
}
}
// Check that the school external id is not already used
if school.HasExternalId() {
_, err := i.getSchoolByExternalId(school.GetExternalId())
switch {
case err == nil:
logger.Debug().Err(errSchoolExternalIdExists).Str("externalId", school.GetExternalId()).Msg("duplicate school external id")
return nil, errSchoolExternalIdExists
case errors.Is(err, ErrNotFound):
break
default:
logger.Error().Err(err).Str("externalId", school.GetExternalId()).Msg("error looking up school by external id")
return nil, errorcode.New(errorcode.GeneralException, "error looking up school by external id")
}
}
attributeTypeAndValue := ldap.AttributeTypeAndValue{
Type: i.educationConfig.schoolAttributeMap.displayName,
Value: school.GetDisplayName(),
@@ -147,6 +165,9 @@ func (i *LDAP) CreateEducationSchool(ctx context.Context, school libregraph.Educ
if school.HasSchoolNumber() {
ar.Attribute(i.educationConfig.schoolAttributeMap.schoolNumber, []string{school.GetSchoolNumber()})
}
if school.HasExternalId() {
ar.Attribute(i.educationConfig.schoolAttributeMap.externalId, []string{school.GetExternalId()})
}
if !i.useServerUUID {
ar.Attribute(i.educationConfig.schoolAttributeMap.id, []string{uuid.NewString()})
}
@@ -278,14 +299,14 @@ func (i *LDAP) updateSchoolProperties(ctx context.Context, dn string, currentSch
}
// UpdateEducationSchool updates the supplied school in the identity backend
func (i *LDAP) UpdateEducationSchool(ctx context.Context, numberOrID string, school libregraph.EducationSchool) (*libregraph.EducationSchool, error) {
func (i *LDAP) UpdateEducationSchool(ctx context.Context, numberOrIDOrExternalID string, school libregraph.EducationSchool) (*libregraph.EducationSchool, error) {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("UpdateEducationSchool")
if !i.writeEnabled {
return nil, ErrReadOnly
}
e, err := i.getSchoolByNumberOrID(numberOrID)
e, err := i.getSchoolByNumberOrIDOrExternalID(numberOrIDOrExternalID)
if err != nil {
return nil, err
}
@@ -308,7 +329,7 @@ func (i *LDAP) UpdateEducationSchool(ctx context.Context, numberOrID string, sch
}
// Read back school from LDAP
e, err = i.getSchoolByNumberOrID(i.getID(e))
e, err = i.getSchoolByNumberOrIDOrExternalID(i.getID(e))
if err != nil {
return nil, err
}
@@ -322,7 +343,7 @@ func (i *LDAP) DeleteEducationSchool(ctx context.Context, id string) error {
if !i.writeEnabled {
return ErrReadOnly
}
e, err := i.getSchoolByNumberOrID(id)
e, err := i.getSchoolByNumberOrIDOrExternalID(id)
if err != nil {
return err
}
@@ -337,10 +358,10 @@ func (i *LDAP) DeleteEducationSchool(ctx context.Context, id string) error {
}
// GetEducationSchool implements the EducationBackend interface for the LDAP backend.
func (i *LDAP) GetEducationSchool(ctx context.Context, numberOrID string) (*libregraph.EducationSchool, error) {
func (i *LDAP) GetEducationSchool(ctx context.Context, numberOrIDOrExternalID string) (*libregraph.EducationSchool, error) {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("GetEducationSchool")
e, err := i.getSchoolByNumberOrID(numberOrID)
e, err := i.getSchoolByNumberOrIDOrExternalID(numberOrIDOrExternalID)
if err != nil {
return nil, err
}
@@ -415,11 +436,11 @@ func (i *LDAP) GetEducationSchoolUsers(ctx context.Context, schoolNumberOrID str
}
// AddUsersToEducationSchool adds new members (reference by a slice of IDs) to supplied school in the identity backend.
func (i *LDAP) AddUsersToEducationSchool(ctx context.Context, schoolNumberOrID string, memberIDs []string) error {
func (i *LDAP) AddUsersToEducationSchool(ctx context.Context, schoolNumberOrIDOrExternalID string, memberIDs []string) error {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("AddUsersToEducationSchool")
schoolEntry, err := i.getSchoolByNumberOrID(schoolNumberOrID)
schoolEntry, err := i.getSchoolByNumberOrIDOrExternalID(schoolNumberOrIDOrExternalID)
if err != nil {
return err
}
@@ -462,11 +483,11 @@ func (i *LDAP) AddUsersToEducationSchool(ctx context.Context, schoolNumberOrID s
}
// RemoveUserFromEducationSchool removes a single member (by ID) from a school
func (i *LDAP) RemoveUserFromEducationSchool(ctx context.Context, schoolNumberOrID string, memberID string) error {
func (i *LDAP) RemoveUserFromEducationSchool(ctx context.Context, schoolNumberOrIDOrExternalID string, memberID string) error {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("RemoveUserFromEducationSchool")
schoolEntry, err := i.getSchoolByNumberOrID(schoolNumberOrID)
schoolEntry, err := i.getSchoolByNumberOrIDOrExternalID(schoolNumberOrIDOrExternalID)
if err != nil {
return err
}
@@ -521,12 +542,12 @@ func (i *LDAP) GetEducationSchoolClasses(ctx context.Context, schoolNumberOrID s
}
func (i *LDAP) getEducationSchoolEntries(
schoolNumberOrID, filter, objectClass, baseDN string,
schoolNumberOrIDOrExternalID, filter, objectClass, baseDN string,
scope int,
attributes []string,
logger log.Logger,
) ([]*ldap.Entry, error) {
schoolEntry, err := i.getSchoolByNumberOrID(schoolNumberOrID)
schoolEntry, err := i.getSchoolByNumberOrIDOrExternalID(schoolNumberOrIDOrExternalID)
if err != nil {
return nil, err
}
@@ -563,11 +584,11 @@ func (i *LDAP) getEducationSchoolEntries(
}
// AddClassesToEducationSchool adds new members (reference by a slice of IDs) to supplied school in the identity backend.
func (i *LDAP) AddClassesToEducationSchool(ctx context.Context, schoolNumberOrID string, memberIDs []string) error {
func (i *LDAP) AddClassesToEducationSchool(ctx context.Context, schoolNumberOrIDOrExternalID string, memberIDs []string) error {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("AddClassesToEducationSchool")
schoolEntry, err := i.getSchoolByNumberOrID(schoolNumberOrID)
schoolEntry, err := i.getSchoolByNumberOrIDOrExternalID(schoolNumberOrIDOrExternalID)
if err != nil {
return err
}
@@ -610,11 +631,11 @@ func (i *LDAP) AddClassesToEducationSchool(ctx context.Context, schoolNumberOrID
}
// RemoveClassFromEducationSchool removes a single member (by ID) from a school
func (i *LDAP) RemoveClassFromEducationSchool(ctx context.Context, schoolNumberOrID string, memberID string) error {
func (i *LDAP) RemoveClassFromEducationSchool(ctx context.Context, schoolNumberOrIDOrExternalID string, memberID string) error {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("RemoveClassFromEducationSchool")
schoolEntry, err := i.getSchoolByNumberOrID(schoolNumberOrID)
schoolEntry, err := i.getSchoolByNumberOrIDOrExternalID(schoolNumberOrIDOrExternalID)
if err != nil {
return err
}
@@ -652,14 +673,16 @@ func (i *LDAP) getSchoolByDN(dn string) (*ldap.Entry, error) {
return i.getEntryByDN(dn, i.getEducationSchoolAttrTypes(), filter)
}
func (i *LDAP) getSchoolByNumberOrID(numberOrID string) (*ldap.Entry, error) {
numberOrID = ldap.EscapeFilter(numberOrID)
func (i *LDAP) getSchoolByNumberOrIDOrExternalID(numberOrIDOrExternalID string) (*ldap.Entry, error) {
numberOrIDOrExternalID = ldap.EscapeFilter(numberOrIDOrExternalID)
filter := fmt.Sprintf(
"(|(%s=%s)(%s=%s))",
"(|(%s=%s)(%s=%s)(%s=%s))",
i.educationConfig.schoolAttributeMap.id,
numberOrID,
numberOrIDOrExternalID,
i.educationConfig.schoolAttributeMap.schoolNumber,
numberOrID,
numberOrIDOrExternalID,
i.educationConfig.schoolAttributeMap.externalId,
numberOrIDOrExternalID,
)
return i.getSchoolByFilter(filter)
}
@@ -674,6 +697,16 @@ func (i *LDAP) getSchoolByNumber(schoolNumber string) (*ldap.Entry, error) {
return i.getSchoolByFilter(filter)
}
func (i *LDAP) getSchoolByExternalId(schoolExternalId string) (*ldap.Entry, error) {
schoolExternalId = ldap.EscapeFilter(schoolExternalId)
filter := fmt.Sprintf(
"(%s=%s)",
i.educationConfig.schoolAttributeMap.externalId,
schoolExternalId,
)
return i.getSchoolByFilter(filter)
}
func (i *LDAP) getSchoolByFilter(filter string) (*ldap.Entry, error) {
filter = fmt.Sprintf("(&%s(objectClass=%s)%s)",
i.educationConfig.schoolFilter,
@@ -723,6 +756,8 @@ func (i *LDAP) createSchoolModelFromLDAP(e *ldap.Entry) *libregraph.EducationSch
id := i.getID(e)
schoolNumber := i.getSchoolNumber(e)
externalId := i.getExternalId(e)
t, err := i.getTerminationDate(e)
if err != nil && !errors.Is(err, errNotSet) {
i.logger.Error().Err(err).Str("dn", e.DN).Msg("Error reading termination date for LDAP entry")
@@ -739,6 +774,9 @@ func (i *LDAP) createSchoolModelFromLDAP(e *ldap.Entry) *libregraph.EducationSch
if schoolNumber != "" {
school.SetSchoolNumber(schoolNumber)
}
if externalId != "" {
school.SetExternalId(externalId)
}
if t != nil {
school.SetTerminationDate(*t)
}
@@ -750,6 +788,11 @@ func (i *LDAP) getSchoolNumber(e *ldap.Entry) string {
return schoolNumber
}
func (i *LDAP) getExternalId(e *ldap.Entry) string {
externalId := e.GetEqualFoldAttributeValue(i.educationConfig.schoolAttributeMap.externalId)
return externalId
}
func (i *LDAP) getID(e *ldap.Entry) string {
id := e.GetEqualFoldAttributeValue(i.educationConfig.schoolAttributeMap.id)
return id

View File

@@ -7,10 +7,10 @@ import (
"time"
"github.com/go-ldap/ldap/v3"
libregraph "github.com/opencloud-eu/libre-graph-api-go"
"github.com/opencloud-eu/opencloud/services/graph/pkg/config"
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/mocks"
libregraph "github.com/opencloud-eu/libre-graph-api-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
@@ -45,6 +45,7 @@ var schoolEntry = ldap.NewEntry("ou=Test School",
"ou": {"Test School"},
"openCloudEducationSchoolNumber": {"0123"},
"openCloudUUID": {"abcd-defg"},
"openCloudEducationExternalId": {"abcd-defg"},
})
var schoolEntry1 = ldap.NewEntry("ou=Test School1",
@@ -52,20 +53,22 @@ var schoolEntry1 = ldap.NewEntry("ou=Test School1",
"ou": {"Test School1"},
"openCloudEducationSchoolNumber": {"0042"},
"openCloudUUID": {"hijk-defg"},
"openCloudEducationExternalId": {"hijk-defg"},
})
var schoolEntryWithTermination = ldap.NewEntry("ou=Test School",
map[string][]string{
"ou": {"Test School"},
"openCloudEducationSchoolNumber": {"0123"},
"openCloudUUID": {"abcd-defg"},
"openCloudEducationExternalId": {"abcd-defg"},
"openCloudEducationSchoolTerminationTimestamp": {"20420131120000Z"},
})
var (
filterSchoolSearchByIdExisting = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=abcd-defg)(openCloudEducationSchoolNumber=abcd-defg)))"
filterSchoolSearchByIdNonexistant = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=xxxx-xxxx)(openCloudEducationSchoolNumber=xxxx-xxxx)))"
filterSchoolSearchByNumberExisting = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=0123)(openCloudEducationSchoolNumber=0123)))"
filterSchoolSearchByNumberNonexistant = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=3210)(openCloudEducationSchoolNumber=3210)))"
filterSchoolSearchByIdExisting = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=abcd-defg)(openCloudEducationSchoolNumber=abcd-defg)(openCloudEducationExternalId=abcd-defg)))"
filterSchoolSearchByIdNonexistant = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=xxxx-xxxx)(openCloudEducationSchoolNumber=xxxx-xxxx)(openCloudEducationExternalId=xxxx-xxxx)))"
filterSchoolSearchByNumberExisting = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=0123)(openCloudEducationSchoolNumber=0123)(openCloudEducationExternalId=0123)))"
filterSchoolSearchByNumberNonexistant = "(&(objectClass=openCloudEducationSchool)(|(openCloudUUID=3210)(openCloudEducationSchoolNumber=3210)(openCloudEducationExternalId=3210)))"
)
func TestCreateEducationSchool(t *testing.T) {

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jörn Friedrich Dreyer <jfd@butonic.de>, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Elías Martín, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-25 00:11+0000\n"
"POT-Creation-Date: 2026-02-14 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Broglia, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
# iikaka88, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-27 00:11+0000\n"
"POT-Creation-Date: 2026-02-16 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Last-Translator: iikaka88, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: gapho shin, 2025\n"
"Language-Team: Korean (https://app.transifex.com/opencloud-eu/teams/204053/ko/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/opencloud-eu/teams/204053/nl/)\n"

View File

@@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Radoslaw Posim, 2025\n"
"Language-Team: Polish (https://app.transifex.com/opencloud-eu/teams/204053/pl/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Mário Machado, 2025\n"
"Language-Team: Portuguese (https://app.transifex.com/opencloud-eu/teams/204053/pt/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Lulufox, 2025\n"
"Language-Team: Russian (https://app.transifex.com/opencloud-eu/teams/204053/ru/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-28 00:12+0000\n"
"POT-Creation-Date: 2026-02-17 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>, 2025\n"
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-25 00:11+0000\n"
"POT-Creation-Date: 2026-02-14 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: LinkinWires <darkinsonic13@gmail.com>, 2025\n"
"Language-Team: Ukrainian (https://app.transifex.com/opencloud-eu/teams/204053/uk/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-26 00:11+0000\n"
"POT-Creation-Date: 2026-02-15 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Quan Tran, 2025\n"
"Language-Team: Vietnamese (https://app.transifex.com/opencloud-eu/teams/204053/vi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: YQS Yang, 2025\n"
"Language-Team: Chinese (https://app.transifex.com/opencloud-eu/teams/204053/zh/)\n"

View File

@@ -7,7 +7,7 @@
"analyze": "source-map-explorer 'build/static/js/*.js'",
"build": "node --openssl-legacy-provider scripts/build.js && rm -f build/service-worker.js",
"licenses": "NODE_PATH=./node_modules node ../scripts/js-license-ranger.js",
"licenses:check": "license-checker-rseidelsohn --summary --relativeLicensePath --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL;ODC-By-1.0;BlueOak-1.0.0;OFL-1.1' --excludePackages 'identifier;kpop;unicoderegexp' --clarificationsFile license-checker-clarifications.json",
"licenses:check": "license-checker-rseidelsohn --summary --relativeLicensePath --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL;ODC-By-1.0;BlueOak-1.0.0;OFL-1.1' --excludePackages 'identifier;unicoderegexp' --clarificationsFile license-checker-clarifications.json",
"licenses:csv": "license-checker-rseidelsohn --relativeLicensePath --csv --out ../../third-party-licenses/node/idp/third-party-licenses.csv",
"licenses:save": "license-checker-rseidelsohn --relativeLicensePath --out /dev/null --files ../../third-party-licenses/node/idp/third-party-licenses",
"lint": "eslint ./**/*.{tsx,ts,jsx,js}",
@@ -71,26 +71,25 @@
]
},
"dependencies": {
"@fontsource/roboto": "^5.2.5",
"@fontsource/roboto": "^5.2.9",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/jest": "^30.0.0",
"@types/node": "^22.15.30",
"@types/react": "^17.0.80",
"@types/react-dom": "^17.0.25",
"@types/react-redux": "^7.1.33",
"@types/react-redux": "^7.1.34",
"@types/redux-logger": "^3.0.13",
"axios": "^1.8.2",
"axios": "^1.13.5",
"classnames": "^2.5.1",
"i18next": "^25.2.1",
"i18next-browser-languagedetector": "^8.1.0",
"i18next": "^25.8.11",
"i18next-browser-languagedetector": "^8.2.1",
"i18next-http-backend": "^3.0.2",
"i18next-resources-to-backend": "^1.2.1",
"kpop": "https://download.kopano.io/community/kapp:/kpop-2.7.2.tgz",
"query-string": "^9.2.0",
"query-string": "^9.3.1",
"react": "^17.0.2",
"react-app-polyfill": "^3.0.0",
"react-dom": "^17.0.2",
@@ -102,7 +101,7 @@
"redux-logger": "^3.0.6",
"redux-thunk": "^2.4.2",
"render-if": "^0.1.1",
"web-vitals": "^5.0.2"
"web-vitals": "^5.1.0"
},
"devDependencies": {
"@babel/core": "7.26.10",
@@ -114,16 +113,16 @@
"babel-preset-react-app": "^10.1.0",
"case-sensitive-paths-webpack-plugin": "2.4.0",
"cldr": "^7.9.0",
"css-loader": "7.1.2",
"css-minimizer-webpack-plugin": "^7.0.2",
"css-loader": "^7.1.4",
"css-minimizer-webpack-plugin": "^7.0.4",
"dotenv": "16.4.7",
"dotenv-expand": "12.0.2",
"dotenv-expand": "^12.0.3",
"eslint": "^7.32.0",
"eslint-config-react-app": "^6.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.10.0",
"eslint-plugin-i18next": "^6.1.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-i18next": "^6.1.3",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^24.7.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
@@ -131,10 +130,10 @@
"eslint-plugin-testing-library": "^3.10.2",
"eslint-webpack-plugin": "^3.2.0",
"file-loader": "6.2.0",
"html-webpack-plugin": "5.6.3",
"html-webpack-plugin": "^5.6.6",
"i18next-conv": "^15.1.1",
"i18next-parser": "^9.3.0",
"jest": "30.0.0",
"jest": "30.2.0",
"license-checker-rseidelsohn": "4.4.2",
"mini-css-extract-plugin": "2.9.2",
"pnp-webpack-plugin": "1.7.0",
@@ -144,20 +143,15 @@
"postcss-preset-env": "10.1.3",
"postcss-safe-parser": "7.0.1",
"react-dev-utils": "^12.0.1",
"resolve": "1.22.8",
"resolve": "^1.22.11",
"resolve-url-loader": "^5.0.0",
"sass-loader": "^16.0.5",
"sass-loader": "^16.0.7",
"source-map-explorer": "^2.5.3",
"typescript": "^5.8.3",
"url-loader": "4.1.1",
"webpack": "5.99.6",
"webpack": "5.105.2",
"webpack-manifest-plugin": "5.0.0",
"workbox-webpack-plugin": "7.1.0"
"workbox-webpack-plugin": "7.4.0"
},
"packageManager": "pnpm@9.15.4",
"pnpm": {
"overrides": {
"kpop>cldr": ""
}
}
"packageManager": "pnpm@9.15.4"
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,10 +2,7 @@ import React, {ReactElement, Suspense, lazy, useState, useEffect} from 'react';
import PropTypes from 'prop-types';
import {MuiThemeProvider} from '@material-ui/core/styles';
import {defaultTheme} from 'kpop/es/theme';
import 'kpop/static/css/base.css';
import 'kpop/static/css/scrollbar.css';
import muiTheme from './theme';
import Spinner from './components/Spinner';
import * as version from './version';
@@ -52,7 +49,7 @@ const App = ({ bgImg }): ReactElement => {
className={`oc-login-bg ${bgImg ? 'oc-login-bg-image' : ''}`}
style={{backgroundImage: bgImg ? `url(${bgImg})` : undefined}}
>
<MuiThemeProvider theme={defaultTheme}>
<MuiThemeProvider theme={muiTheme}>
<Suspense fallback={<Spinner/>}>
<LazyMain/>
</Suspense>

View File

@@ -1,4 +1,3 @@
/* additional css on top of kpop */
@font-face {
font-family: OpenCloud;
src: url('./fonts/OpenCloud500-Regular.woff2') format('woff2');
@@ -17,16 +16,25 @@
html {
font-feature-settings: "cv11";
color: #20434f !important;
height: 100%;
}
body {
font-family: OpenCloud, sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
strong {
font-weight: 600;
}
#root {
height: 100%;
display: flex;
}
.oc-font-weight-light {
font-weight: 300;
}

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jonas, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: miguel tapias, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-23 00:11+0000\n"
"POT-Creation-Date: 2026-02-12 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Broglia, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
# iikaka88, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-27 00:11+0000\n"
"POT-Creation-Date: 2026-02-16 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Last-Translator: iikaka88, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: gapho shin, 2025\n"
"Language-Team: Korean (https://app.transifex.com/opencloud-eu/teams/204053/ko/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/opencloud-eu/teams/204053/nl/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Mário Machado, 2025\n"
"Language-Team: Portuguese (https://app.transifex.com/opencloud-eu/teams/204053/pt/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Lulufox, 2025\n"
"Language-Team: Russian (https://app.transifex.com/opencloud-eu/teams/204053/ru/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-28 00:12+0000\n"
"POT-Creation-Date: 2026-02-17 00:16+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>, 2025\n"
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: YQS Yang, 2025\n"
"Language-Team: Chinese (https://app.transifex.com/opencloud-eu/teams/204053/zh/)\n"

View File

@@ -86,6 +86,7 @@ type ScienceMesh struct {
MeshDirectoryURL string `yaml:"science_mesh_directory_url" env:"OCM_MESH_DIRECTORY_URL" desc:"URL of the mesh directory service." introductionVersion:"1.0.0"`
DirectoryServiceURLs string `yaml:"directory_service_urls" env:"OCM_DIRECTORY_SERVICE_URLS" desc:"Space delimited URLs of the directory services." introductionVersion:"3.5.0"`
InviteAcceptDialog string `yaml:"invite_accept_dialog" env:"OCM_INVITE_ACCEPT_DIALOG" desc:"/open-cloud-mesh/accept-invite;The frontend URL where to land when receiving an invitation" introductionVersion:"3.5.0"`
OCMClientInsecure bool `yaml:"ocm_client_insecure" env:"OC_INSECURE;OCM_CLIENT_INSECURE" desc:"Dev-only. Disable TLS verification for the OCM discovery client (directory fetch and provider discovery). Does not affect OCM invite manager, storage provider, or share provider. Do not set in production." introductionVersion:"%%NEXT%%"`
}
type OCMD struct {

View File

@@ -76,6 +76,7 @@ func OCMConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]inter
"gatewaysvc": cfg.Reva.Address,
"mesh_directory_url": cfg.ScienceMesh.MeshDirectoryURL,
"directory_service_urls": cfg.ScienceMesh.DirectoryServiceURLs,
"ocm_client_insecure": cfg.ScienceMesh.OCMClientInsecure,
"provider_domain": providerDomain,
"events": map[string]interface{}{
"natsaddress": cfg.Events.Endpoint,

View File

@@ -12,3 +12,8 @@ packages:
github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles:
interfaces:
UserRoleAssigner: {}
go-micro.dev/v4/store:
config:
dir: pkg/staticroutes/internal/backchannellogout/mocks
interfaces:
Store: {}

View File

@@ -10,6 +10,7 @@ import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/justinas/alice"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/generators"
"github.com/opencloud-eu/opencloud/pkg/log"
@@ -72,6 +73,7 @@ func Server(cfg *config.Config) *cobra.Command {
microstore.Nodes(cfg.PreSignedURL.SigningKeys.Nodes...),
microstore.Database("proxy"),
microstore.Table("signing-keys"),
store.DisablePersistence(cfg.PreSignedURL.SigningKeys.DisablePersistence),
store.Authentication(cfg.PreSignedURL.SigningKeys.AuthUsername, cfg.PreSignedURL.SigningKeys.AuthPassword),
)

View File

@@ -134,7 +134,7 @@ type Cache struct {
Nodes []string `yaml:"addresses" env:"OC_CACHE_STORE_NODES;PROXY_OIDC_USERINFO_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' store is configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
Database string `yaml:"database" env:"OC_CACHE_DATABASE" desc:"The database name the configured store should use." introductionVersion:"1.0.0"`
Table string `yaml:"table" env:"PROXY_OIDC_USERINFO_CACHE_TABLE" desc:"The database table the store should use." introductionVersion:"1.0.0"`
TTL time.Duration `yaml:"ttl" env:"OC_CACHE_TTL;PROXY_OIDC_USERINFO_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
TTL time.Duration `yaml:"ttl" env:"OC_CACHE_TTL;PROXY_OIDC_USERINFO_CACHE_TTL" desc:"Default time to live for user info in the user info cache. This value is only applied when the token expiration cannot be extracted from the access tokens (e.g. when non-JWT access tokes are used). See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
DisablePersistence bool `yaml:"disable_persistence" env:"OC_CACHE_DISABLE_PERSISTENCE;PROXY_OIDC_USERINFO_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false." introductionVersion:"1.0.0"`
AuthUsername string `yaml:"username" env:"OC_CACHE_AUTH_USERNAME;PROXY_OIDC_USERINFO_CACHE_AUTH_USERNAME" desc:"The username to authenticate with the cache. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
AuthPassword string `yaml:"password" env:"OC_CACHE_AUTH_PASSWORD;PROXY_OIDC_USERINFO_CACHE_AUTH_PASSWORD" desc:"The password to authenticate with the cache. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`

View File

@@ -8,14 +8,15 @@ import (
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/oidc"
"github.com/pkg/errors"
"github.com/vmihailenco/msgpack/v5"
store "go-micro.dev/v4/store"
"go-micro.dev/v4/store"
"golang.org/x/crypto/sha3"
"golang.org/x/oauth2"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/oidc"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/staticroutes"
)
const (
@@ -68,12 +69,13 @@ func (m *OIDCAuthenticator) getClaims(token string, req *http.Request) (map[stri
if len(record) > 0 {
if err = msgpack.Unmarshal(record[0].Value, &claims); err == nil {
m.Logger.Debug().Interface("claims", claims).Msg("cache hit for userinfo")
if ok := verifyExpiresAt(claims, m.TimeFunc()); !ok {
return nil, false, jwt.ErrTokenExpired
if verifyExpiresAt(claims, m.TimeFunc()) {
return claims, false, nil
}
return claims, false, nil
m.Logger.Debug().Msg("cached userinfo claims expired, ignoring cache")
} else {
m.Logger.Error().Err(err).Msg("failed to unmarshal cached userinfo, ignoring cache")
}
m.Logger.Error().Err(err).Msg("could not unmarshal userinfo")
}
aClaims, claims, err := m.oidcClient.VerifyAccessToken(req.Context(), token)
@@ -114,16 +116,25 @@ func (m *OIDCAuthenticator) getClaims(token string, req *http.Request) (map[stri
m.Logger.Error().Err(err).Msg("failed to write to userinfo cache")
}
if sid := aClaims.SessionID; sid != "" {
// reuse user cache for session id lookup
err = m.userInfoCache.Write(&store.Record{
Key: sid,
Value: []byte(encodedHash),
Expiry: time.Until(expiration),
})
if err != nil {
m.Logger.Error().Err(err).Msg("failed to write session lookup cache")
}
// fail if creating the storage key fails,
// it means there is no subject and no session.
//
// ok: {key: ".sessionId"}
// ok: {key: "subject."}
// ok: {key: "subject.sessionId"}
// fail: {key: "."}
subjectSessionKey, err := staticroutes.NewRecordKey(aClaims.Subject, aClaims.SessionID)
if err != nil {
m.Logger.Error().Err(err).Msg("failed to build subject.session")
return
}
if err := m.userInfoCache.Write(&store.Record{
Key: subjectSessionKey,
Value: []byte(encodedHash),
Expiry: time.Until(expiration),
}); err != nil {
m.Logger.Error().Err(err).Msg("failed to write session lookup cache")
}
}
}()

View File

@@ -6,17 +6,40 @@ import (
"net/http"
"github.com/go-chi/render"
"github.com/opencloud-eu/opencloud/pkg/oidc"
"github.com/opencloud-eu/reva/v2/pkg/events"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/pkg/errors"
"github.com/vmihailenco/msgpack/v5"
microstore "go-micro.dev/v4/store"
bcl "github.com/opencloud-eu/opencloud/services/proxy/pkg/staticroutes/internal/backchannellogout"
"github.com/opencloud-eu/reva/v2/pkg/events"
"github.com/opencloud-eu/reva/v2/pkg/utils"
)
// handle backchannel logout requests as per https://openid.net/specs/openid-connect-backchannel-1_0.html#BCRequest
// NewRecordKey converts the subject and session to a base64 encoded key
var NewRecordKey = bcl.NewKey
// backchannelLogout handles backchannel logout requests from the identity provider and invalidates the related sessions in the cache
// spec: https://openid.net/specs/openid-connect-backchannel-1_0.html#BCRequest
//
// known side effects of backchannel logout in keycloak:
//
// - keyCloak "Sign out all active sessions" does not send a backchannel logout request,
// as the devs mention, this may lead to thousands of backchannel logout requests,
// therefore, they recommend a short token lifetime.
// https://github.com/keycloak/keycloak/issues/27342#issuecomment-2408461913
//
// - keyCloak user self-service portal, "Sign out all devices" may not send a backchannel
// logout request for each session, it's not mentionex explicitly,
// but maybe the reason for that is the same as for "Sign out all active sessions"
// to prevent a flood of backchannel logout requests.
//
// - if the keycloak setting "Backchannel logout session required" is disabled (or the token has no session id),
// we resolve the session by the subject which can lead to multiple session records (subject.*),
// we then send a logout event (sse) to each connected client and delete our stored cache record (subject.session & claim).
// all sessions besides the one that triggered the backchannel logout continue to exist in the identity provider,
// so the user will not be fully logged out until all sessions are logged out or expired.
// this leads to the situation that web renders the logout view even if the instance is not fully logged out yet.
func (s *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Request) {
// parse the application/x-www-form-urlencoded POST request
logger := s.Logger.SubloggerWithRequestID(r.Context())
if err := r.ParseForm(); err != nil {
logger.Warn().Err(err).Msg("ParseForm failed")
@@ -27,45 +50,84 @@ func (s *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
logoutToken, err := s.OidcClient.VerifyLogoutToken(r.Context(), r.PostFormValue("logout_token"))
if err != nil {
logger.Warn().Err(err).Msg("VerifyLogoutToken failed")
msg := "failed to verify logout token"
logger.Warn().Err(err).Msg(msg)
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: msg})
return
}
records, err := s.UserInfoCache.Read(logoutToken.SessionId)
if errors.Is(err, microstore.ErrNotFound) || len(records) == 0 {
lookupKey, err := bcl.NewKey(logoutToken.Subject, logoutToken.SessionId)
if err != nil {
msg := "failed to build key from logout token"
logger.Warn().Err(err).Msg(msg)
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: msg})
return
}
requestSubjectAndSession, err := bcl.NewSuSe(lookupKey)
if err != nil {
msg := "failed to build subjec.session from lookupKey"
logger.Error().Err(err).Msg(msg)
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: msg})
return
}
lookupRecords, err := bcl.GetLogoutRecords(requestSubjectAndSession, s.UserInfoCache)
if errors.Is(err, microstore.ErrNotFound) || len(lookupRecords) == 0 {
render.Status(r, http.StatusOK)
render.JSON(w, r, nil)
return
}
if err != nil {
logger.Error().Err(err).Msg("Error reading userinfo cache")
msg := "failed to read userinfo cache"
logger.Error().Err(err).Msg(msg)
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: msg})
return
}
for _, record := range records {
err := s.publishBackchannelLogoutEvent(r.Context(), record, logoutToken)
for _, record := range lookupRecords {
// the record key is in the format "subject.session" or ".session"
// the record value is the key of the record that contains the claim in its value
key, value := record.Key, string(record.Value)
subjectSession, err := bcl.NewSuSe(key)
if err != nil {
s.Logger.Warn().Err(err).Msg("could not publish backchannel logout event")
// never leak any key-related information
logger.Warn().Err(err).Msgf("failed to parse key: %s", key)
continue
}
err = s.UserInfoCache.Delete(string(record.Value))
session, err := subjectSession.Session()
if err != nil {
logger.Warn().Err(err).Msgf("failed to read session for: %s", key)
continue
}
if err := s.publishBackchannelLogoutEvent(r.Context(), session, value); err != nil {
s.Logger.Warn().Err(err).Msgf("failed to publish backchannel logout event for: %s", key)
continue
}
err = s.UserInfoCache.Delete(value)
if err != nil && !errors.Is(err, microstore.ErrNotFound) {
// Spec requires us to return a 400 BadRequest when the session could not be destroyed
logger.Err(err).Msg("could not delete user info from cache")
// we have to return a 400 BadRequest when we fail to delete the session
// https://openid.net/specs/openid-connect-backchannel-1_0.html#rfc.section.2.8
msg := "failed to delete record"
s.Logger.Warn().Err(err).Msgf("%s for: %s", msg, key)
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: msg})
return
}
logger.Debug().Msg("Deleted userinfo from cache")
}
// we can ignore errors when cleaning up the lookup table
err = s.UserInfoCache.Delete(logoutToken.SessionId)
if err != nil {
logger.Debug().Err(err).Msg("Failed to cleanup sessionid lookup entry")
// we can ignore errors when deleting the lookup record
err = s.UserInfoCache.Delete(key)
if err != nil {
logger.Debug().Err(err).Msgf("failed to delete record for: %s", key)
}
}
render.Status(r, http.StatusOK)
@@ -73,41 +135,42 @@ func (s *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
}
// publishBackchannelLogoutEvent publishes a backchannel logout event when the callback revived from the identity provider
func (s StaticRouteHandler) publishBackchannelLogoutEvent(ctx context.Context, record *microstore.Record, logoutToken *oidc.LogoutToken) error {
func (s *StaticRouteHandler) publishBackchannelLogoutEvent(ctx context.Context, sessionId, claimKey string) error {
if s.EventsPublisher == nil {
return fmt.Errorf("the events publisher is not set")
return errors.New("events publisher not set")
}
urecords, err := s.UserInfoCache.Read(string(record.Value))
if err != nil {
return fmt.Errorf("reading userinfo cache: %w", err)
}
if len(urecords) == 0 {
return fmt.Errorf("userinfo not found")
claimRecords, err := s.UserInfoCache.Read(claimKey)
switch {
case err != nil:
return fmt.Errorf("failed to read userinfo cache: %w", err)
case len(claimRecords) == 0:
return fmt.Errorf("no claim found for key: %s", claimKey)
}
var claims map[string]interface{}
if err = msgpack.Unmarshal(urecords[0].Value, &claims); err != nil {
return fmt.Errorf("could not unmarshal userinfo: %w", err)
if err = msgpack.Unmarshal(claimRecords[0].Value, &claims); err != nil {
return fmt.Errorf("failed to unmarshal claims: %w", err)
}
oidcClaim, ok := claims[s.Config.UserOIDCClaim].(string)
if !ok {
return fmt.Errorf("could not get claim %w", err)
return fmt.Errorf("failed to get claim %w", err)
}
user, _, err := s.UserProvider.GetUserByClaims(ctx, s.Config.UserCS3Claim, oidcClaim)
if err != nil || user.GetId() == nil {
return fmt.Errorf("could not get user by claims: %w", err)
return fmt.Errorf("failed to get user by claims: %w", err)
}
e := events.BackchannelLogout{
Executant: user.GetId(),
SessionId: logoutToken.SessionId,
SessionId: sessionId,
Timestamp: utils.TSNow(),
}
if err := events.Publish(ctx, s.EventsPublisher, e); err != nil {
return fmt.Errorf("could not publish user created event %w", err)
return fmt.Errorf("failed to publish user logout event %w", err)
}
return nil
}

View File

@@ -0,0 +1,185 @@
// package backchannellogout provides functions to classify and lookup
// backchannel logout records from the cache store.
package backchannellogout
import (
"encoding/base64"
"errors"
"strings"
microstore "go-micro.dev/v4/store"
)
// keyEncoding is the base64 encoding used for session and subject keys
var keyEncoding = base64.URLEncoding
// ErrInvalidKey indicates that the provided key does not conform to the expected format.
var ErrInvalidKey = errors.New("invalid key format")
// NewKey converts the subject and session to a base64 encoded key
func NewKey(subject, session string) (string, error) {
subjectSession := strings.Join([]string{
keyEncoding.EncodeToString([]byte(subject)),
keyEncoding.EncodeToString([]byte(session)),
}, ".")
if subjectSession == "." {
return "", ErrInvalidKey
}
return subjectSession, nil
}
// ErrDecoding is returned when decoding fails
var ErrDecoding = errors.New("failed to decode")
// SuSe 🦎 ;) is a struct that groups the subject and session together
// to prevent mix-ups for ('session, subject' || 'subject, session')
// return values.
type SuSe struct {
encodedSubject string
encodedSession string
}
// Subject decodes and returns the subject or an error
func (suse SuSe) Subject() (string, error) {
subject, err := keyEncoding.DecodeString(suse.encodedSubject)
if err != nil {
return "", errors.Join(errors.New("failed to decode subject"), ErrDecoding, err)
}
return string(subject), nil
}
// Session decodes and returns the session or an error
func (suse SuSe) Session() (string, error) {
subject, err := keyEncoding.DecodeString(suse.encodedSession)
if err != nil {
return "", errors.Join(errors.New("failed to decode session"), ErrDecoding, err)
}
return string(subject), nil
}
// ErrInvalidSubjectOrSession is returned when the provided key does not match the expected key format
var ErrInvalidSubjectOrSession = errors.New("invalid subject or session")
// NewSuSe parses the subject and session id from the given key and returns a SuSe struct
func NewSuSe(key string) (SuSe, error) {
suse := SuSe{}
keys := strings.Split(key, ".")
switch len(keys) {
case 1:
suse.encodedSession = keys[0]
case 2:
suse.encodedSubject = keys[0]
suse.encodedSession = keys[1]
default:
return suse, ErrInvalidSubjectOrSession
}
if suse.encodedSubject == "" && suse.encodedSession == "" {
return suse, ErrInvalidSubjectOrSession
}
if _, err := suse.Subject(); err != nil {
return suse, errors.Join(ErrInvalidSubjectOrSession, err)
}
if _, err := suse.Session(); err != nil {
return suse, errors.Join(ErrInvalidSubjectOrSession, err)
}
return suse, nil
}
// logoutMode defines the mode of backchannel logout, either by session or by subject
type logoutMode int
const (
// logoutModeUndefined is used when the logout mode cannot be determined
logoutModeUndefined logoutMode = iota
// logoutModeSubject is used when the logout mode is determined by the subject
logoutModeSubject
// logoutModeSession is used when the logout mode is determined by the session id
logoutModeSession
)
// getLogoutMode determines the backchannel logout mode based on the presence of subject and session in the SuSe struct
func getLogoutMode(suse SuSe) logoutMode {
switch {
case suse.encodedSession == "" && suse.encodedSubject != "":
return logoutModeSubject
case suse.encodedSession != "":
return logoutModeSession
default:
return logoutModeUndefined
}
}
// ErrSuspiciousCacheResult is returned when the cache result is suspicious
var ErrSuspiciousCacheResult = errors.New("suspicious cache result")
// GetLogoutRecords retrieves the records from the user info cache based on the backchannel
// logout mode and the provided SuSe struct.
// it uses a seperator to prevent sufix and prefix exploration in the cache and checks
// if the retrieved records match the requested subject and or session id as well, to prevent false positives.
func GetLogoutRecords(suse SuSe, store microstore.Store) ([]*microstore.Record, error) {
// get subject.session mode
mode := getLogoutMode(suse)
var key string
var opts []microstore.ReadOption
switch {
case mode == logoutModeSubject && suse.encodedSubject != "":
// the dot at the end prevents prefix exploration in the cache,
// so only keys that start with 'subject.*' will be returned, but not 'sub*'.
key = suse.encodedSubject + "."
opts = append(opts, microstore.ReadPrefix())
case mode == logoutModeSession && suse.encodedSession != "":
// the dot at the beginning prevents sufix exploration in the cache,
// so only keys that end with '*.session' will be returned, but not '*sion'.
key = "." + suse.encodedSession
opts = append(opts, microstore.ReadSuffix())
default:
return nil, errors.Join(errors.New("cannot determine logout mode"), ErrSuspiciousCacheResult)
}
// the go micro memory store requires a limit to work, why???
records, err := store.Read(key, append(opts, microstore.ReadLimit(1000))...)
if err != nil {
return nil, err
}
if len(records) == 0 {
return nil, microstore.ErrNotFound
}
if mode == logoutModeSession && len(records) > 1 {
return nil, errors.Join(errors.New("multiple session records found"), ErrSuspiciousCacheResult)
}
// double-check if the found records match the requested subject and or session id as well,
// to prevent false positives.
for _, record := range records {
recordSuSe, err := NewSuSe(record.Key)
if err != nil {
// never leak any key-related information
return nil, errors.Join(errors.New("failed to parse key"), ErrSuspiciousCacheResult, err)
}
switch {
// in subject mode, the subject must match, but the session id can be different
case mode == logoutModeSubject && suse.encodedSubject == recordSuSe.encodedSubject:
continue
// in session mode, the session id must match, but the subject can be different
case mode == logoutModeSession && suse.encodedSession == recordSuSe.encodedSession:
continue
}
return nil, errors.Join(errors.New("key does not match the requested subject or session"), ErrSuspiciousCacheResult)
}
return records, nil
}

View File

@@ -0,0 +1,331 @@
package backchannellogout
import (
"slices"
"strings"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go-micro.dev/v4/store"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/staticroutes/internal/backchannellogout/mocks"
)
func mustNewKey(t *testing.T, subject, session string) string {
key, err := NewKey(subject, session)
require.NoError(t, err)
return key
}
func mustNewSuSe(t *testing.T, subject, session string) SuSe {
suse, err := NewSuSe(mustNewKey(t, subject, session))
require.NoError(t, err)
return suse
}
func TestNewKey(t *testing.T) {
tests := []struct {
name string
subject string
session string
wantKey string
wantErr error
}{
{
name: "key variation: 'subject.session'",
subject: "subject",
session: "session",
wantKey: "c3ViamVjdA==.c2Vzc2lvbg==",
},
{
name: "key variation: 'subject.'",
subject: "subject",
wantKey: "c3ViamVjdA==.",
},
{
name: "key variation: '.session'",
session: "session",
wantKey: ".c2Vzc2lvbg==",
},
{
name: "key variation: '.'",
wantErr: ErrInvalidKey,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
key, err := NewKey(tt.subject, tt.session)
require.ErrorIs(t, err, tt.wantErr)
require.Equal(t, tt.wantKey, key)
})
}
}
func TestNewSuSe(t *testing.T) {
tests := []struct {
name string
key string
wantSubject string
wantSession string
wantErr error
}{
{
name: "key variation: '.session'",
key: mustNewKey(t, "", "session"),
wantSession: "session",
},
{
name: "key variation: 'session'",
key: mustNewKey(t, "", "session"),
wantSession: "session",
},
{
name: "key variation: 'subject.'",
key: mustNewKey(t, "subject", ""),
wantSubject: "subject",
},
{
name: "key variation: 'subject.session'",
key: mustNewKey(t, "subject", "session"),
wantSubject: "subject",
wantSession: "session",
},
{
name: "key variation: 'dot'",
key: ".",
wantErr: ErrInvalidSubjectOrSession,
},
{
name: "key variation: 'empty'",
key: "",
wantErr: ErrInvalidSubjectOrSession,
},
{
name: "key variation: string('subject.session')",
key: "subject.session",
wantErr: ErrInvalidSubjectOrSession,
},
{
name: "key variation: string('subject.')",
key: "subject.",
wantErr: ErrInvalidSubjectOrSession,
},
{
name: "key variation: string('.session')",
key: ".session",
wantErr: ErrInvalidSubjectOrSession,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
suSe, err := NewSuSe(tt.key)
require.ErrorIs(t, err, tt.wantErr)
subject, _ := suSe.Subject()
require.Equal(t, tt.wantSubject, subject)
session, _ := suSe.Session()
require.Equal(t, tt.wantSession, session)
})
}
}
func TestGetLogoutMode(t *testing.T) {
tests := []struct {
name string
suSe SuSe
want logoutMode
}{
{
name: "key variation: '.session'",
suSe: mustNewSuSe(t, "", "session"),
want: logoutModeSession,
},
{
name: "key variation: 'subject.session'",
suSe: mustNewSuSe(t, "subject", "session"),
want: logoutModeSession,
},
{
name: "key variation: 'subject.'",
suSe: mustNewSuSe(t, "subject", ""),
want: logoutModeSubject,
},
{
name: "key variation: 'empty'",
suSe: SuSe{},
want: logoutModeUndefined,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mode := getLogoutMode(tt.suSe)
require.Equal(t, tt.want, mode)
})
}
}
func TestGetLogoutRecords(t *testing.T) {
sessionStore := store.NewMemoryStore()
recordClaimA := &store.Record{Key: "claim-a", Value: []byte("claim-a-data")}
recordClaimB := &store.Record{Key: "claim-b", Value: []byte("claim-b-data")}
recordClaimC := &store.Record{Key: "claim-c", Value: []byte("claim-c-data")}
recordClaimD := &store.Record{Key: "claim-d", Value: []byte("claim-d-data")}
recordSessionA := &store.Record{Key: mustNewKey(t, "", "session-a"), Value: []byte(recordClaimA.Key)}
recordSessionB := &store.Record{Key: mustNewKey(t, "", "session-b"), Value: []byte(recordClaimB.Key)}
recordSubjectASessionC := &store.Record{Key: mustNewKey(t, "subject-a", "session-c"), Value: []byte(recordSessionA.Key)}
recordSubjectASessionD := &store.Record{Key: mustNewKey(t, "subject-a", "session-d"), Value: []byte(recordSessionA.Key)}
for _, r := range []*store.Record{
recordClaimA,
recordClaimB,
recordClaimC,
recordClaimD,
recordSessionA,
recordSessionB,
recordSubjectASessionC,
recordSubjectASessionD,
} {
require.NoError(t, sessionStore.Write(r))
}
tests := []struct {
name string
suSe SuSe
store func(t *testing.T) store.Store
wantRecords []*store.Record
wantErrs []error
}{
{
name: "fails if multiple session records are found",
suSe: mustNewSuSe(t, "", "session-a"),
store: func(t *testing.T) store.Store {
s := mocks.NewStore(t)
s.EXPECT().Read(mock.Anything, mock.Anything).Return([]*store.Record{
recordSessionA,
recordSessionB,
}, nil)
return s
},
wantRecords: []*store.Record{},
wantErrs: []error{ErrSuspiciousCacheResult}},
{
name: "fails if the record key is not ok",
suSe: mustNewSuSe(t, "", "session-a"),
store: func(t *testing.T) store.Store {
s := mocks.NewStore(t)
s.EXPECT().Read(mock.Anything, mock.Anything).Return([]*store.Record{
{Key: "invalid.record.key"},
}, nil)
return s
},
wantRecords: []*store.Record{},
wantErrs: []error{ErrInvalidSubjectOrSession, ErrSuspiciousCacheResult},
},
{
name: "fails if the session does not match the retrieved record",
suSe: mustNewSuSe(t, "", "session-a"),
store: func(t *testing.T) store.Store {
s := mocks.NewStore(t)
s.EXPECT().Read(mock.Anything, mock.Anything).Return([]*store.Record{
recordSessionB,
}, nil)
return s
},
wantRecords: []*store.Record{},
wantErrs: []error{ErrSuspiciousCacheResult}},
{
name: "fails if the subject does not match the retrieved record",
suSe: mustNewSuSe(t, "subject-a", ""),
store: func(t *testing.T) store.Store {
s := mocks.NewStore(t)
s.EXPECT().Read(mock.Anything, mock.Anything).Return([]*store.Record{
recordSessionB,
}, nil)
return s
},
wantRecords: []*store.Record{},
wantErrs: []error{ErrSuspiciousCacheResult}},
// key variation tests
{
name: "key variation: 'session-a'",
suSe: mustNewSuSe(t, "", "session-a"),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{recordSessionA},
},
{
name: "key variation: 'session-b'",
suSe: mustNewSuSe(t, "", "session-b"),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{recordSessionB},
},
{
name: "key variation: 'session-c'",
suSe: mustNewSuSe(t, "", "session-c"),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{recordSubjectASessionC},
},
{
name: "key variation: 'ession-c'",
suSe: mustNewSuSe(t, "", "ession-c"),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{},
wantErrs: []error{store.ErrNotFound},
},
{
name: "key variation: 'subject-a'",
suSe: mustNewSuSe(t, "subject-a", ""),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{recordSubjectASessionC, recordSubjectASessionD},
},
{
name: "key variation: 'subject-'",
suSe: mustNewSuSe(t, "subject-", ""),
store: func(*testing.T) store.Store {
return sessionStore
},
wantRecords: []*store.Record{},
wantErrs: []error{store.ErrNotFound},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
records, err := GetLogoutRecords(tt.suSe, tt.store(t))
for _, wantErr := range tt.wantErrs {
require.ErrorIs(t, err, wantErr)
}
require.Len(t, records, len(tt.wantRecords))
sortRecords := func(r []*store.Record) []*store.Record {
slices.SortFunc(r, func(a, b *store.Record) int {
return strings.Compare(a.Key, b.Key)
})
return r
}
records = sortRecords(records)
for i, wantRecords := range sortRecords(tt.wantRecords) {
require.True(t, len(records) >= i+1)
require.Equal(t, wantRecords.Key, records[i].Key)
require.Equal(t, wantRecords.Value, records[i].Value)
}
})
}
}

View File

@@ -0,0 +1,509 @@
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
mock "github.com/stretchr/testify/mock"
"go-micro.dev/v4/store"
)
// NewStore creates a new instance of Store. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewStore(t interface {
mock.TestingT
Cleanup(func())
}) *Store {
mock := &Store{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// Store is an autogenerated mock type for the Store type
type Store struct {
mock.Mock
}
type Store_Expecter struct {
mock *mock.Mock
}
func (_m *Store) EXPECT() *Store_Expecter {
return &Store_Expecter{mock: &_m.Mock}
}
// Close provides a mock function for the type Store
func (_mock *Store) Close() error {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for Close")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = returnFunc()
} else {
r0 = ret.Error(0)
}
return r0
}
// Store_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
type Store_Close_Call struct {
*mock.Call
}
// Close is a helper method to define mock.On call
func (_e *Store_Expecter) Close() *Store_Close_Call {
return &Store_Close_Call{Call: _e.mock.On("Close")}
}
func (_c *Store_Close_Call) Run(run func()) *Store_Close_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Store_Close_Call) Return(err error) *Store_Close_Call {
_c.Call.Return(err)
return _c
}
func (_c *Store_Close_Call) RunAndReturn(run func() error) *Store_Close_Call {
_c.Call.Return(run)
return _c
}
// Delete provides a mock function for the type Store
func (_mock *Store) Delete(key string, opts ...store.DeleteOption) error {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _mock.Called(key, opts)
} else {
tmpRet = _mock.Called(key)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for Delete")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string, ...store.DeleteOption) error); ok {
r0 = returnFunc(key, opts...)
} else {
r0 = ret.Error(0)
}
return r0
}
// Store_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
type Store_Delete_Call struct {
*mock.Call
}
// Delete is a helper method to define mock.On call
// - key string
// - opts ...store.DeleteOption
func (_e *Store_Expecter) Delete(key interface{}, opts ...interface{}) *Store_Delete_Call {
return &Store_Delete_Call{Call: _e.mock.On("Delete",
append([]interface{}{key}, opts...)...)}
}
func (_c *Store_Delete_Call) Run(run func(key string, opts ...store.DeleteOption)) *Store_Delete_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 []store.DeleteOption
var variadicArgs []store.DeleteOption
if len(args) > 1 {
variadicArgs = args[1].([]store.DeleteOption)
}
arg1 = variadicArgs
run(
arg0,
arg1...,
)
})
return _c
}
func (_c *Store_Delete_Call) Return(err error) *Store_Delete_Call {
_c.Call.Return(err)
return _c
}
func (_c *Store_Delete_Call) RunAndReturn(run func(key string, opts ...store.DeleteOption) error) *Store_Delete_Call {
_c.Call.Return(run)
return _c
}
// Init provides a mock function for the type Store
func (_mock *Store) Init(options ...store.Option) error {
var tmpRet mock.Arguments
if len(options) > 0 {
tmpRet = _mock.Called(options)
} else {
tmpRet = _mock.Called()
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for Init")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(...store.Option) error); ok {
r0 = returnFunc(options...)
} else {
r0 = ret.Error(0)
}
return r0
}
// Store_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init'
type Store_Init_Call struct {
*mock.Call
}
// Init is a helper method to define mock.On call
// - options ...store.Option
func (_e *Store_Expecter) Init(options ...interface{}) *Store_Init_Call {
return &Store_Init_Call{Call: _e.mock.On("Init",
append([]interface{}{}, options...)...)}
}
func (_c *Store_Init_Call) Run(run func(options ...store.Option)) *Store_Init_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 []store.Option
var variadicArgs []store.Option
if len(args) > 0 {
variadicArgs = args[0].([]store.Option)
}
arg0 = variadicArgs
run(
arg0...,
)
})
return _c
}
func (_c *Store_Init_Call) Return(err error) *Store_Init_Call {
_c.Call.Return(err)
return _c
}
func (_c *Store_Init_Call) RunAndReturn(run func(options ...store.Option) error) *Store_Init_Call {
_c.Call.Return(run)
return _c
}
// List provides a mock function for the type Store
func (_mock *Store) List(opts ...store.ListOption) ([]string, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _mock.Called(opts)
} else {
tmpRet = _mock.Called()
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for List")
}
var r0 []string
var r1 error
if returnFunc, ok := ret.Get(0).(func(...store.ListOption) ([]string, error)); ok {
return returnFunc(opts...)
}
if returnFunc, ok := ret.Get(0).(func(...store.ListOption) []string); ok {
r0 = returnFunc(opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if returnFunc, ok := ret.Get(1).(func(...store.ListOption) error); ok {
r1 = returnFunc(opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Store_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List'
type Store_List_Call struct {
*mock.Call
}
// List is a helper method to define mock.On call
// - opts ...store.ListOption
func (_e *Store_Expecter) List(opts ...interface{}) *Store_List_Call {
return &Store_List_Call{Call: _e.mock.On("List",
append([]interface{}{}, opts...)...)}
}
func (_c *Store_List_Call) Run(run func(opts ...store.ListOption)) *Store_List_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 []store.ListOption
var variadicArgs []store.ListOption
if len(args) > 0 {
variadicArgs = args[0].([]store.ListOption)
}
arg0 = variadicArgs
run(
arg0...,
)
})
return _c
}
func (_c *Store_List_Call) Return(strings []string, err error) *Store_List_Call {
_c.Call.Return(strings, err)
return _c
}
func (_c *Store_List_Call) RunAndReturn(run func(opts ...store.ListOption) ([]string, error)) *Store_List_Call {
_c.Call.Return(run)
return _c
}
// Options provides a mock function for the type Store
func (_mock *Store) Options() store.Options {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for Options")
}
var r0 store.Options
if returnFunc, ok := ret.Get(0).(func() store.Options); ok {
r0 = returnFunc()
} else {
r0 = ret.Get(0).(store.Options)
}
return r0
}
// Store_Options_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Options'
type Store_Options_Call struct {
*mock.Call
}
// Options is a helper method to define mock.On call
func (_e *Store_Expecter) Options() *Store_Options_Call {
return &Store_Options_Call{Call: _e.mock.On("Options")}
}
func (_c *Store_Options_Call) Run(run func()) *Store_Options_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Store_Options_Call) Return(options store.Options) *Store_Options_Call {
_c.Call.Return(options)
return _c
}
func (_c *Store_Options_Call) RunAndReturn(run func() store.Options) *Store_Options_Call {
_c.Call.Return(run)
return _c
}
// Read provides a mock function for the type Store
func (_mock *Store) Read(key string, opts ...store.ReadOption) ([]*store.Record, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _mock.Called(key, opts)
} else {
tmpRet = _mock.Called(key)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for Read")
}
var r0 []*store.Record
var r1 error
if returnFunc, ok := ret.Get(0).(func(string, ...store.ReadOption) ([]*store.Record, error)); ok {
return returnFunc(key, opts...)
}
if returnFunc, ok := ret.Get(0).(func(string, ...store.ReadOption) []*store.Record); ok {
r0 = returnFunc(key, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*store.Record)
}
}
if returnFunc, ok := ret.Get(1).(func(string, ...store.ReadOption) error); ok {
r1 = returnFunc(key, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Store_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read'
type Store_Read_Call struct {
*mock.Call
}
// Read is a helper method to define mock.On call
// - key string
// - opts ...store.ReadOption
func (_e *Store_Expecter) Read(key interface{}, opts ...interface{}) *Store_Read_Call {
return &Store_Read_Call{Call: _e.mock.On("Read",
append([]interface{}{key}, opts...)...)}
}
func (_c *Store_Read_Call) Run(run func(key string, opts ...store.ReadOption)) *Store_Read_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 []store.ReadOption
var variadicArgs []store.ReadOption
if len(args) > 1 {
variadicArgs = args[1].([]store.ReadOption)
}
arg1 = variadicArgs
run(
arg0,
arg1...,
)
})
return _c
}
func (_c *Store_Read_Call) Return(records []*store.Record, err error) *Store_Read_Call {
_c.Call.Return(records, err)
return _c
}
func (_c *Store_Read_Call) RunAndReturn(run func(key string, opts ...store.ReadOption) ([]*store.Record, error)) *Store_Read_Call {
_c.Call.Return(run)
return _c
}
// String provides a mock function for the type Store
func (_mock *Store) String() string {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for String")
}
var r0 string
if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = returnFunc()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// Store_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String'
type Store_String_Call struct {
*mock.Call
}
// String is a helper method to define mock.On call
func (_e *Store_Expecter) String() *Store_String_Call {
return &Store_String_Call{Call: _e.mock.On("String")}
}
func (_c *Store_String_Call) Run(run func()) *Store_String_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Store_String_Call) Return(s string) *Store_String_Call {
_c.Call.Return(s)
return _c
}
func (_c *Store_String_Call) RunAndReturn(run func() string) *Store_String_Call {
_c.Call.Return(run)
return _c
}
// Write provides a mock function for the type Store
func (_mock *Store) Write(r *store.Record, opts ...store.WriteOption) error {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _mock.Called(r, opts)
} else {
tmpRet = _mock.Called(r)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for Write")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(*store.Record, ...store.WriteOption) error); ok {
r0 = returnFunc(r, opts...)
} else {
r0 = ret.Error(0)
}
return r0
}
// Store_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
type Store_Write_Call struct {
*mock.Call
}
// Write is a helper method to define mock.On call
// - r *store.Record
// - opts ...store.WriteOption
func (_e *Store_Expecter) Write(r interface{}, opts ...interface{}) *Store_Write_Call {
return &Store_Write_Call{Call: _e.mock.On("Write",
append([]interface{}{r}, opts...)...)}
}
func (_c *Store_Write_Call) Run(run func(r *store.Record, opts ...store.WriteOption)) *Store_Write_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 *store.Record
if args[0] != nil {
arg0 = args[0].(*store.Record)
}
var arg1 []store.WriteOption
var variadicArgs []store.WriteOption
if len(args) > 1 {
variadicArgs = args[1].([]store.WriteOption)
}
arg1 = variadicArgs
run(
arg0,
arg1...,
)
})
return _c
}
func (_c *Store_Write_Call) Return(err error) *Store_Write_Call {
_c.Call.Return(err)
return _c
}
func (_c *Store_Write_Call) RunAndReturn(run func(r *store.Record, opts ...store.WriteOption) error) *Store_Write_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jörn Friedrich Dreyer <jfd@butonic.de>, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Alejandro Robles, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-23 00:11+0000\n"
"POT-Creation-Date: 2026-02-12 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: idoet <idoet@protonmail.ch>, 2025\n"
"Language-Team: Indonesian (https://app.transifex.com/opencloud-eu/teams/204053/id/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Pagano, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
# iikaka88, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-14 00:09+0000\n"
"POT-Creation-Date: 2026-02-24 00:11+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Last-Translator: iikaka88, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: gapho shin, 2025\n"
"Language-Team: Korean (https://app.transifex.com/opencloud-eu/teams/204053/ko/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-12 00:08+0000\n"
"POT-Creation-Date: 2026-02-22 00:12+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/opencloud-eu/teams/204053/nl/)\n"

View File

@@ -13,7 +13,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Radoslaw Posim, 2025\n"
"Language-Team: Polish (https://app.transifex.com/opencloud-eu/teams/204053/pl/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-22 00:11+0000\n"
"POT-Creation-Date: 2026-02-11 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Mário Machado, 2025\n"
"Language-Team: Portuguese (https://app.transifex.com/opencloud-eu/teams/204053/pt/)\n"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Lulufox, 2025\n"
"Language-Team: Russian (https://app.transifex.com/opencloud-eu/teams/204053/ru/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Davis Kaza, 2025\n"
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-25 00:11+0000\n"
"POT-Creation-Date: 2026-02-14 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: LinkinWires <darkinsonic13@gmail.com>, 2025\n"
"Language-Team: Ukrainian (https://app.transifex.com/opencloud-eu/teams/204053/uk/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: YQS Yang, 2025\n"
"Language-Team: Chinese (https://app.transifex.com/opencloud-eu/teams/204053/zh/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jörn Friedrich Dreyer <jfd@butonic.de>, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Elías Martín, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-25 00:11+0000\n"
"POT-Creation-Date: 2026-02-14 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-09 00:08+0000\n"
"POT-Creation-Date: 2026-02-18 00:15+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Broglia, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
# iikaka88, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2026-01-14 00:09+0000\n"
"POT-Creation-Date: 2026-02-24 00:11+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Last-Translator: iikaka88, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

Some files were not shown because too many files have changed in this diff Show More