mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-24 14:50:39 -05:00
Compare commits
2 Commits
4.0.0-rc.2
...
readtimeou
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2883a6245d | ||
|
|
936a84096e |
@@ -16,7 +16,7 @@ exclude_paths:
|
||||
- 'tests/acceptance/expected-failures-*.md'
|
||||
- 'tests/acceptance/bootstrap/**'
|
||||
- 'tests/acceptance/TestHelpers/**'
|
||||
- 'tests/acceptance/scripts/run.sh'
|
||||
- 'tests/acceptance/run.sh'
|
||||
- 'vendor/**/*'
|
||||
- 'tests/ocwrapper/vendor/**'
|
||||
...
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,7 +38,6 @@ vendor-php
|
||||
# API acceptance tests - auto-generated files
|
||||
.php-cs-fixer.cache
|
||||
suite-logs
|
||||
tests/acceptance/filesForUpload/filesWithVirus/
|
||||
|
||||
# QA activity reports
|
||||
tests/qa-activity-report/reports/
|
||||
|
||||
29
.vscode/launch.json
vendored
29
.vscode/launch.json
vendored
@@ -53,7 +53,7 @@
|
||||
"OC_MACHINE_AUTH_API_KEY": "some-opencloud-machine-auth-api-key",
|
||||
"OC_TRANSFER_SECRET": "some-opencloud-transfer-secret",
|
||||
// collaboration
|
||||
"COLLABORATION_WOPI_SECRET": "some-wopi-secret",
|
||||
"COLLABORATION_WOPIAPP_SECRET": "some-wopi-secret",
|
||||
// idm ldap
|
||||
"IDM_SVC_PASSWORD": "some-ldap-idm-password",
|
||||
"GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password",
|
||||
@@ -193,21 +193,20 @@
|
||||
"OC_LOG_COLOR": "true",
|
||||
"PROXY_ENABLE_BASIC_AUTH": "true",
|
||||
"IDM_CREATE_DEMO_USERS": "true",
|
||||
"OC_ADMIN_USER_ID": "fed-admin-user-id-0000-000000000000",
|
||||
"OC_ADMIN_USER_ID": "some-admin-user-id-0000-000000000000",
|
||||
"IDM_ADMIN_PASSWORD": "admin",
|
||||
"OC_SYSTEM_USER_ID": "fed-system-user-id-000-000000000000",
|
||||
"OC_SYSTEM_USER_API_KEY": "fed-system-user-machine-auth-api-key",
|
||||
"OC_JWT_SECRET": "fed-opencloud-jwt-secret",
|
||||
"OC_MACHINE_AUTH_API_KEY": "fed-opencloud-machine-auth-api-key",
|
||||
"OC_TRANSFER_SECRET": "fed-opencloud-transfer-secret",
|
||||
"COLLABORATION_WOPI_SECRET": "fed-wopi-secret",
|
||||
"IDM_SVC_PASSWORD": "fed-ldap-idm-password",
|
||||
"GRAPH_LDAP_BIND_PASSWORD": "fed-ldap-idm-password",
|
||||
"IDM_REVASVC_PASSWORD": "fed-ldap-reva-password",
|
||||
"GROUPS_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
|
||||
"USERS_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
|
||||
"AUTH_BASIC_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
|
||||
"IDM_IDPSVC_PASSWORD": "fed-ldap-idp-password",
|
||||
"OC_SYSTEM_USER_ID": "some-system-user-id-000-000000000000",
|
||||
"OC_SYSTEM_USER_API_KEY": "some-system-user-machine-auth-api-key",
|
||||
"OC_JWT_SECRET": "some-opencloud-jwt-secret",
|
||||
"OC_MACHINE_AUTH_API_KEY": "some-opencloud-machine-auth-api-key",
|
||||
"OC_TRANSFER_SECRET": "some-opencloud-transfer-secret",
|
||||
"IDM_SVC_PASSWORD": "some-ldap-idm-password",
|
||||
"GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password",
|
||||
"IDM_REVASVC_PASSWORD": "some-ldap-reva-password",
|
||||
"GROUPS_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
|
||||
"USERS_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
|
||||
"AUTH_BASIC_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
|
||||
"IDM_IDPSVC_PASSWORD": "some-ldap-idp-password",
|
||||
"IDP_LDAP_BIND_PASSWORD": "some-ldap-idp-password",
|
||||
"GRAPH_APPLICATION_ID": "application-1"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# The test runner source for UI tests
|
||||
WEB_COMMITID=3d7367cfb1abe288d0fc0b0b1cc494a7747bcaf6
|
||||
WEB_BRANCH=stable-4.2
|
||||
WEB_COMMITID=6abffcc9cff31c46a341105eb6030fec56338126
|
||||
WEB_BRANCH=main
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ docker_repo_slug = "opencloudeu/opencloud"
|
||||
|
||||
# images
|
||||
ALPINE_GIT = "alpine/git:latest"
|
||||
APACHE_TIKA = "apache/tika:3.2.3.0-full"
|
||||
APACHE_TIKA = "apache/tika:2.8.0.0"
|
||||
CHKO_DOCKER_PUSHRM = "chko/docker-pushrm:1"
|
||||
COLLABORA_CODE = "collabora/code:24.04.5.1.1"
|
||||
OPEN_SEARCH = "opensearchproject/opensearch:2"
|
||||
@@ -233,7 +233,6 @@ config = {
|
||||
],
|
||||
"skip": False,
|
||||
"antivirusNeeded": True,
|
||||
"generateVirusFiles": True,
|
||||
"extraServerEnvironment": {
|
||||
"ANTIVIRUS_SCANNER_TYPE": "clamav",
|
||||
"ANTIVIRUS_CLAMAV_SOCKET": "tcp://clamav:3310",
|
||||
@@ -300,7 +299,6 @@ config = {
|
||||
"skip": False,
|
||||
"withRemotePhp": [True],
|
||||
"antivirusNeeded": True,
|
||||
"generateVirusFiles": True,
|
||||
"extraServerEnvironment": {
|
||||
"ANTIVIRUS_SCANNER_TYPE": "clamav",
|
||||
"ANTIVIRUS_CLAMAV_SOCKET": "tcp://clamav:3310",
|
||||
@@ -608,7 +606,7 @@ def testPipelines(ctx):
|
||||
pipelines += apiTests(ctx)
|
||||
|
||||
enable_watch_fs = [False]
|
||||
if ctx.build.event == "cron":
|
||||
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
|
||||
enable_watch_fs.append(True)
|
||||
|
||||
for run_with_watch_fs_enabled in enable_watch_fs:
|
||||
@@ -994,7 +992,7 @@ def localApiTestPipeline(ctx):
|
||||
|
||||
with_remote_php = [True]
|
||||
enable_watch_fs = [False]
|
||||
if ctx.build.event == "cron":
|
||||
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
|
||||
with_remote_php.append(False)
|
||||
enable_watch_fs.append(True)
|
||||
|
||||
@@ -1018,7 +1016,6 @@ def localApiTestPipeline(ctx):
|
||||
"withRemotePhp": with_remote_php,
|
||||
"enableWatchFs": enable_watch_fs,
|
||||
"ldapNeeded": False,
|
||||
"generateVirusFiles": False,
|
||||
}
|
||||
|
||||
if "localApiTests" in config:
|
||||
@@ -1043,7 +1040,7 @@ def localApiTestPipeline(ctx):
|
||||
(opencloudServer(storage, params["accounts_hash_difficulty"], deploy_type = "federation", extra_server_environment = params["extraServerEnvironment"], watch_fs_enabled = run_with_watch_fs_enabled) if params["federationServer"] else []) +
|
||||
((wopiCollaborationService("fakeoffice") + wopiCollaborationService("collabora") + wopiCollaborationService("onlyoffice")) if params["collaborationServiceNeeded"] else []) +
|
||||
(openCloudHealthCheck("wopi", ["wopi-collabora:9304", "wopi-onlyoffice:9304", "wopi-fakeoffice:9304"]) if params["collaborationServiceNeeded"] else []) +
|
||||
localApiTests(name, params["suites"], storage, params["extraTestEnvironment"], run_with_remote_php, params["generateVirusFiles"]) +
|
||||
localApiTests(name, params["suites"], storage, params["extraTestEnvironment"], run_with_remote_php) +
|
||||
logRequests(),
|
||||
"services": (emailService() if params["emailNeeded"] else []) +
|
||||
(clamavService() if params["antivirusNeeded"] else []) +
|
||||
@@ -1063,7 +1060,7 @@ def localApiTestPipeline(ctx):
|
||||
pipelines.append(pipeline)
|
||||
return pipelines
|
||||
|
||||
def localApiTests(name, suites, storage = "decomposed", extra_environment = {}, with_remote_php = False, generate_virus_files = False):
|
||||
def localApiTests(name, suites, storage = "decomposed", extra_environment = {}, with_remote_php = False):
|
||||
test_dir = "%s/tests/acceptance" % dirs["base"]
|
||||
expected_failures_file = "%s/expected-failures-localAPI-on-%s-storage.md" % (test_dir, storage)
|
||||
|
||||
@@ -1086,25 +1083,15 @@ def localApiTests(name, suites, storage = "decomposed", extra_environment = {},
|
||||
for item in extra_environment:
|
||||
environment[item] = extra_environment[item]
|
||||
|
||||
commands = []
|
||||
|
||||
# Generate EICAR virus test files if needed
|
||||
if generate_virus_files:
|
||||
commands.append("chmod +x %s/tests/acceptance/scripts/generate-virus-files.sh" % dirs["base"])
|
||||
commands.append("bash %s/tests/acceptance/scripts/generate-virus-files.sh" % dirs["base"])
|
||||
|
||||
# Merge expected failures
|
||||
if not with_remote_php:
|
||||
commands.append("cat %s/expected-failures-without-remotephp.md >> %s" % (test_dir, expected_failures_file))
|
||||
|
||||
# Run tests
|
||||
commands.append("make -C %s test-acceptance-api" % (dirs["base"]))
|
||||
|
||||
return [{
|
||||
"name": "localApiTests-%s" % name,
|
||||
"image": OC_CI_PHP % DEFAULT_PHP_VERSION,
|
||||
"environment": environment,
|
||||
"commands": commands,
|
||||
"commands": [
|
||||
# merge the expected failures
|
||||
"" if with_remote_php else "cat %s/expected-failures-without-remotephp.md >> %s" % (test_dir, expected_failures_file),
|
||||
"make -C %s test-acceptance-api" % (dirs["base"]),
|
||||
],
|
||||
}]
|
||||
|
||||
def cs3ApiTests(ctx, storage, accounts_hash_difficulty = 4):
|
||||
@@ -1310,7 +1297,7 @@ def apiTests(ctx):
|
||||
|
||||
with_remote_php = [True]
|
||||
enable_watch_fs = [False]
|
||||
if ctx.build.event == "cron":
|
||||
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
|
||||
with_remote_php.append(False)
|
||||
enable_watch_fs.append(True)
|
||||
|
||||
@@ -1654,16 +1641,6 @@ def dockerRelease(ctx, repo, build_type):
|
||||
"VERSION": "%s" % (ctx.build.ref.replace("refs/tags/", "") if ctx.build.event == "tag" else "daily"),
|
||||
}
|
||||
|
||||
# if no additional tag is given, the build-plugin adds latest
|
||||
hard_tag = "daily"
|
||||
if ctx.build.event == "tag":
|
||||
tag_version = ctx.build.ref.replace("refs/tags/", "")
|
||||
tag_parts = tag_version.split("-")
|
||||
|
||||
# if a tag has something appended with "-" i.e. alpha, beta, rc1...
|
||||
# set the entire string as tag, else leave empty to autotag with latest
|
||||
hard_tag = tag_version if len(tag_parts) > 1 else ""
|
||||
|
||||
depends_on = getPipelineNames(getGoBinForTesting(ctx))
|
||||
|
||||
if ctx.build.event == "tag":
|
||||
@@ -1677,12 +1654,11 @@ def dockerRelease(ctx, repo, build_type):
|
||||
"name": "dryrun",
|
||||
"image": PLUGINS_DOCKER_BUILDX,
|
||||
"settings": {
|
||||
"context": "..",
|
||||
"dry_run": True,
|
||||
"platforms": "linux/amd64", # do dry run only on the native platform
|
||||
"repo": "%s,quay.io/%s" % (repo, repo),
|
||||
"auto_tag": False if build_type == "daily" else True,
|
||||
"tag": hard_tag,
|
||||
"tag": "daily" if build_type == "daily" else "",
|
||||
"default_tag": "daily",
|
||||
"dockerfile": "opencloud/docker/Dockerfile.multiarch",
|
||||
"build_args": build_args,
|
||||
@@ -1700,7 +1676,6 @@ def dockerRelease(ctx, repo, build_type):
|
||||
"name": "build-and-push",
|
||||
"image": PLUGINS_DOCKER_BUILDX,
|
||||
"settings": {
|
||||
"context": "..",
|
||||
"repo": "%s,quay.io/%s" % (repo, repo),
|
||||
"platforms": "linux/amd64,linux/arm64", # we can add remote builders
|
||||
"auto_tag": False if build_type == "daily" else True,
|
||||
|
||||
2
Makefile
2
Makefile
@@ -124,7 +124,7 @@ BEHAT_BIN=vendor-bin/behat/vendor/bin/behat
|
||||
|
||||
.PHONY: test-acceptance-api
|
||||
test-acceptance-api: vendor-bin/behat/vendor
|
||||
BEHAT_BIN=$(BEHAT_BIN) tests/acceptance/scripts/run.sh
|
||||
BEHAT_BIN=$(BEHAT_BIN) tests/acceptance/run.sh
|
||||
|
||||
vendor/bamarni/composer-bin-plugin: composer.lock
|
||||
composer install
|
||||
|
||||
84
go.mod
84
go.mod
@@ -5,20 +5,20 @@ go 1.24.6
|
||||
require (
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/CiscoM31/godata v1.0.11
|
||||
github.com/KimMachineGun/automemlimit v0.7.5
|
||||
github.com/KimMachineGun/automemlimit v0.7.4
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/MicahParks/keyfunc/v2 v2.1.0
|
||||
github.com/Nerzal/gocloak/v13 v13.9.0
|
||||
github.com/bbalet/stopwords v1.0.0
|
||||
github.com/beevik/etree v1.6.0
|
||||
github.com/blevesearch/bleve/v2 v2.5.5
|
||||
github.com/blevesearch/bleve/v2 v2.5.4
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.17.0
|
||||
github.com/coreos/go-oidc/v3 v3.16.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20250908152307-4ca807afe54e
|
||||
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.11
|
||||
github.com/gabriel-vasile/mimetype v1.4.10
|
||||
github.com/ggwhite/go-masker v1.1.0
|
||||
github.com/go-chi/chi/v5 v5.2.3
|
||||
github.com/go-chi/render v1.0.3
|
||||
@@ -34,6 +34,7 @@ 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.28.0
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/google/go-cmp v0.7.0
|
||||
@@ -54,17 +55,17 @@ require (
|
||||
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.1
|
||||
github.com/nats-io/nats-server/v2 v2.12.0
|
||||
github.com/nats-io/nats.go v1.47.0
|
||||
github.com/oklog/run v1.2.0
|
||||
github.com/olekukonko/tablewriter v1.1.1
|
||||
github.com/olekukonko/tablewriter v1.1.0
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.27.2
|
||||
github.com/onsi/gomega v1.38.2
|
||||
github.com/open-policy-agent/opa v1.10.1
|
||||
github.com/open-policy-agent/opa v1.9.0
|
||||
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.39.3
|
||||
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6
|
||||
github.com/opensearch-project/opensearch-go/v4 v4.5.0
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -101,19 +102,18 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0
|
||||
go.opentelemetry.io/otel/sdk v1.38.0
|
||||
go.opentelemetry.io/otel/trace v1.38.0
|
||||
golang.org/x/crypto v0.44.0
|
||||
golang.org/x/crypto v0.43.0
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
|
||||
golang.org/x/image v0.32.0
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/oauth2 v0.33.0
|
||||
golang.org/x/sync v0.18.0
|
||||
golang.org/x/term v0.37.0
|
||||
golang.org/x/text v0.31.0
|
||||
golang.org/x/oauth2 v0.32.0
|
||||
golang.org/x/sync v0.17.0
|
||||
golang.org/x/term v0.36.0
|
||||
golang.org/x/text v0.30.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4
|
||||
google.golang.org/grpc v1.76.0
|
||||
google.golang.org/protobuf v1.36.10
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.2
|
||||
stash.kopano.io/kgol/rndm v1.1.2
|
||||
)
|
||||
@@ -140,13 +140,13 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.2.11 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.2.10 // indirect
|
||||
github.com/blevesearch/geo v0.2.4 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.26 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.12 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
@@ -156,24 +156,21 @@ require (
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.7 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.6 // indirect
|
||||
github.com/bluele/gcache v0.0.2 // indirect
|
||||
github.com/bombsimon/logrusr/v3 v3.1.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/ceph/go-ceph v0.36.0 // indirect
|
||||
github.com/ceph/go-ceph v0.35.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.3.1 // indirect
|
||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v1.0.0-rc.1 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cornelk/hashmap v1.0.8 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
@@ -233,16 +230,15 @@ require (
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gomodule/redigo v1.9.3 // indirect
|
||||
github.com/gomodule/redigo v1.9.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.6 // indirect
|
||||
github.com/google/go-tpm v0.9.5 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/renameio/v2 v2.0.1 // indirect
|
||||
github.com/google/renameio/v2 v2.0.0 // indirect
|
||||
github.com/gookit/goutil v0.7.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/schema v1.4.1 // indirect
|
||||
@@ -261,7 +257,6 @@ require (
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
|
||||
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||
github.com/kovidgoyal/go-parallel v1.0.1 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
|
||||
@@ -280,16 +275,16 @@ require (
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.32 // 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/mileusna/useragent v1.3.5 // indirect
|
||||
github.com/minio/crc64nvme v1.1.0 // indirect
|
||||
github.com/minio/crc64nvme v1.0.2 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.97 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.95 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
@@ -308,9 +303,8 @@ require (
|
||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.1.2 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
@@ -324,19 +318,17 @@ 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.29.0 // indirect
|
||||
github.com/prometheus/alertmanager v0.28.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.66.1 // 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
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/russellhaering/goxmldsig v1.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // 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/segmentio/asm v1.2.0 // indirect
|
||||
github.com/segmentio/kafka-go v0.4.49 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
@@ -375,23 +367,24 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.5 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.5 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // 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/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/time v0.13.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
@@ -406,6 +399,3 @@ replace go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.202411151126
|
||||
exclude github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
|
||||
replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a
|
||||
|
||||
// to get the logger injection (https://github.com/pablodz/inotifywaitgo/pull/11)
|
||||
replace github.com/pablodz/inotifywaitgo v0.0.9 => github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9
|
||||
|
||||
162
go.sum
162
go.sum
@@ -72,8 +72,8 @@ github.com/CiscoM31/godata v1.0.11 h1:w7y8twuW02LdH6mak3/GJ5i0GrCv2IoZUJVqa/g5Ye
|
||||
github.com/CiscoM31/godata v1.0.11/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
|
||||
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c h1:ocsNvQ2tNHme4v/lTs17HROamc7mFzZfzWcg4m+UXN0=
|
||||
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
github.com/KimMachineGun/automemlimit v0.7.5 h1:RkbaC0MwhjL1ZuBKunGDjE/ggwAX43DwZrJqVwyveTk=
|
||||
github.com/KimMachineGun/automemlimit v0.7.5/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||
github.com/KimMachineGun/automemlimit v0.7.4 h1:UY7QYOIfrr3wjjOAqahFmC3IaQCLWvur9nmfIn6LnWk=
|
||||
github.com/KimMachineGun/automemlimit v0.7.4/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
@@ -151,22 +151,22 @@ github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6
|
||||
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
|
||||
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/blevesearch/bleve/v2 v2.5.5 h1:lzC89QUCco+y1qBnJxGqm4AbtsdsnlUvq0kXok8n3C8=
|
||||
github.com/blevesearch/bleve/v2 v2.5.5/go.mod h1:t5WoESS5TDteTdnjhhvpA1BpLYErOBX2IQViTMLK7wo=
|
||||
github.com/blevesearch/bleve_index_api v1.2.11 h1:bXQ54kVuwP8hdrXUSOnvTQfgK0KI1+f9A0ITJT8tX1s=
|
||||
github.com/blevesearch/bleve_index_api v1.2.11/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/bleve/v2 v2.5.4 h1:1iur8e+PHsxtncV2xIVuqlQme/V8guEDO2uV6Wll3lQ=
|
||||
github.com/blevesearch/bleve/v2 v2.5.4/go.mod h1:yB4PnV4N2q5rTEpB2ndG8N2ISexBQEFIYgwx4ztfvoo=
|
||||
github.com/blevesearch/bleve_index_api v1.2.10 h1:FMFmZCmTX6PdoLLvwUnKF2RsmILFFwO3h0WPevXY9fE=
|
||||
github.com/blevesearch/bleve_index_api v1.2.10/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||
github.com/blevesearch/go-faiss v1.0.26 h1:4dRLolFgjPyjkaXwff4NfbZFdE/dfywbzDqporeQvXI=
|
||||
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
||||
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.12 h1:GGZc2qwbyRBwtckPPkHkLyXw64mmsLJxdturBI1cM+c=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.12/go.mod h1:JBRGAneqgLSI2+jCNjtwMqp2B7EBF3/VUzgDPIU33MM=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||
@@ -185,8 +185,8 @@ github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT
|
||||
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||
github.com/blevesearch/zapx/v16 v16.2.7 h1:xcgFRa7f/tQXOwApVq7JWgPYSlzyUMmkuYa54tMDuR0=
|
||||
github.com/blevesearch/zapx/v16 v16.2.7/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
|
||||
github.com/blevesearch/zapx/v16 v16.2.6 h1:OHuUl2GhM+FpBq9RwNsJ4k/QodqbMMHoQEgn/IHYpu8=
|
||||
github.com/blevesearch/zapx/v16 v16.2.6/go.mod h1:cuAPB+YoIyRngNhno1S1GPr9SfMk+x/SgAHBLXSIq3k=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
@@ -198,8 +198,8 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/
|
||||
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
|
||||
github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3 h1:h8Z0hBv5tg/uZMKu8V47+DKWYVQg0lYP8lXDQq7uRpE=
|
||||
github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3/go.mod h1:eE/tD53n3KbVrzrWxKLxdkGw45Fg1qaNLWjpJMvIUF4=
|
||||
github.com/bytecodealliance/wasmtime-go/v37 v37.0.0 h1:DPjdn2V3JhXHMoZ2ymRqGK+y1bDyr9wgpyYCvhjMky8=
|
||||
github.com/bytecodealliance/wasmtime-go/v37 v37.0.0/go.mod h1:Pf1l2JCTUFMnOqDIwkjzx1qfVJ09xbaXETKgRVE4jZ0=
|
||||
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
|
||||
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
|
||||
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
@@ -210,8 +210,8 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/ceph/go-ceph v0.36.0 h1:IDE4vEF+4fmjve+CPjD1WStgfQ+Lh6vD+9PMUI712KI=
|
||||
github.com/ceph/go-ceph v0.36.0/go.mod h1:fGCbndVDLuHW7q2954d6y+tgPFOBnRLqJRe2YXyngw4=
|
||||
github.com/ceph/go-ceph v0.35.0 h1:wcDUbsjeNJ7OfbWCE7I5prqUL794uXchopw3IvrGQkk=
|
||||
github.com/ceph/go-ceph v0.35.0/go.mod h1:ILF8WKhQQ2p2YuX1oWigkmsfT39U8T/HS2NrqxExq2s=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -223,12 +223,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/clipperhouse/displaywidth v0.3.1 h1:k07iN9gD32177o1y4O1jQMzbLdCrsGJh+blirVYybsk=
|
||||
github.com/clipperhouse/displaywidth v0.3.1/go.mod h1:tgLJKKyaDOCadywag3agw4snxS5kYEuYR6Y9+qWDDYM=
|
||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
||||
@@ -243,15 +237,14 @@ github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsW
|
||||
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
|
||||
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
||||
github.com/coreos/go-oidc/v3 v3.16.0 h1:qRQUCFstKpXwmEjDQTIbyY/5jF00+asXzSkmkoa/mow=
|
||||
github.com/coreos/go-oidc/v3 v3.16.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc=
|
||||
github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k=
|
||||
@@ -356,8 +349,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
||||
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.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
|
||||
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.10/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=
|
||||
@@ -543,8 +536,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/gomodule/redigo v1.9.3 h1:dNPSXeXv6HCq2jdyWfjgmhBdqnR6PRO3m/G05nvpPC8=
|
||||
github.com/gomodule/redigo v1.9.3/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
|
||||
github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s=
|
||||
github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
||||
@@ -572,8 +565,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.6 h1:Ku42PT4LmjDu1H5C5ISWLlpI1mj+Zq7sPGKoRw2XROA=
|
||||
github.com/google/go-tpm v0.9.6/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||
github.com/google/go-tpm v0.9.5/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 +580,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
||||
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/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=
|
||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -730,8 +723,6 @@ github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYW
|
||||
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=
|
||||
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
|
||||
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
|
||||
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 h1:A1xJ2NKgiYFiaHiLl9B5yw/gUBACSs9crDykTS3GuQI=
|
||||
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
@@ -827,8 +818,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
|
||||
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
@@ -846,14 +837,14 @@ 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/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.0 h1:e/tAguZ+4cw32D+IO/8GSf5UVr9y+3eJcxZI2WOO/7Q=
|
||||
github.com/minio/crc64nvme v1.1.0/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/crc64nvme v1.0.2 h1:6uO1UxGAD+kwqWWp7mBFsi5gAse66C4NXO8cmcVculg=
|
||||
github.com/minio/crc64nvme v1.0.2/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
|
||||
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.97 h1:lqhREPyfgHTB/ciX8k2r8k0D93WaFqxbJX36UZq5occ=
|
||||
github.com/minio/minio-go/v7 v7.0.97/go.mod h1:re5VXuo0pwEtoNLsNuSr0RrLfT/MBtohwdaSmPPSRSk=
|
||||
github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU=
|
||||
github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
@@ -908,8 +899,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.1 h1:0tRrc9bzyXEdBLcHr2XEjDzVpUxWx64aZBm7Rl1QDrA=
|
||||
github.com/nats-io/nats-server/v2 v2.12.1/go.mod h1:OEaOLmu/2e6J9LzUt2OuGjgNem4EpYApO5Rpf26HDs8=
|
||||
github.com/nats-io/nats-server/v2 v2.12.0 h1:OIwe8jZUqJFrh+hhiyKu8snNib66qsx806OslqJuo74=
|
||||
github.com/nats-io/nats-server/v2 v2.12.0/go.mod h1:nr8dhzqkP5E/lDwmn+A2CvQPMd1yDKXQI7iGg3lAvww=
|
||||
github.com/nats-io/nats.go v1.47.0 h1:YQdADw6J/UfGUd2Oy6tn4Hq6YHxCaJrVKayxxFqYrgM=
|
||||
github.com/nats-io/nats.go v1.47.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
@@ -930,15 +921,13 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
|
||||
github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=
|
||||
github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
|
||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.1.2 h1:lkg/k/9mlsy0SxO5aC+WEpbdT5K83ddnNhAepz7TQc0=
|
||||
github.com/olekukonko/ll v0.1.2/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/olekukonko/tablewriter v1.1.1 h1:b3reP6GCfrHwmKkYwNRFh2rxidGHcT6cgxj/sHiDDx0=
|
||||
github.com/olekukonko/tablewriter v1.1.1/go.mod h1:De/bIcTF+gpBDB3Alv3fEsZA+9unTsSzAg/ZGADCtn4=
|
||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
@@ -951,18 +940,16 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
|
||||
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
|
||||
github.com/open-policy-agent/opa v1.10.1 h1:haIvxZSPky8HLjRrvQwWAjCPLg8JDFSZMbbG4yyUHgY=
|
||||
github.com/open-policy-agent/opa v1.10.1/go.mod h1:7uPI3iRpOalJ0BhK6s1JALWPU9HvaV1XeBSSMZnr/PM=
|
||||
github.com/open-policy-agent/opa v1.9.0 h1:QWFNwbcc29IRy0xwD3hRrMc/RtSersLY1Z6TaID3vgI=
|
||||
github.com/open-policy-agent/opa v1.9.0/go.mod h1:72+lKmTda0O48m1VKAxxYl7MjP/EWFZu9fxHQK2xihs=
|
||||
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.39.3 h1:/9NW08Bpy1GaNAPo8HrlyT21Flj8uNnOUyWLud1ehGc=
|
||||
github.com/opencloud-eu/reva/v2 v2.39.3/go.mod h1:kkGiMeEVR59VjDsmWIczWqRcwK8cy9ogTd/u802U3NI=
|
||||
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6 h1:BUrCUrRqBg04MJuhnIK4H1KNK4aebK6H/AYcHjQ0DM4=
|
||||
github.com/opencloud-eu/reva/v2 v2.39.2-0.20251030154544-cac8a0257da6/go.mod h1:Qm0CibFYrFc096OhWWL14nsGiFoE6g/4oMFHV5CqU+Q=
|
||||
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=
|
||||
@@ -979,6 +966,8 @@ github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CF
|
||||
github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/pablodz/inotifywaitgo v0.0.9 h1:njquRbBU7fuwIe5rEvtaniVBjwWzcpdUVptSgzFqZsw=
|
||||
github.com/pablodz/inotifywaitgo v0.0.9/go.mod h1:hAfx2oN+WKg8miwUKPs52trySpPignlRBRxWcXVHku0=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
@@ -1012,8 +1001,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.29.0 h1:/ET4NmAGx2Dv9kStrXIBqBgHyiSgIk4OetY+hoZRfgc=
|
||||
github.com/prometheus/alertmanager v0.29.0/go.mod h1:SjI2vhrfdWg10UaRUxTz27rgdJVG3HXrhI5WFjCdBgs=
|
||||
github.com/prometheus/alertmanager v0.28.1 h1:BK5pCoAtaKg01BYRUJhEDV1tqJMEtYBGzPw8QdvnnvA=
|
||||
github.com/prometheus/alertmanager v0.28.1/go.mod h1:0StpPUDDHi1VXeM7p2yYfeZgLVi/PPlt39vo9LQUHxM=
|
||||
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=
|
||||
@@ -1046,8 +1035,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.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
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=
|
||||
@@ -1072,6 +1061,9 @@ github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8A
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/riandyrn/otelchi v0.12.2 h1:6QhGv0LVw/dwjtPd12mnNrl0oEQF4ZAlmHcnlTYbeAg=
|
||||
github.com/riandyrn/otelchi v0.12.2/go.mod h1:weZZeUJURvtCcbWsdb7Y6F8KFZGedJlSrgUjq9VirV8=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -1091,12 +1083,6 @@ github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
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/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.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
@@ -1289,8 +1275,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
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/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
|
||||
@@ -1332,8 +1318,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -1357,8 +1343,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.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
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=
|
||||
@@ -1400,8 +1386,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.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
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=
|
||||
@@ -1464,8 +1450,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.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.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=
|
||||
@@ -1483,8 +1469,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1568,8 +1554,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.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.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=
|
||||
@@ -1581,8 +1567,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.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
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=
|
||||
@@ -1597,16 +1583,16 @@ 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.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
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=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1661,8 +1647,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.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
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=
|
||||
|
||||
@@ -17,7 +17,7 @@ include ../.make/docs.mk
|
||||
|
||||
.PHONY: dev-docker
|
||||
dev-docker:
|
||||
docker build -f docker/Dockerfile.multiarch -t opencloudeu/opencloud:dev ../..
|
||||
docker build -f docker/Dockerfile.multiarch -t opencloudeu/opencloud:dev ..
|
||||
|
||||
.PHONY: dev-docker-multiarch
|
||||
dev-docker-multiarch:
|
||||
@@ -28,7 +28,7 @@ dev-docker-multiarch:
|
||||
docker buildx rm opencloudbuilder || true
|
||||
docker buildx create --platform linux/arm64,linux/amd64 --name opencloudbuilder
|
||||
docker buildx use opencloudbuilder
|
||||
docker buildx build --platform linux/arm64,linux/amd64 --output type=docker --file docker/Dockerfile.multiarch --tag opencloudeu/opencloud:dev-multiarch ../..
|
||||
cd .. && docker buildx build --platform linux/arm64,linux/amd64 --output type=docker --file opencloud/docker/Dockerfile.multiarch --tag opencloudeu/opencloud:dev-multiarch .
|
||||
docker buildx rm opencloudbuilder
|
||||
|
||||
.PHONY: debug-docker
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:alpine3.22 AS build
|
||||
FROM golang:alpine3.21 AS build
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG VERSION
|
||||
@@ -6,14 +6,14 @@ ARG STRING
|
||||
|
||||
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev
|
||||
|
||||
WORKDIR /build
|
||||
RUN --mount=type=bind,target=/build,rw \
|
||||
WORKDIR /opencloud
|
||||
RUN --mount=type=bind,target=/opencloud \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
GOOS="${TARGETOS:-linux}" GOARCH="${TARGETARCH:-amd64}" ; \
|
||||
make -C opencloud/opencloud release-linux-docker-${TARGETARCH} ENABLE_VIPS=true DIST=/dist
|
||||
make -C opencloud release-linux-docker-${TARGETARCH} ENABLE_VIPS=true DIST=/dist
|
||||
|
||||
FROM alpine:3.22
|
||||
FROM alpine:3.21
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
ARG TARGETOS
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gofrs/uuid"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/generators"
|
||||
@@ -68,7 +68,7 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
systemUserID, adminUserID, graphApplicationID, storageUsersMountID, serviceAccountID string
|
||||
idmServicePassword, idpServicePassword, ocAdminServicePassword, revaServicePassword string
|
||||
tokenManagerJwtSecret, collaborationWOPISecret, machineAuthAPIKey, systemUserAPIKey string
|
||||
revaTransferSecret, thumbnailsTransferSecret, serviceAccountSecret, urlSigningSecret string
|
||||
revaTransferSecret, thumbnailsTransferSecret, serviceAccountSecret string
|
||||
)
|
||||
|
||||
if diff {
|
||||
@@ -95,19 +95,12 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
revaTransferSecret = oldCfg.TransferSecret
|
||||
thumbnailsTransferSecret = oldCfg.Thumbnails.Thumbnail.TransferSecret
|
||||
serviceAccountSecret = oldCfg.Graph.ServiceAccount.ServiceAccountSecret
|
||||
urlSigningSecret = oldCfg.URLSigningSecret
|
||||
if urlSigningSecret == "" {
|
||||
urlSigningSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random secret for urlSigningSecret: %s", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
systemUserID = uuid.NewString()
|
||||
adminUserID = uuid.NewString()
|
||||
graphApplicationID = uuid.NewString()
|
||||
storageUsersMountID = uuid.NewString()
|
||||
serviceAccountID = uuid.NewString()
|
||||
systemUserID = uuid.Must(uuid.NewV4()).String()
|
||||
adminUserID = uuid.Must(uuid.NewV4()).String()
|
||||
graphApplicationID = uuid.Must(uuid.NewV4()).String()
|
||||
storageUsersMountID = uuid.Must(uuid.NewV4()).String()
|
||||
serviceAccountID = uuid.Must(uuid.NewV4()).String()
|
||||
|
||||
idmServicePassword, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
@@ -149,17 +142,13 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random password for revaTransferSecret: %s", err)
|
||||
}
|
||||
urlSigningSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random secret for urlSigningSecret: %s", err)
|
||||
}
|
||||
thumbnailsTransferSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random password for thumbnailsTransferSecret: %s", err)
|
||||
}
|
||||
serviceAccountSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random secret for serviceAccountSecret: %s", err)
|
||||
return fmt.Errorf("could not generate random password for thumbnailsTransferSecret: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +164,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
MachineAuthAPIKey: machineAuthAPIKey,
|
||||
SystemUserAPIKey: systemUserAPIKey,
|
||||
TransferSecret: revaTransferSecret,
|
||||
URLSigningSecret: urlSigningSecret,
|
||||
SystemUserID: systemUserID,
|
||||
AdminUserID: adminUserID,
|
||||
Idm: IdmService{
|
||||
|
||||
@@ -19,7 +19,6 @@ type OpenCloudConfig struct {
|
||||
MachineAuthAPIKey string `yaml:"machine_auth_api_key"`
|
||||
SystemUserAPIKey string `yaml:"system_user_api_key"`
|
||||
TransferSecret string `yaml:"transfer_secret"`
|
||||
URLSigningSecret string `yaml:"url_signing_secret"`
|
||||
SystemUserID string `yaml:"system_user_id"`
|
||||
AdminUserID string `yaml:"admin_user_id"`
|
||||
Graph GraphService `yaml:"graph"`
|
||||
|
||||
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/rpc"
|
||||
@@ -381,32 +382,7 @@ func Start(ctx context.Context, o ...Option) error {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
switch ev := e.(type) {
|
||||
case suture.EventServicePanic:
|
||||
l := s.Log.Fatal()
|
||||
if ev.Restarting {
|
||||
l = s.Log.Error()
|
||||
}
|
||||
l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
|
||||
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold).
|
||||
Str("message", ev.PanicMsg).Msg("service panic")
|
||||
case suture.EventServiceTerminate:
|
||||
l := s.Log.Fatal()
|
||||
if ev.Restarting {
|
||||
l = s.Log.Error()
|
||||
}
|
||||
l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
|
||||
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold).
|
||||
Interface("error", ev.Err).Msg("service terminated")
|
||||
case suture.EventBackoff:
|
||||
s.Log.Warn().Str("event", e.String()).Str("supervisor", ev.SupervisorName).Msg("service backoff")
|
||||
case suture.EventResume:
|
||||
s.Log.Info().Str("event", e.String()).Str("supervisor", ev.SupervisorName).Msg("service resume")
|
||||
case suture.EventStopTimeout:
|
||||
s.Log.Warn().Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).Msg("service resume")
|
||||
default:
|
||||
s.Log.Warn().Str("event", e.String()).Msgf("supervisor: %v", e.Map()["supervisor_name"])
|
||||
}
|
||||
s.Log.Info().Str("event", e.String()).Msg(fmt.Sprintf("supervisor: %v", e.Map()["supervisor_name"]))
|
||||
},
|
||||
FailureThreshold: 5,
|
||||
FailureBackoff: 3 * time.Second,
|
||||
|
||||
@@ -62,13 +62,14 @@ type Runtime struct {
|
||||
type Config struct {
|
||||
*shared.Commons `yaml:"shared"`
|
||||
|
||||
Tracing *shared.Tracing `yaml:"tracing"`
|
||||
Log *shared.Log `yaml:"log"`
|
||||
Cache *shared.Cache `yaml:"cache"`
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GRPCServiceTLS *shared.GRPCServiceTLS `yaml:"grpc_service_tls"`
|
||||
HTTPServiceTLS shared.HTTPServiceTLS `yaml:"http_service_tls"`
|
||||
Reva *shared.Reva `yaml:"reva"`
|
||||
Tracing *shared.Tracing `yaml:"tracing"`
|
||||
Log *shared.Log `yaml:"log"`
|
||||
Cache *shared.Cache `yaml:"cache"`
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GRPCServiceTLS *shared.GRPCServiceTLS `yaml:"grpc_service_tls"`
|
||||
HTTPServiceTLS shared.HTTPServiceTLS `yaml:"http_service_tls"`
|
||||
HTTPServiceTimeout shared.HTTPServiceTimeout `yaml:"http_service_timeout"`
|
||||
Reva *shared.Reva `yaml:"reva"`
|
||||
|
||||
Mode Mode // DEPRECATED
|
||||
File string
|
||||
@@ -78,7 +79,6 @@ type Config struct {
|
||||
TokenManager *shared.TokenManager `yaml:"token_manager"`
|
||||
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
|
||||
TransferSecret string `yaml:"transfer_secret" env:"OC_TRANSFER_SECRET" desc:"Transfer secret for signing file up- and download requests." introductionVersion:"1.0.0"`
|
||||
URLSigningSecret string `yaml:"url_signing_secret" env:"OC_URL_SIGNING_SECRET" desc:"The shared secret used to sign URLs e.g. for image downloads by the web office suite." introductionVersion:"%%NEXT%%"`
|
||||
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
|
||||
SystemUserAPIKey string `yaml:"system_user_api_key" env:"OC_SYSTEM_USER_API_KEY" desc:"API key for the storage-system system user." introductionVersion:"1.0.0"`
|
||||
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`
|
||||
|
||||
@@ -2,6 +2,7 @@ package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/config"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/envdecode"
|
||||
@@ -61,6 +62,8 @@ func EnsureDefaults(cfg *config.Config) {
|
||||
if cfg.Reva == nil {
|
||||
cfg.Reva = &shared.Reva{}
|
||||
}
|
||||
|
||||
cfg.HTTPServiceTimeout.Read = 60 * time.Second
|
||||
}
|
||||
|
||||
// EnsureCommons copies applicable parts of the OpenCloud config into the commons part
|
||||
@@ -83,6 +86,7 @@ func EnsureCommons(cfg *config.Config) {
|
||||
}
|
||||
|
||||
cfg.Commons.HTTPServiceTLS = cfg.HTTPServiceTLS
|
||||
cfg.Commons.HTTPServiceTimeout = cfg.HTTPServiceTimeout
|
||||
|
||||
cfg.Commons.TokenManager = structs.CopyOrZeroValue(cfg.TokenManager)
|
||||
|
||||
@@ -100,14 +104,6 @@ func EnsureCommons(cfg *config.Config) {
|
||||
cfg.Commons.TransferSecret = cfg.TransferSecret
|
||||
}
|
||||
|
||||
// make sure url signing secret is set and copy it to the commons part
|
||||
// fall back to transfer secret for url signing secret to avoid
|
||||
// issues when upgrading from an older release
|
||||
if cfg.URLSigningSecret == "" {
|
||||
cfg.URLSigningSecret = cfg.TransferSecret
|
||||
}
|
||||
cfg.Commons.URLSigningSecret = cfg.URLSigningSecret
|
||||
|
||||
// copy metadata user id to the commons part if set
|
||||
if cfg.SystemUserID != "" {
|
||||
cfg.Commons.SystemUserID = cfg.SystemUserID
|
||||
@@ -136,10 +132,6 @@ func Validate(cfg *config.Config) error {
|
||||
return shared.MissingRevaTransferSecretError("opencloud")
|
||||
}
|
||||
|
||||
if cfg.URLSigningSecret == "" {
|
||||
return shared.MissingURLSigningSecret("opencloud")
|
||||
}
|
||||
|
||||
if cfg.MachineAuthAPIKey == "" {
|
||||
return shared.MissingMachineAuthApiKeyError("opencloud")
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/shared"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/shared"
|
||||
)
|
||||
|
||||
// Option defines a single option function.
|
||||
@@ -17,6 +18,7 @@ type Option func(o *Options)
|
||||
type Options struct {
|
||||
Logger log.Logger
|
||||
TLSConfig shared.HTTPServiceTLS
|
||||
TimeoutConfig shared.HTTPServiceTimeout
|
||||
Namespace string
|
||||
Name string
|
||||
Version string
|
||||
@@ -96,6 +98,13 @@ func TLSConfig(config shared.HTTPServiceTLS) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// TimeoutConfig provides a function to set the TimeOutConfig option.
|
||||
func TimeoutConfig(config shared.HTTPServiceTimeout) Option {
|
||||
return func(o *Options) {
|
||||
o.TimeoutConfig = config
|
||||
}
|
||||
}
|
||||
|
||||
// TraceProvider provides a function to set the TraceProvider option.
|
||||
func TraceProvider(tp trace.TracerProvider) Option {
|
||||
return func(o *Options) {
|
||||
|
||||
@@ -3,16 +3,18 @@ package http
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/broker"
|
||||
"github.com/opencloud-eu/opencloud/pkg/registry"
|
||||
netx "github.com/opencloud-eu/opencloud/pkg/x/net"
|
||||
|
||||
mhttps "github.com/go-micro/plugins/v4/server/http"
|
||||
mtracer "github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry"
|
||||
occrypto "github.com/opencloud-eu/opencloud/pkg/crypto"
|
||||
"go-micro.dev/v4"
|
||||
"go-micro.dev/v4/server"
|
||||
|
||||
occrypto "github.com/opencloud-eu/opencloud/pkg/crypto"
|
||||
)
|
||||
|
||||
// Service simply wraps the go-micro web service.
|
||||
@@ -24,7 +26,9 @@ type Service struct {
|
||||
func NewService(opts ...Option) (Service, error) {
|
||||
noopBroker := broker.NoOp{}
|
||||
sopts := newOptions(opts...)
|
||||
var mServer server.Server
|
||||
|
||||
var listener net.Listener
|
||||
var err error
|
||||
if sopts.TLSConfig.Enabled {
|
||||
var cert tls.Certificate
|
||||
var err error
|
||||
@@ -50,11 +54,27 @@ func NewService(opts ...Option) (Service, error) {
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
mServer = mhttps.NewServer(server.TLSConfig(tlsConfig))
|
||||
// Create TLS listener
|
||||
listener, err = tls.Listen("tcp", sopts.Address, tlsConfig)
|
||||
if err != nil {
|
||||
return Service{}, fmt.Errorf("error starting TLS listener: %w", err)
|
||||
}
|
||||
} else {
|
||||
mServer = mhttps.NewServer()
|
||||
// Create Non-TLS listener
|
||||
listener, err = net.Listen("tcp", sopts.Address)
|
||||
if err != nil {
|
||||
return Service{}, fmt.Errorf("error starting TCP listener: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
mServer := mhttps.NewServer(
|
||||
// Wrap listener with timeoutListener to set a read timeout
|
||||
mhttps.Listener(netx.TimeoutListener{
|
||||
Listener: listener,
|
||||
ReadTimeout: sopts.TimeoutConfig.Read,
|
||||
}),
|
||||
)
|
||||
|
||||
wopts := []micro.Option{
|
||||
micro.Server(mServer),
|
||||
micro.Broker(noopBroker),
|
||||
|
||||
@@ -93,11 +93,3 @@ func MissingWOPISecretError(service string) error {
|
||||
"the config/corresponding environment variable).",
|
||||
service, defaults.BaseConfigPath())
|
||||
}
|
||||
|
||||
func MissingURLSigningSecret(service string) error {
|
||||
return fmt.Errorf("The URL signing secret has not been set properly in your config for %s. "+
|
||||
"Make sure your %s config contains the proper values "+
|
||||
"(e.g. by using 'opencloud init --diff' and applying the patch or setting a value manually in "+
|
||||
"the config/corresponding environment variable).",
|
||||
service, defaults.BaseConfigPath())
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ type HTTPServiceTLS struct {
|
||||
Key string `yaml:"key" env:"OC_HTTP_TLS_KEY" desc:"Path/File name for the TLS certificate key (in PEM format) for the server certificate to use for the http services." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type HTTPServiceTimeout struct {
|
||||
Read time.Duration `yaml:"duration" env:"OC_HTTP_TIMEOUT_READ" desc:"The duration after which a read operation will time out." introductionVersion:"%%NEXT%%"`
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
Store string `yaml:"store" env:"OC_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details." introductionVersion:"1.0.0"`
|
||||
Nodes []string `yaml:"nodes" env:"OC_CACHE_STORE_NODES" desc:"A comma separated 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." introductionVersion:"1.0.0"`
|
||||
@@ -69,22 +73,22 @@ type Cache struct {
|
||||
// Commons holds configuration that are common to all extensions. Each extension can then decide whether
|
||||
// to overwrite its values.
|
||||
type Commons struct {
|
||||
Log *Log `yaml:"log"`
|
||||
Tracing *Tracing `yaml:"tracing"`
|
||||
Cache *Cache `yaml:"cache"`
|
||||
GRPCClientTLS *GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GRPCServiceTLS *GRPCServiceTLS `yaml:"grpc_service_tls"`
|
||||
HTTPServiceTLS HTTPServiceTLS `yaml:"http_service_tls"`
|
||||
OpenCloudURL string `yaml:"opencloud_url" env:"OC_URL" desc:"URL, where OpenCloud is reachable for users." introductionVersion:"1.0.0"`
|
||||
TokenManager *TokenManager `mask:"struct" yaml:"token_manager"`
|
||||
Reva *Reva `yaml:"reva"`
|
||||
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
|
||||
TransferSecret string `mask:"password" yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET" desc:"The secret used for signing the requests towards the data gateway for up- and downloads." introductionVersion:"1.0.0"`
|
||||
URLSigningSecret string `yaml:"url_signing_secret" env:"OC_URL_SIGNING_SECRET" desc:"The shared secret used to sign URLs e.g. for image downloads by the web office suite." introductionVersion:"%%NEXT%%"`
|
||||
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
|
||||
SystemUserAPIKey string `mask:"password" yaml:"system_user_api_key" env:"SYSTEM_USER_API_KEY" desc:"API key for all system users." introductionVersion:"1.0.0"`
|
||||
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`
|
||||
MultiTenantEnabled bool `yaml:"multi_tenant_enabled" env:"OC_MULTI_TENANT_ENABLED" desc:"Set this to true to enable multi-tenant support." introductionVersion:"%%NEXT%%"`
|
||||
Log *Log `yaml:"log"`
|
||||
Tracing *Tracing `yaml:"tracing"`
|
||||
Cache *Cache `yaml:"cache"`
|
||||
GRPCClientTLS *GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GRPCServiceTLS *GRPCServiceTLS `yaml:"grpc_service_tls"`
|
||||
HTTPServiceTLS HTTPServiceTLS `yaml:"http_service_tls"`
|
||||
HTTPServiceTimeout HTTPServiceTimeout `yaml:"http_service_timeout"`
|
||||
OpenCloudURL string `yaml:"opencloud_url" env:"OC_URL" desc:"URL, where OpenCloud is reachable for users." introductionVersion:"1.0.0"`
|
||||
TokenManager *TokenManager `mask:"struct" yaml:"token_manager"`
|
||||
Reva *Reva `yaml:"reva"`
|
||||
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
|
||||
TransferSecret string `mask:"password" yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET" desc:"The secret used for signing the requests towards the data gateway for up- and downloads." introductionVersion:"1.0.0"`
|
||||
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
|
||||
SystemUserAPIKey string `mask:"password" yaml:"system_user_api_key" env:"SYSTEM_USER_API_KEY" desc:"API key for all system users." introductionVersion:"1.0.0"`
|
||||
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`
|
||||
MultiTenantEnabled bool `yaml:"multi_tenant_enabled" env:"OC_MULTI_TENANT_ENABLED" desc:"Set this to true to enable multi-tenant support." introductionVersion:"%%NEXT%%"`
|
||||
|
||||
// NOTE: you will not fing GRPCMaxReceivedMessageSize size being used in the code. The envvar is actually extracted in revas `pool` package: https://github.com/cs3org/reva/blob/edge/pkg/rgrpc/todo/pool/connection.go
|
||||
// It is mentioned here again so it is documented
|
||||
|
||||
@@ -16,7 +16,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 = "4.0.0-rc.2+dev"
|
||||
LatestTag = "3.7.0+dev"
|
||||
|
||||
// Date indicates the build date.
|
||||
// This has been removed, it looks like you can only replace static strings with recent go versions
|
||||
|
||||
47
pkg/x/net/listener.go
Normal file
47
pkg/x/net/listener.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"io"
|
||||
gonet "net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TimeoutListener struct {
|
||||
gonet.Listener
|
||||
ReadTimeout time.Duration
|
||||
}
|
||||
|
||||
func (l TimeoutListener) Accept() (gonet.Conn, error) {
|
||||
c, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &TimeoutConn{Conn: c, readTimeout: l.ReadTimeout}, nil
|
||||
}
|
||||
|
||||
type TimeoutConn struct {
|
||||
gonet.Conn
|
||||
readTimeout time.Duration
|
||||
bodyDone bool
|
||||
}
|
||||
|
||||
// Read implements a read with a sliding timeout window.
|
||||
func (c *TimeoutConn) Read(b []byte) (int, error) {
|
||||
if c.readTimeout > 0 && !c.bodyDone {
|
||||
if err := c.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n, err := c.Conn.Read(b)
|
||||
if n > 0 && c.readTimeout > 0 && !c.bodyDone {
|
||||
// reset deadline after every successful read
|
||||
_ = c.SetReadDeadline(time.Now().Add(c.readTimeout))
|
||||
}
|
||||
|
||||
if err == io.EOF {
|
||||
c.bodyDone = true
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-26 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: pkg/service/response.go:44
|
||||
msgid "description"
|
||||
msgstr "kuvaus"
|
||||
|
||||
#: pkg/service/response.go:43
|
||||
msgid "display name"
|
||||
msgstr "näyttönimi"
|
||||
|
||||
#: pkg/service/response.go:42
|
||||
msgid "expiration date"
|
||||
msgstr "vanhenemispäivä"
|
||||
|
||||
#: pkg/service/response.go:41
|
||||
msgid "password"
|
||||
msgstr "salasana"
|
||||
|
||||
#: pkg/service/response.go:40
|
||||
msgid "permission"
|
||||
msgstr "käyttöoikeus"
|
||||
|
||||
#: pkg/service/response.go:39
|
||||
msgid "some field"
|
||||
msgstr "jokin kieltä"
|
||||
|
||||
#: pkg/service/response.go:26
|
||||
msgid "{resource} was downloaded via public link {token}"
|
||||
msgstr "{resource} ladattiin julkisen linkin {token} kautta"
|
||||
|
||||
#: pkg/service/response.go:24
|
||||
msgid "{user} added {resource} to {folder}"
|
||||
msgstr "{user} lisäsi {resource} kansioon {folder}"
|
||||
|
||||
#: pkg/service/response.go:36
|
||||
msgid "{user} added {sharee} as member of {space}"
|
||||
msgstr "{user} lisäsi {sharee} jäseneksi avaruuteen {space}"
|
||||
|
||||
#: pkg/service/response.go:27
|
||||
msgid "{user} deleted {resource} from {folder}"
|
||||
msgstr "{user} poisti {resource} kansiosta {folder}"
|
||||
|
||||
#: pkg/service/response.go:28
|
||||
msgid "{user} moved {resource} to {folder}"
|
||||
msgstr "{user} siirsi {resource} kansioon {folder}"
|
||||
|
||||
#: pkg/service/response.go:35
|
||||
msgid "{user} removed link to {resource}"
|
||||
msgstr "{user} poisti linkin resurssiin {resource}"
|
||||
|
||||
#: pkg/service/response.go:32
|
||||
msgid "{user} removed {sharee} from {resource}"
|
||||
msgstr "{user} poisti {sharee} resurssista {resource}"
|
||||
|
||||
#: pkg/service/response.go:37
|
||||
msgid "{user} removed {sharee} from {space}"
|
||||
msgstr "{user} poisti {sharee} avaruudesta {space}"
|
||||
|
||||
#: pkg/service/response.go:29
|
||||
msgid "{user} renamed {oldResource} to {resource}"
|
||||
msgstr "{user} muutti kohteen {oldResource} uudeksi nimeksi {resource}"
|
||||
|
||||
#: pkg/service/response.go:33
|
||||
msgid "{user} shared {resource} via link"
|
||||
msgstr "{user} jakoi {resource} linkin kautta"
|
||||
|
||||
#: pkg/service/response.go:30
|
||||
msgid "{user} shared {resource} with {sharee}"
|
||||
msgstr "{user} jakoi {resource} käyttäjän {sharee} kanssa"
|
||||
|
||||
#: pkg/service/response.go:34
|
||||
msgid "{user} updated {field} for a link {token} on {resource}"
|
||||
msgstr ""
|
||||
"{user} päivitti kentän {field} linkkiin {token} resurssissa {resource}"
|
||||
|
||||
#: pkg/service/response.go:31
|
||||
msgid "{user} updated {field} for the {resource}"
|
||||
msgstr "{user} päivitti kentän {field} resurssille {resource}"
|
||||
|
||||
#: pkg/service/response.go:25
|
||||
msgid "{user} updated {resource} in {folder}"
|
||||
msgstr "{user} päivitti {resource} kansiossa {folder}"
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-12 00:01+0000\n"
|
||||
"POT-Creation-Date: 2025-10-23 00:01+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"
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Mário Machado, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-17 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#: pkg/service/response.go:44
|
||||
msgid "description"
|
||||
msgstr "descrição"
|
||||
|
||||
#: pkg/service/response.go:43
|
||||
msgid "display name"
|
||||
msgstr "nome de exibição"
|
||||
|
||||
#: pkg/service/response.go:42
|
||||
msgid "expiration date"
|
||||
msgstr "data de expiração"
|
||||
|
||||
#: pkg/service/response.go:41
|
||||
msgid "password"
|
||||
msgstr "palavra-passe"
|
||||
|
||||
#: pkg/service/response.go:40
|
||||
msgid "permission"
|
||||
msgstr "permissão"
|
||||
|
||||
#: pkg/service/response.go:39
|
||||
msgid "some field"
|
||||
msgstr "algum campo"
|
||||
|
||||
#: pkg/service/response.go:26
|
||||
msgid "{resource} was downloaded via public link {token}"
|
||||
msgstr "{resource} foi descarregado através da ligação pública {token}"
|
||||
|
||||
#: pkg/service/response.go:24
|
||||
msgid "{user} added {resource} to {folder}"
|
||||
msgstr "{user} adicionou {resource} a {folder}"
|
||||
|
||||
#: pkg/service/response.go:36
|
||||
msgid "{user} added {sharee} as member of {space}"
|
||||
msgstr "{user} adicionou {sharee} como membro de {space}"
|
||||
|
||||
#: pkg/service/response.go:27
|
||||
msgid "{user} deleted {resource} from {folder}"
|
||||
msgstr "{user} eliminou {resource} de {folder}"
|
||||
|
||||
#: pkg/service/response.go:28
|
||||
msgid "{user} moved {resource} to {folder}"
|
||||
msgstr "{user} moveu {resource} para {folder}"
|
||||
|
||||
#: pkg/service/response.go:35
|
||||
msgid "{user} removed link to {resource}"
|
||||
msgstr "{user} removeu a ligação para {resource}"
|
||||
|
||||
#: pkg/service/response.go:32
|
||||
msgid "{user} removed {sharee} from {resource}"
|
||||
msgstr "{user} removeu {sharee} de {resource}"
|
||||
|
||||
#: pkg/service/response.go:37
|
||||
msgid "{user} removed {sharee} from {space}"
|
||||
msgstr "{user} removeu {sharee} de {space}"
|
||||
|
||||
#: pkg/service/response.go:29
|
||||
msgid "{user} renamed {oldResource} to {resource}"
|
||||
msgstr "{user} renomeou {oldResource} para {resource}"
|
||||
|
||||
#: pkg/service/response.go:33
|
||||
msgid "{user} shared {resource} via link"
|
||||
msgstr "{user} partilhou {resource} via ligação"
|
||||
|
||||
#: pkg/service/response.go:30
|
||||
msgid "{user} shared {resource} with {sharee}"
|
||||
msgstr "{user} partilhou {resource} com {sharee}"
|
||||
|
||||
#: pkg/service/response.go:34
|
||||
msgid "{user} updated {field} for a link {token} on {resource}"
|
||||
msgstr "{user} atualizou {field} para a ligação {token} em {resource}"
|
||||
|
||||
#: pkg/service/response.go:31
|
||||
msgid "{user} updated {field} for the {resource}"
|
||||
msgstr "{user} atualizou {field} para o {resource}"
|
||||
|
||||
#: pkg/service/response.go:25
|
||||
msgid "{user} updated {resource} in {folder}"
|
||||
msgstr "{user} atualizou {resource} em {folder}"
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-12 00:01+0000\n"
|
||||
"POT-Creation-Date: 2025-10-23 00:01+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"
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Daniel Nylander <po@danielnylander.se>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-08 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sv\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: pkg/service/response.go:44
|
||||
msgid "description"
|
||||
msgstr "beskrivning"
|
||||
|
||||
#: pkg/service/response.go:43
|
||||
msgid "display name"
|
||||
msgstr "visningsnamn"
|
||||
|
||||
#: pkg/service/response.go:42
|
||||
msgid "expiration date"
|
||||
msgstr "utgångsdatum"
|
||||
|
||||
#: pkg/service/response.go:41
|
||||
msgid "password"
|
||||
msgstr "lösenord"
|
||||
|
||||
#: pkg/service/response.go:40
|
||||
msgid "permission"
|
||||
msgstr "behörighet"
|
||||
|
||||
#: pkg/service/response.go:39
|
||||
msgid "some field"
|
||||
msgstr "något fält"
|
||||
|
||||
#: pkg/service/response.go:26
|
||||
msgid "{resource} was downloaded via public link {token}"
|
||||
msgstr "{resource} hämtades via en offentlig länk {token}"
|
||||
|
||||
#: pkg/service/response.go:24
|
||||
msgid "{user} added {resource} to {folder}"
|
||||
msgstr "{user} lade till {resource} till {folder}"
|
||||
|
||||
#: pkg/service/response.go:36
|
||||
msgid "{user} added {sharee} as member of {space}"
|
||||
msgstr "{user} lade till {sharee} som medlem av {space}"
|
||||
|
||||
#: pkg/service/response.go:27
|
||||
msgid "{user} deleted {resource} from {folder}"
|
||||
msgstr "{user} raderade {resource} från {folder}"
|
||||
|
||||
#: pkg/service/response.go:28
|
||||
msgid "{user} moved {resource} to {folder}"
|
||||
msgstr "{user} flyttade {resource} till {folder}"
|
||||
|
||||
#: pkg/service/response.go:35
|
||||
msgid "{user} removed link to {resource}"
|
||||
msgstr "{user} tog bort länk till {resource}"
|
||||
|
||||
#: pkg/service/response.go:32
|
||||
msgid "{user} removed {sharee} from {resource}"
|
||||
msgstr "{user} tog bort {sharee} från {resource}"
|
||||
|
||||
#: pkg/service/response.go:37
|
||||
msgid "{user} removed {sharee} from {space}"
|
||||
msgstr "{user} tog bort {sharee} från {space}"
|
||||
|
||||
#: pkg/service/response.go:29
|
||||
msgid "{user} renamed {oldResource} to {resource}"
|
||||
msgstr "{user} döpte om {oldResource} till {resource}"
|
||||
|
||||
#: pkg/service/response.go:33
|
||||
msgid "{user} shared {resource} via link"
|
||||
msgstr "{user} delade {resource} via länk"
|
||||
|
||||
#: pkg/service/response.go:30
|
||||
msgid "{user} shared {resource} with {sharee}"
|
||||
msgstr "{user} delade {resource} med {sharee}"
|
||||
|
||||
#: pkg/service/response.go:34
|
||||
msgid "{user} updated {field} for a link {token} on {resource}"
|
||||
msgstr "{user} uppdaterade {field} för en länk {token} på {resource}"
|
||||
|
||||
#: pkg/service/response.go:31
|
||||
msgid "{user} updated {field} for the {resource}"
|
||||
msgstr "{user} uppdaterade {field} för {resource}"
|
||||
|
||||
#: pkg/service/response.go:25
|
||||
msgid "{user} updated {resource} in {folder}"
|
||||
msgstr "{user} uppdaterade {resource} i {folder}"
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# App Provider
|
||||
|
||||
The `app-provider` service provides the CS3 App Provider API for OpenCloud. It is responsible for managing and serving applications that can open files based on their MIME types.
|
||||
|
||||
The service works in conjunction with the `app-registry` service, which maintains the registry of available applications and their supported MIME types. When a client requests to open a file with a specific application, the `app-provider` service handles the request and coordinates with the application to provide the appropriate interface.
|
||||
|
||||
## Integration
|
||||
|
||||
The `app-provider` service integrates with:
|
||||
- `app-registry` - For discovering which applications are available for specific MIME types
|
||||
- `frontend` - The frontend service forwards app provider requests (default endpoint `/app`) to this service
|
||||
|
||||
## Configuration
|
||||
|
||||
The service can be configured via environment variables. Key configuration options include:
|
||||
- `APP_PROVIDER_EXTERNAL_ADDR` - External address where the gateway service can reach the app provider
|
||||
|
||||
## Scalability
|
||||
|
||||
The app-provider service can be scaled horizontally as it primarily acts as a coordinator between applications and the OpenCloud backend services.
|
||||
@@ -60,20 +60,20 @@ The `auth-app` service provides an API to create (POST), list (GET) and delete (
|
||||
```
|
||||
|
||||
Note that the `token` value in the response to the "List Tokens` request is not the actual
|
||||
app token, but the UUID of the token. So this value cannot be used for authenticating
|
||||
app token, but a hashed value of the token. So this value cannot be used for authenticating
|
||||
with the token.
|
||||
|
||||
Example output:
|
||||
```
|
||||
[
|
||||
{
|
||||
"token": "155f402e-1c5c-411c-92d4-92f3b612cd99"
|
||||
"token": "$2a$11$EyudDGAJ18bBf5NG6PL9Ru9gygZAu0oPyLawdieNjGozcbXyyuUhG",
|
||||
"expiration_date": "2024-08-08T13:44:31.025199075+02:00",
|
||||
"created_date": "2024-08-07T13:44:31+02:00",
|
||||
"label": "Generated via Impersonation API"
|
||||
},
|
||||
{
|
||||
"token": "8c606bdb-e22e-4094-9304-732fd4702bc9"
|
||||
"token": "$2a$11$dfRBQrxRMPg8fvyvkFwaX.IPoIUiokvhzK.YNI/pCafk0us3MyPzy",
|
||||
"expiration_date": "2024-08-08T13:46:41.936052281+02:00",
|
||||
"created_date": "2024-08-07T13:46:42+02:00",
|
||||
"label": "Generated via Impersonation API"
|
||||
@@ -84,7 +84,7 @@ The `auth-app` service provides an API to create (POST), list (GET) and delete (
|
||||
* **Delete a token**\
|
||||
The DELETE request requires:
|
||||
* A `token` key/value pair in the form of `token=<token_issued>`. The value needs to be the hashed value as returned by the `List Tokens` respone.\
|
||||
Example: `token=8c606bdb-e22e-4094-9304-732fd4702bc9`
|
||||
Example: `token=$2$Z3s2K7816M4vuSpd5`
|
||||
```bash
|
||||
curl --request DELETE 'https://<your host:9200>/auth-app/tokens?token={value}' \
|
||||
--header 'accept: application/json'
|
||||
|
||||
@@ -1198,7 +1198,6 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
isAnonymousUser := true
|
||||
|
||||
isPublicShare := false
|
||||
isAdminUser := false
|
||||
user := ctxpkg.ContextMustGetUser(ctx)
|
||||
if user.String() != "" {
|
||||
// if we have a wopiContext.User
|
||||
@@ -1208,12 +1207,6 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
isAnonymousUser = false
|
||||
userFriendlyName = user.GetDisplayName()
|
||||
userId = hexEncodedWopiUserId
|
||||
|
||||
isAdminUser, err = utils.CheckPermission(ctx, "WebOffice.Manage", gwc)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("CheckPermission failed")
|
||||
isAdminUser = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1266,7 +1259,6 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
fileinfo.KeyFileVersionURL: createVersionsUrl(privateLinkURL),
|
||||
|
||||
fileinfo.KeyEnableOwnerTermination: true, // only for collabora
|
||||
fileinfo.KeyEnableInsertRemoteImage: true,
|
||||
fileinfo.KeySupportsExtendedLockLength: true,
|
||||
fileinfo.KeySupportsGetLock: true,
|
||||
fileinfo.KeySupportsLocks: true,
|
||||
@@ -1275,7 +1267,6 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
fileinfo.KeySupportsRename: true,
|
||||
|
||||
fileinfo.KeyIsAnonymousUser: isAnonymousUser,
|
||||
fileinfo.KeyIsAdminUser: isAdminUser,
|
||||
fileinfo.KeyUserFriendlyName: userFriendlyName,
|
||||
fileinfo.KeyUserID: userId,
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
auth "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
|
||||
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
|
||||
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
@@ -1672,13 +1671,6 @@ var _ = Describe("FileConnector", func() {
|
||||
}
|
||||
ctx = ctxpkg.ContextSetUser(ctx, u)
|
||||
|
||||
gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(
|
||||
&permissions.CheckPermissionResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
Info: &providerv1beta1.ResourceInfo{
|
||||
@@ -1800,8 +1792,6 @@ var _ = Describe("FileConnector", func() {
|
||||
UserCanRename: false,
|
||||
BreadcrumbDocName: "test.txt",
|
||||
PostMessageOrigin: "https://cloud.opencloud.test",
|
||||
EnableInsertRemoteImage: true,
|
||||
IsAnonymousUser: true,
|
||||
}
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
@@ -1899,7 +1889,7 @@ var _ = Describe("FileConnector", func() {
|
||||
UserCanRename: false,
|
||||
UserCanReview: false,
|
||||
UserCanWrite: false,
|
||||
EnableInsertRemoteImage: true,
|
||||
EnableInsertRemoteImage: false,
|
||||
UserID: "guest-zzz000",
|
||||
UserFriendlyName: "guest zzz000",
|
||||
FileSharingURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=sharing",
|
||||
@@ -1938,13 +1928,6 @@ var _ = Describe("FileConnector", func() {
|
||||
}
|
||||
ctx = ctxpkg.ContextSetUser(ctx, u)
|
||||
|
||||
gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(
|
||||
&permissions.CheckPermissionResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
Info: &providerv1beta1.ResourceInfo{
|
||||
@@ -1992,8 +1975,6 @@ var _ = Describe("FileConnector", func() {
|
||||
UserCanRename: false,
|
||||
BreadcrumbDocName: "test.txt",
|
||||
PostMessageOrigin: "https://cloud.opencloud.test",
|
||||
EnableInsertRemoteImage: true,
|
||||
IsAdminUser: true,
|
||||
}
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
@@ -2020,13 +2001,6 @@ var _ = Describe("FileConnector", func() {
|
||||
}
|
||||
ctx = ctxpkg.ContextSetUser(ctx, u)
|
||||
|
||||
gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(
|
||||
&permissions.CheckPermissionResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
Info: &providerv1beta1.ResourceInfo{
|
||||
@@ -2071,7 +2045,6 @@ var _ = Describe("FileConnector", func() {
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-onlyoffice/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
PostMessageOrigin: "https://cloud.opencloud.test",
|
||||
EnableInsertRemoteImage: true,
|
||||
}
|
||||
|
||||
// change wopi app provider
|
||||
|
||||
@@ -56,10 +56,6 @@ type Collabora struct {
|
||||
SaveAsPostmessage bool `json:"SaveAsPostmessage,omitempty"`
|
||||
// If set to true, it allows the document owner (the one with OwnerId =UserId) to send a closedocument message (see protocol.txt)
|
||||
EnableOwnerTermination bool `json:"EnableOwnerTermination,omitempty"`
|
||||
// If set to true, the user has administrator rights in the integration. Some functionality of Collabora Online, such as update check and server audit are supposed to be shown to administrators only.
|
||||
IsAdminUser bool `json:"IsAdminUser"`
|
||||
// If set to true, some functionality of Collabora which is supposed to be shown to authenticated users only is hidden
|
||||
IsAnonymousUser bool `json:"IsAnonymousUser,omitempty"`
|
||||
|
||||
// JSON object that contains additional info about the user, namely the avatar image.
|
||||
//UserExtraInfo -> requires definition, currently not used
|
||||
@@ -135,10 +131,6 @@ func (cinfo *Collabora) SetProperties(props map[string]interface{}) {
|
||||
//UserPrivateInfo -> requires definition, currently not used
|
||||
case KeyWatermarkText:
|
||||
cinfo.WatermarkText = value.(string)
|
||||
case KeyIsAdminUser:
|
||||
cinfo.IsAdminUser = value.(bool)
|
||||
case KeyIsAnonymousUser:
|
||||
cinfo.IsAnonymousUser = value.(bool)
|
||||
|
||||
case KeyEnableShare:
|
||||
cinfo.EnableShare = value.(bool)
|
||||
|
||||
@@ -50,7 +50,6 @@ const (
|
||||
|
||||
KeyIsAnonymousUser = "IsAnonymousUser"
|
||||
KeyIsEduUser = "IsEduUser"
|
||||
KeyIsAdminUser = "IsAdminUser"
|
||||
KeyLicenseCheckForEditIsEnabled = "LicenseCheckForEditIsEnabled"
|
||||
KeyUserFriendlyName = "UserFriendlyName"
|
||||
KeyUserInfo = "UserInfo"
|
||||
|
||||
@@ -42,7 +42,7 @@ While the frontend service does not persist any data, it does cache information
|
||||
|
||||
A lot of user management is made via the standardized libregraph API. Depending on how the system is configured, there might be some user attributes that an OpenCloud instance admin can't change because of properties coming from an external LDAP server, or similar. This can be the case when the OpenCloud admin is not the LDAP admin. To ease life for admins, there are hints as capabilites telling the frontend which attributes are read-only to enable a different optical representation like being grayed out. To configure these hints, use the environment variable `FRONTEND_READONLY_USER_ATTRIBUTES`, which takes a comma separated list of attributes, see the envvar for supported values.
|
||||
|
||||
You can find more details regarding available attributes at the [libre-graph-api openapi-spec](https://github.com/opencloud-eu/libre-graph-api/blob/main/api/openapi-spec/v1.0.yaml) and on [docs.opencloud.eu](https://docs.opencloud.eu/swagger/libre-graph-api/).
|
||||
You can find more details regarding available attributes at the [libre-graph-api openapi-spec](https://github.com/owncloud/libre-graph-api/blob/main/api/openapi-spec/v1.0.yaml) and on [docs.opencloud.eu](https://docs.opencloud.eu/libre-graph-api/).
|
||||
|
||||
## Caching
|
||||
|
||||
@@ -77,7 +77,7 @@ In OpenCloud, the password policy is always enabled because the max-length restr
|
||||
|
||||
With the password policy, mandatory criteria for the password can be defined via the environment variables listed below.
|
||||
|
||||
Generally, a password can contain any UTF-8 characters, however some characters are regarded as special since they are not used in ordinary texts. Which characters should be treated as special is defined by "The OWASP® Foundation" [password-special-characters](https://owasp.org/www-community/password-special-characters) (between double quotes): ```" !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"```
|
||||
Generally, a password can contain any UTF-8 characters, however some characters are regarded as special since they are not used in ordinary texts. Which characters should be treated as special is defined by "The OWASP® Foundation" [password-special-characters](https://owasp.org/www-community/password-special-characters) (between double quotes): " !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
|
||||
|
||||
The validation against the banned passwords list can be configured via a text file with words separated by new lines. If a user tries to set a password listed in the banned passwords list, the password can not be used (is invalid) even if the other mandatory criteria are passed. The admin can define the path of the banned passwords list file. If the file doesn't exist in a location, OpenCloud tries to load a file from the `OC_CONFIG_DIR/OC_PASSWORD_POLICY_BANNED_PASSWORDS_LIST`. An option will be enabled when the file has been loaded successfully.
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ type Config struct {
|
||||
SearchMinLength int `yaml:"search_min_length" env:"FRONTEND_SEARCH_MIN_LENGTH" desc:"Minimum number of characters to enter before a client should start a search for Share receivers. This setting can be used to customize the user experience if e.g too many results are displayed." introductionVersion:"1.0.0"`
|
||||
Edition string `yaml:"edition" env:"OC_EDITION;FRONTEND_EDITION" desc:"Edition of OpenCloud. Used for branding purposes." introductionVersion:"1.0.0"`
|
||||
DisableSSE bool `yaml:"disable_sse" env:"OC_DISABLE_SSE;FRONTEND_DISABLE_SSE" desc:"When set to true, clients are informed that the Server-Sent Events endpoint is not accessible." introductionVersion:"1.0.0"`
|
||||
DisableRadicale bool `yaml:"disable_radicale" env:"FRONTEND_DISABLE_RADICALE" desc:"When set to true, clients are informed that the Radicale (CalDAV/CardDAV) is not accessible." introductionVersion:"4.0.0"`
|
||||
DefaultLinkPermissions int `yaml:"default_link_permissions" env:"FRONTEND_DEFAULT_LINK_PERMISSIONS" desc:"Defines the default permissions a link is being created with. Possible values are 0 (= internal link, for instance members only) and 1 (= public link with viewer permissions). Defaults to 1." introductionVersion:"1.0.0"`
|
||||
|
||||
PublicURL string `yaml:"public_url" env:"OC_URL;FRONTEND_PUBLIC_URL" desc:"The public facing URL of the OpenCloud frontend." introductionVersion:"1.0.0"`
|
||||
|
||||
@@ -218,7 +218,6 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string
|
||||
"check_for_updates": cfg.CheckForUpdates,
|
||||
"support_url_signing": true,
|
||||
"support_sse": !cfg.DisableSSE,
|
||||
"support_radicale": !cfg.DisableRadicale,
|
||||
},
|
||||
"graph": map[string]interface{}{
|
||||
"personal_data_export": true,
|
||||
|
||||
@@ -8,7 +8,7 @@ The gateway service is using caching as it is highly frequented with the same re
|
||||
- the `provider cache` is caching requests to list or get storage providers.
|
||||
- the `create home cache` is caching requests to create personal spaces (as they only need to be executed once).
|
||||
|
||||
Both caches can be configured via the `OC_CACHE_*` envvars (or `GATEWAY_PROVIDER_CACHE_*` and `GATEWAY_CREATE_HOME_CACHE_*` respectively).
|
||||
Both caches can be configured via the `OC_CACHE_*` envvars (or `GATEWAY_PROVIDER_CACHE_*` and `GATEWAY_CREATE_HOME_CACHE_*` respectively). See the [envvar section](/services/gateway/configuration/#environment-variables) for details.
|
||||
|
||||
Use `OC_CACHE_STORE` (`GATEWAY_PROVIDER_CACHE_STORE`, `GATEWAY_CREATE_HOME_CACHE_STORE`) to define the type of cache to use:
|
||||
- `memory`: Basic in-memory store and the default.
|
||||
@@ -40,9 +40,9 @@ The scheme for this setup is the following. Note that there is, except storage,
|
||||
|
||||
| **envvar** | **default** | **alternative** |
|
||||
|------|------|------|
|
||||
| OC_GRPC_PROTOCOL or <br /> `<service>`_GRPC_PROTOCOL | tcp | unix |
|
||||
| OC_GRPC_PROTOCOL or <br> `<service>`_GRPC_PROTOCOL | tcp | unix |
|
||||
| `<service>`_GRPC_ADDR | 127.0.0.1:`<port>` | /var/run/opencloud/`<service>`.sock |
|
||||
| GATEWAY_`<service>`_ENDPOINT | eu.opencloud.api.`<service>` | unix:/var/run/opencloud/`<service>`.sock <br /> dns: ... <br /> kubernetes: ... |
|
||||
| GATEWAY_`<service>`_ENDPOINT | eu.opencloud.api.`<service>` | unix:/var/run/opencloud/`<service>`.sock <br> dns: ... <br> kubernetes: ... |
|
||||
|
||||
```console
|
||||
USERS_GRPC_PROTOCOL=unix"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The graph service provides the Graph API which is a RESTful web API used to access OpenCloud
|
||||
resources. It is inspired by the [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/use-the-api)
|
||||
and can be used by clients or other services or extensions. Visit the [Libre Graph API](https://docs.opencloud.eu/swagger/libre-graph-api/)
|
||||
and can be used by clients or other services or extensions. Visit the [Libre Graph API](https://docs.opencloud.eu/libre-graph-api/)
|
||||
for a detailed specification of the API implemented by the graph service.
|
||||
|
||||
## Sequence Diagram
|
||||
@@ -24,7 +24,7 @@ The graph service provides endpoints for querying users and groups. It features
|
||||
### LDAP Configuration
|
||||
|
||||
The LDAP backend is configured using a set of environment variables. A detailed list of all the
|
||||
available configuration options can be found in the [documentation](https://docs.opencloud.eu/docs/dev/server/services/graph/environment-variables).
|
||||
available configuration options can be found in the [documentation](https://docs.opencloud.eu/services/graph/configuration/#environment-variables).
|
||||
The LDAP related options are prefixed with `OC_LDAP_` (or `GRAPH_LDAP_` for settings specific to graph service).
|
||||
|
||||
#### Read-Only Access to Existing LDAP Servers
|
||||
@@ -32,7 +32,8 @@ The LDAP related options are prefixed with `OC_LDAP_` (or `GRAPH_LDAP_` for sett
|
||||
To connect the graph service to an existing LDAP server, set `OC_LDAP_SERVER_WRITE_ENABLED` to
|
||||
`false` to prevent the graph service from sending write operations to the LDAP server. Also set the
|
||||
various `OC_LDAP_*` environment variables to match the configuration of the LDAP server you are connecting
|
||||
to. A more detailed explanation can be found [here](https://docs.opencloud.eu/docs/admin/configuration/authentication-and-user-management/.
|
||||
to. An example configuration for connecting OpenCloud to an instance of Microsoft Active Directory is
|
||||
available [here](https://docs.opencloud.eu/opencloud/identity-provider/ldap-active-directory/).
|
||||
|
||||
#### Using a Write Enabled LDAP Server
|
||||
|
||||
@@ -46,13 +47,13 @@ respect to the available schema:
|
||||
object class for groups.
|
||||
* The graph service maintains a few additional attributes for users and groups that are not
|
||||
available in the standard LDAP schema. An schema file, ready to use with OpenLDAP, defining those
|
||||
additional attributes is available [here](https://github.com/opencloud-eu/opencloud-compose/blob/main/config/ldap/schemas/10_opencloud_schema.ldif)
|
||||
additional attributes is available [here](https://github.com/opencloud-eu/opencloud/blob/main/deployments/examples/shared/config/ldap/schemas/10_opencloud_schema.ldif)
|
||||
|
||||
## Query Filters Provided by the Graph API
|
||||
|
||||
Some API endpoints provided by the graph service allow to specify query filters. The filter syntax
|
||||
is based on the [OData Specification](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter).
|
||||
See the [Libre Graph API](https://docs.opencloud.eu/swagger/libre-graph-api/#/users/ListUsers) for examples
|
||||
See the [Libre Graph API](https://docs.opencloud.eu/libre-graph-api/#/users/ListUsers) for examples
|
||||
on the filters supported when querying users.
|
||||
|
||||
## Caching
|
||||
@@ -65,6 +66,10 @@ The `graph` service can use a configured store via `GRAPH_CACHE_STORE`. Possible
|
||||
|
||||
Other store types may work but are not supported currently.
|
||||
|
||||
Note: The service can only be scaled if not using `memory` store and the stores are configured identically over all instances!
|
||||
|
||||
Note that if you have used one of the deprecated stores, you should reconfigure to one of the supported ones as the deprecated stores will be removed in a later version.
|
||||
|
||||
Store specific notes:
|
||||
- When using `redis-sentinel`, the Redis master to use is configured via e.g. `OC_CACHE_STORE_NODES` in the form of `<sentinel-host>:<sentinel-port>/<redis-master>` like `10.10.0.200:26379/mymaster`.
|
||||
- When using `nats-js-kv` it is recommended to set `OC_CACHE_STORE_NODES` to the same value as `OC_EVENTS_ENDPOINT`. That way the cache uses the same nats instance as the event bus.
|
||||
@@ -92,9 +97,7 @@ The client that is used to authenticate with keycloak has to be able to list use
|
||||
* `view-events`
|
||||
* `view-authorization`
|
||||
|
||||
:::note
|
||||
These roles are only available to assign if the client is in the `master` realm.
|
||||
:::
|
||||
Note that these roles are only available to assign if the client is in the `master` realm.
|
||||
|
||||
## Translations
|
||||
|
||||
@@ -110,9 +113,7 @@ For example, for the language `de`, one needs to place the corresponding transla
|
||||
|
||||
<!-- also see the notifications readme -->
|
||||
|
||||
:::warning
|
||||
For the time being, the embedded OpenCloud Web frontend only supports the main language code but does not handle any territory. When strings are available in the language code `language_territory`, the web frontend does not see it as it only requests `language`. In consequence, any translations made must exist in the requested `language` to avoid a fallback to the default.
|
||||
:::
|
||||
Important: For the time being, the embedded OpenCloud Web frontend only supports the main language code but does not handle any territory. When strings are available in the language code `language_territory`, the web frontend does not see it as it only requests `language`. In consequence, any translations made must exist in the requested `language` to avoid a fallback to the default.
|
||||
|
||||
### Translation Rules
|
||||
|
||||
@@ -128,9 +129,8 @@ The default language can be defined via the `OC_DEFAULT_LANGUAGE` environment va
|
||||
|
||||
Unified Roles are roles granted a user for sharing and can be enabled or disabled. A CLI command is provided to list existing roles and their state among other data.
|
||||
|
||||
:::info
|
||||
::: info
|
||||
Note that a disabled role does not lose previously assigned permissions. It only means that the role is not available for new assignments.
|
||||
:::
|
||||
|
||||
The following roles are **enabled** by default:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cache
|
||||
package identity
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
revautils "github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
)
|
||||
@@ -86,38 +85,33 @@ func NewIdentityCache(opts ...IdentityCacheOption) IdentityCache {
|
||||
}
|
||||
|
||||
// GetUser looks up a user by id, if the user is not cached, yet it will do a lookup via the CS3 API
|
||||
func (cache IdentityCache) GetUser(ctx context.Context, tenantId, userid string) (libregraph.User, error) {
|
||||
// can we get the tenant from the context or do we have to pass it?
|
||||
u, err := cache.GetCS3User(ctx, tenantId, userid)
|
||||
func (cache IdentityCache) GetUser(ctx context.Context, userid string) (libregraph.User, error) {
|
||||
u, err := cache.GetCS3User(ctx, userid)
|
||||
if err != nil {
|
||||
return libregraph.User{}, err
|
||||
}
|
||||
if tenantId != u.GetId().GetTenantId() {
|
||||
return libregraph.User{}, identity.ErrNotFound
|
||||
}
|
||||
return *identity.CreateUserModelFromCS3(u), nil
|
||||
return *CreateUserModelFromCS3(u), nil
|
||||
}
|
||||
|
||||
func (cache IdentityCache) GetCS3User(ctx context.Context, tenantId, userid string) (*cs3User.User, error) {
|
||||
func (cache IdentityCache) GetCS3User(ctx context.Context, userid string) (*cs3User.User, error) {
|
||||
var user *cs3User.User
|
||||
if item := cache.users.Get(tenantId + "|" + userid); item == nil {
|
||||
if item := cache.users.Get(userid); item == nil {
|
||||
gatewayClient, err := cache.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
return nil, errorcode.New(errorcode.GeneralException, err.Error())
|
||||
}
|
||||
cs3UserID := &cs3User.UserId{
|
||||
OpaqueId: userid,
|
||||
TenantId: tenantId,
|
||||
}
|
||||
user, err = revautils.GetUserNoGroups(ctx, cs3UserID, gatewayClient)
|
||||
if err != nil {
|
||||
if revautils.IsErrNotFound(err) {
|
||||
return nil, identity.ErrNotFound
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return nil, errorcode.New(errorcode.GeneralException, err.Error())
|
||||
}
|
||||
cache.users.Set(userid, user, ttlcache.DefaultTTL)
|
||||
|
||||
cache.users.Set(tenantId+"|"+userid, user, ttlcache.DefaultTTL)
|
||||
} else {
|
||||
user = item.Value()
|
||||
}
|
||||
@@ -130,7 +124,7 @@ func (cache IdentityCache) GetAcceptedUser(ctx context.Context, userid string) (
|
||||
if err != nil {
|
||||
return libregraph.User{}, err
|
||||
}
|
||||
return *identity.CreateUserModelFromCS3(u), nil
|
||||
return *CreateUserModelFromCS3(u), nil
|
||||
}
|
||||
|
||||
func (cache IdentityCache) GetAcceptedCS3User(ctx context.Context, userid string) (*cs3User.User, error) {
|
||||
@@ -146,7 +140,7 @@ func (cache IdentityCache) GetAcceptedCS3User(ctx context.Context, userid string
|
||||
user, err = revautils.GetAcceptedUserWithContext(ctx, cs3UserID, gatewayClient)
|
||||
if err != nil {
|
||||
if revautils.IsErrNotFound(err) {
|
||||
return nil, identity.ErrNotFound
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return nil, errorcode.New(errorcode.GeneralException, err.Error())
|
||||
}
|
||||
@@ -179,10 +173,10 @@ func (cache IdentityCache) GetGroup(ctx context.Context, groupID string) (libreg
|
||||
switch res.Status.Code {
|
||||
case rpc.Code_CODE_OK:
|
||||
g := res.GetGroup()
|
||||
group = *identity.CreateGroupModelFromCS3(g)
|
||||
group = *CreateGroupModelFromCS3(g)
|
||||
cache.groups.Set(groupID, group, ttlcache.DefaultTTL)
|
||||
case rpc.Code_CODE_NOT_FOUND:
|
||||
return group, identity.ErrNotFound
|
||||
return group, ErrNotFound
|
||||
default:
|
||||
return group, errorcode.New(errorcode.GeneralException, res.Status.Message)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package cache_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Cache Suite")
|
||||
}
|
||||
106
services/graph/pkg/identity/cache/cache_test.go
vendored
106
services/graph/pkg/identity/cache/cache_test.go
vendored
@@ -1,106 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
cs3User "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
)
|
||||
|
||||
// mockGatewaySelector is a mock implementation of pool.Selectable[gateway.GatewayAPIClient]
|
||||
type mockGatewaySelector struct {
|
||||
client gateway.GatewayAPIClient
|
||||
}
|
||||
|
||||
func (m *mockGatewaySelector) Next(opts ...pool.Option) (gateway.GatewayAPIClient, error) {
|
||||
return m.client, nil
|
||||
}
|
||||
|
||||
var _ = Describe("Cache", func() {
|
||||
var (
|
||||
ctx context.Context
|
||||
idc IdentityCache
|
||||
mockGwSelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a mock gateway selector (client can be nil for cached tests)
|
||||
mockGwSelector = &mockGatewaySelector{
|
||||
client: nil,
|
||||
}
|
||||
|
||||
idc = NewIdentityCache(
|
||||
IdentityCacheWithGatewaySelector(mockGwSelector),
|
||||
)
|
||||
ctx = context.Background()
|
||||
})
|
||||
|
||||
Describe("GetUser", func() {
|
||||
It("should return no error", func() {
|
||||
alan := &cs3User.User{
|
||||
Id: &cs3User.UserId{
|
||||
OpaqueId: "alan",
|
||||
TenantId: "",
|
||||
},
|
||||
DisplayName: "Alan",
|
||||
}
|
||||
// Persist the user to the cache for 1 hour
|
||||
idc.users.Set(alan.GetId().GetTenantId()+"|"+alan.GetId().GetOpaqueId(), alan, time.Hour)
|
||||
|
||||
// getting the cache item in cache.go line 103 does not work
|
||||
ru, err := idc.GetUser(ctx, "", "alan")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(ru).ToNot(BeNil())
|
||||
Expect(ru.GetId()).To(Equal(alan.GetId().GetOpaqueId()))
|
||||
Expect(ru.GetDisplayName()).To(Equal(alan.GetDisplayName()))
|
||||
})
|
||||
|
||||
It("should return the correct user if two users with the same uid and different tennant ids exist", func() {
|
||||
alan1 := &cs3User.User{
|
||||
Id: &cs3User.UserId{
|
||||
OpaqueId: "alan",
|
||||
TenantId: "1234",
|
||||
},
|
||||
DisplayName: "Alan1",
|
||||
}
|
||||
|
||||
alan2 := &cs3User.User{
|
||||
Id: &cs3User.UserId{
|
||||
OpaqueId: "alan",
|
||||
TenantId: "5678",
|
||||
},
|
||||
DisplayName: "Alan2",
|
||||
}
|
||||
// Persist the user to the cache for 1 hour
|
||||
idc.users.Set(alan1.GetId().GetTenantId()+"|"+alan1.GetId().GetOpaqueId(), alan1, time.Hour)
|
||||
idc.users.Set(alan2.GetId().GetTenantId()+"|"+alan2.GetId().GetOpaqueId(), alan2, time.Hour)
|
||||
ru, err := idc.GetUser(ctx, "5678", "alan")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(ru.GetDisplayName()).To(Equal(alan2.GetDisplayName()))
|
||||
ru, err = idc.GetUser(ctx, "1234", "alan")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(ru.GetDisplayName()).To(Equal(alan1.GetDisplayName()))
|
||||
})
|
||||
|
||||
It("should not return an error, if the tenant id does match", func() {
|
||||
alan := &cs3User.User{
|
||||
Id: &cs3User.UserId{
|
||||
OpaqueId: "alan",
|
||||
TenantId: "1234",
|
||||
},
|
||||
DisplayName: "Alan",
|
||||
}
|
||||
// Persist the user to the cache for 1 hour
|
||||
cu := idc.users.Set(alan.GetId().GetTenantId()+"|"+alan.GetId().GetOpaqueId(), alan, time.Hour)
|
||||
// Test if element has been persisted in the cache
|
||||
Expect(cu.Value().GetId().GetOpaqueId()).To(Equal(alan.GetId().GetOpaqueId()))
|
||||
ru, err := idc.GetUser(ctx, "1234", "alan")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(ru.GetDisplayName()).To(Equal(alan.GetDisplayName()))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -497,7 +497,7 @@ func (i *LDAP) searchLDAPEntryByFilter(basedn string, attrs []string, filter str
|
||||
return res.Entries[0], nil
|
||||
}
|
||||
|
||||
func filterEscapeAttribute(attribute string, binary bool, id string) (string, error) {
|
||||
func filterEscapeUUID(binary bool, id string) (string, error) {
|
||||
var escaped string
|
||||
if binary {
|
||||
pid, err := uuid.Parse(id)
|
||||
@@ -505,44 +505,17 @@ func filterEscapeAttribute(attribute string, binary bool, id string) (string, er
|
||||
err := fmt.Errorf("error parsing id '%s' as UUID: %w", id, err)
|
||||
return "", err
|
||||
}
|
||||
escaped = filterEscapeBinaryUUID(attribute, pid)
|
||||
for _, b := range pid {
|
||||
escaped = fmt.Sprintf("%s\\%02x", escaped, b)
|
||||
}
|
||||
} else {
|
||||
escaped = ldap.EscapeFilter(id)
|
||||
}
|
||||
return escaped, nil
|
||||
}
|
||||
|
||||
// swapObjectGUIDBytes converts between AD's mixed-endian objectGUID format and standard UUID byte order
|
||||
func swapObjectGUIDBytes(value []byte) []byte {
|
||||
if len(value) != 16 {
|
||||
return value
|
||||
}
|
||||
return []byte{
|
||||
value[3], value[2], value[1], value[0], // First component (4 bytes) - reverse
|
||||
value[5], value[4], // Second component (2 bytes) - reverse
|
||||
value[7], value[6], // Third component (2 bytes) - reverse
|
||||
value[8], value[9], value[10], value[11], value[12], value[13], value[14], value[15], // Last 8 bytes - keep as-is
|
||||
}
|
||||
}
|
||||
|
||||
func filterEscapeBinaryUUID(attribute string, value uuid.UUID) string {
|
||||
bytes := value[:]
|
||||
|
||||
// AD stores objectGUID with mixed endianness 🤪 - swap first 3 components
|
||||
if strings.EqualFold(attribute, "objectguid") {
|
||||
bytes = swapObjectGUIDBytes(bytes)
|
||||
}
|
||||
|
||||
var filtered strings.Builder
|
||||
filtered.Grow(len(bytes) * 3) // Pre-allocate: each byte becomes "\xx"
|
||||
for _, b := range bytes {
|
||||
fmt.Fprintf(&filtered, "\\%02x", b)
|
||||
}
|
||||
return filtered.String()
|
||||
}
|
||||
|
||||
func (i *LDAP) getLDAPUserByID(id string) (*ldap.Entry, error) {
|
||||
idString, err := filterEscapeAttribute(i.userAttributeMap.id, i.userIDisOctetString, id)
|
||||
idString, err := filterEscapeUUID(i.userIDisOctetString, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid User id: %w", err)
|
||||
}
|
||||
@@ -551,7 +524,7 @@ func (i *LDAP) getLDAPUserByID(id string) (*ldap.Entry, error) {
|
||||
}
|
||||
|
||||
func (i *LDAP) getLDAPUserByNameOrID(nameOrID string) (*ldap.Entry, error) {
|
||||
idString, err := filterEscapeAttribute(i.userAttributeMap.id, i.userIDisOctetString, nameOrID)
|
||||
idString, err := filterEscapeUUID(i.userIDisOctetString, nameOrID)
|
||||
// err != nil just means that this is not an uuid, so we can skip the uuid filter part
|
||||
// and just filter by name
|
||||
var filter string
|
||||
@@ -839,25 +812,16 @@ func (i *LDAP) updateUserPassword(ctx context.Context, dn, password string) erro
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *LDAP) ldapUUIDtoString(e *ldap.Entry, attribute string, binary bool) (string, error) {
|
||||
func (i *LDAP) ldapUUIDtoString(e *ldap.Entry, attrType string, binary bool) (string, error) {
|
||||
if binary {
|
||||
value := e.GetEqualFoldRawAttributeValue(attribute)
|
||||
|
||||
if len(value) != 16 {
|
||||
return "", fmt.Errorf("invalid UUID in '%s' attribute (got %d bytes)", attribute, len(value))
|
||||
rawValue := e.GetEqualFoldRawAttributeValue(attrType)
|
||||
value, err := uuid.FromBytes(rawValue)
|
||||
if err == nil {
|
||||
return value.String(), nil
|
||||
}
|
||||
|
||||
// AD stores objectGUID with mixed endianness 🤪 - swap first 3 components
|
||||
if strings.EqualFold(attribute, "objectguid") {
|
||||
value = swapObjectGUIDBytes(value)
|
||||
}
|
||||
id, err := uuid.FromBytes(value)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing UUID from '%s' attribute bytes: %w", attribute, err)
|
||||
}
|
||||
return id.String(), nil
|
||||
return "", err
|
||||
}
|
||||
return e.GetEqualFoldAttributeValue(attribute), nil
|
||||
return e.GetEqualFoldAttributeValue(attrType), nil
|
||||
}
|
||||
|
||||
func (i *LDAP) createUserModelFromLDAP(e *ldap.Entry) *libregraph.User {
|
||||
@@ -912,7 +876,7 @@ func (i *LDAP) createUserModelFromLDAP(e *ldap.Entry) *libregraph.User {
|
||||
}
|
||||
return user
|
||||
}
|
||||
i.logger.Warn().Str("dn", e.DN).Str("id", id).Str("username", opsan).Msg("Invalid User. Missing username or id attribute")
|
||||
i.logger.Warn().Str("dn", e.DN).Msg("Invalid User. Missing username or id attribute")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gofrs/uuid"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/config"
|
||||
@@ -148,7 +148,7 @@ func (i *LDAP) CreateEducationSchool(ctx context.Context, school libregraph.Educ
|
||||
ar.Attribute(i.educationConfig.schoolAttributeMap.schoolNumber, []string{school.GetSchoolNumber()})
|
||||
}
|
||||
if !i.useServerUUID {
|
||||
ar.Attribute(i.educationConfig.schoolAttributeMap.id, []string{uuid.NewString()})
|
||||
ar.Attribute(i.educationConfig.schoolAttributeMap.id, []string{uuid.Must(uuid.NewV4()).String()})
|
||||
}
|
||||
objectClasses := []string{"organizationalUnit", i.educationConfig.schoolObjectClass, "top"}
|
||||
ar.Attribute("objectClass", objectClasses)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/CiscoM31/godata"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/libregraph/idm/pkg/ldapdn"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
|
||||
@@ -448,14 +448,14 @@ func (i *LDAP) groupToLDAPAttrValues(group libregraph.Group) (map[string][]strin
|
||||
}
|
||||
|
||||
if !i.useServerUUID {
|
||||
attrs["openCloudUUID"] = []string{uuid.NewString()}
|
||||
attrs["openCloudUUID"] = []string{uuid.Must(uuid.NewV4()).String()}
|
||||
attrs["objectClass"] = append(attrs["objectClass"], "openCloudObject")
|
||||
}
|
||||
return attrs, nil
|
||||
}
|
||||
|
||||
func (i *LDAP) getLDAPGroupByID(id string, requestMembers bool) (*ldap.Entry, error) {
|
||||
idString, err := filterEscapeAttribute(i.groupAttributeMap.id, i.groupIDisOctetString, id)
|
||||
idString, err := filterEscapeUUID(i.groupIDisOctetString, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid group id: %w", err)
|
||||
}
|
||||
@@ -464,7 +464,7 @@ func (i *LDAP) getLDAPGroupByID(id string, requestMembers bool) (*ldap.Entry, er
|
||||
}
|
||||
|
||||
func (i *LDAP) getLDAPGroupByNameOrID(nameOrID string, requestMembers bool) (*ldap.Entry, error) {
|
||||
idString, err := filterEscapeAttribute(i.groupAttributeMap.id, i.groupIDisOctetString, nameOrID)
|
||||
idString, err := filterEscapeUUID(i.groupIDisOctetString, nameOrID)
|
||||
// err != nil just means that this is not an uuid, so we can skip the uuid filter part
|
||||
// and just filter by name
|
||||
filter := ""
|
||||
|
||||
@@ -2,7 +2,6 @@ package identity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -10,10 +9,10 @@ import (
|
||||
|
||||
"github.com/CiscoM31/godata"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/config"
|
||||
"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"
|
||||
)
|
||||
@@ -64,33 +63,6 @@ var userEntry = ldap.NewEntry("uid=user",
|
||||
"usertypeattribute": {"Member"},
|
||||
})
|
||||
|
||||
var lconfigAD = config.LDAP{
|
||||
UserBaseDN: "ou=users,dc=test",
|
||||
UserObjectClass: "user",
|
||||
UserSearchScope: "sub",
|
||||
UserFilter: "",
|
||||
UserDisplayNameAttribute: "displayname",
|
||||
UserIDAttribute: "objectGUID",
|
||||
UserIDIsOctetString: true,
|
||||
UserEmailAttribute: "mail",
|
||||
UserNameAttribute: "uid",
|
||||
UserEnabledAttribute: "userEnabledAttribute",
|
||||
UserTypeAttribute: "userTypeAttribute",
|
||||
LdapDisabledUsersGroupDN: disableUsersGroup,
|
||||
DisableUserMechanism: "attribute",
|
||||
|
||||
GroupBaseDN: "ou=groups,dc=test",
|
||||
GroupObjectClass: "group",
|
||||
GroupSearchScope: "sub",
|
||||
GroupFilter: "",
|
||||
GroupNameAttribute: "cn",
|
||||
GroupMemberAttribute: "member",
|
||||
GroupIDAttribute: "objectGUID",
|
||||
GroupIDIsOctetString: true,
|
||||
|
||||
WriteEnabled: true,
|
||||
}
|
||||
|
||||
var invalidUserEntry = ldap.NewEntry("uid=user",
|
||||
map[string][]string{
|
||||
"uid": {"invalid"},
|
||||
@@ -288,50 +260,6 @@ func TestGetUser(t *testing.T) {
|
||||
assert.ErrorContains(t, err, "itemNotFound:")
|
||||
}
|
||||
|
||||
func TestGetUserAD(t *testing.T) {
|
||||
|
||||
// we have to simulate ldap / AD returning a binary encoded objectguid
|
||||
byteID, err := base64.StdEncoding.DecodeString("js8n0m6YBUqIYK8ZMFYnig==")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
userEntryAD := ldap.NewEntry("uid=user",
|
||||
map[string][]string{
|
||||
"uid": {"user"},
|
||||
"displayname": {"DisplayName"},
|
||||
"mail": {"user@example"},
|
||||
"objectguid": {string(byteID)}, // ugly but works
|
||||
"sn": {"surname"},
|
||||
"givenname": {"givenName"},
|
||||
"userenabledattribute": {"TRUE"},
|
||||
"usertypeattribute": {"Member"},
|
||||
})
|
||||
|
||||
// Mock a valid Search Result
|
||||
lm := &mocks.Client{}
|
||||
lm.On("Search", mock.Anything).
|
||||
Return(
|
||||
&ldap.SearchResult{
|
||||
Entries: []*ldap.Entry{userEntryAD},
|
||||
},
|
||||
nil)
|
||||
|
||||
odataReqDefault, err := godata.ParseRequest(context.Background(), "",
|
||||
url.Values{})
|
||||
if err != nil {
|
||||
t.Errorf("Expected success got '%s'", err.Error())
|
||||
}
|
||||
|
||||
b, _ := getMockedBackend(lm, lconfigAD, &logger)
|
||||
u, err := b.GetUser(context.Background(), "user", odataReqDefault)
|
||||
if err != nil {
|
||||
t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
|
||||
} else if *u.Id != "d227cf8e-986e-4a05-8860-af193056278a" { // this checks if we decoded the objectguid correctly
|
||||
t.Errorf("Expected GetUser to return a valid user")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetUsers(t *testing.T) {
|
||||
// Mock a Sizelimit Error
|
||||
lm := &mocks.Client{}
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-26 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole EditorListGrants, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditorListGrants, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:116 pkg/unifiedrole/roles.go:122
|
||||
#: pkg/unifiedrole/roles.go:128 pkg/unifiedrole/roles.go:140
|
||||
#: pkg/unifiedrole/roles.go:146
|
||||
msgid "Can edit"
|
||||
msgstr "Voi muokata"
|
||||
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:134
|
||||
msgid "Can edit without versions"
|
||||
msgstr "Voi muokata ilman versioita"
|
||||
|
||||
#. UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:158
|
||||
msgid "Can manage"
|
||||
msgstr "Voi hallita"
|
||||
|
||||
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:152
|
||||
msgid "Can upload"
|
||||
msgstr "Voi lähettää"
|
||||
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:98 pkg/unifiedrole/roles.go:104
|
||||
#: pkg/unifiedrole/roles.go:110
|
||||
msgid "Can view"
|
||||
msgstr "Voi nähdä"
|
||||
|
||||
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:164
|
||||
msgid "Can view (secure)"
|
||||
msgstr "Voi nähdä (turvallinen)"
|
||||
|
||||
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:170
|
||||
msgid "Cannot access"
|
||||
msgstr "Ei pääsyä"
|
||||
|
||||
#. UnifiedRole FullDenial, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:167
|
||||
msgid "Deny all access."
|
||||
msgstr "Estä kaikki pääsy."
|
||||
|
||||
#. default description for new spaces
|
||||
#: pkg/service/v0/spacetemplates.go:32
|
||||
msgid "Here you can add a description for this Space."
|
||||
msgstr "Täällä voit lisätä kuvauksen avaruudelle."
|
||||
|
||||
#. UnifiedRole Viewer, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:95 pkg/unifiedrole/roles.go:107
|
||||
msgid "View and download."
|
||||
msgstr "Näytä ja lataa."
|
||||
|
||||
#. UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:161
|
||||
msgid "View only documents, images and PDFs. Watermarks will be applied."
|
||||
msgstr "Näytä vain asiakirjat, kuvat ja PDF:t. Vesileimat lisätään."
|
||||
|
||||
#. UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:137
|
||||
msgid "View, download and edit."
|
||||
msgstr "Näytä, lataa ja muokkaa."
|
||||
|
||||
#. UnifiedRole ViewerListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:101
|
||||
msgid "View, download and show all invited people."
|
||||
msgstr "Näytä, lataa ja näytä kaikki kutsutut henkilöt."
|
||||
|
||||
#. UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:149
|
||||
msgid "View, download and upload."
|
||||
msgstr "Näytä, lataa ja lähetä."
|
||||
|
||||
#. UnifiedRole FileEditorListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:143
|
||||
msgid "View, download, edit and show all invited people."
|
||||
msgstr "Näytä, lataa, muokkaa ja näytä kaikki kaikki kutsutut henkilöt."
|
||||
|
||||
#. UnifiedRole Editor, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role Description (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:113 pkg/unifiedrole/roles.go:131
|
||||
msgid "View, download, upload, edit, add and delete."
|
||||
msgstr "Näytä, lataa lähetä, muokkaa, lisää ja poista."
|
||||
|
||||
#. UnifiedRole Manager, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:155
|
||||
msgid "View, download, upload, edit, add, delete and manage members."
|
||||
msgstr "Näytä, lataa, lähetä, muokkaa, lisää, poista ja hallitse jäseniä."
|
||||
|
||||
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:119
|
||||
msgid "View, download, upload, edit, add, delete and show all invited people."
|
||||
msgstr ""
|
||||
"Näytä, lataa, lähetä, muokkaa, lisää, poista ja näytä kaikki kutsutut "
|
||||
"henkilöt."
|
||||
|
||||
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:125
|
||||
msgid "View, download, upload, edit, add, delete including the history."
|
||||
msgstr "Näytä, lataa, lähetä, muokkaa, lisää, poista mukaan lukien historia."
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-15 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-26 00:00+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"
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# skrzat <skrzacikus@gmail.com>, 2025
|
||||
# Maksymilian Styżej, 2025
|
||||
# Xiaomi Box, 2025
|
||||
# Radoslaw Posim, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-15 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pl\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
|
||||
#. UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole EditorListGrants, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditorListGrants, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:116 pkg/unifiedrole/roles.go:122
|
||||
#: pkg/unifiedrole/roles.go:128 pkg/unifiedrole/roles.go:140
|
||||
#: pkg/unifiedrole/roles.go:146
|
||||
msgid "Can edit"
|
||||
msgstr "Może edytować"
|
||||
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:134
|
||||
msgid "Can edit without versions"
|
||||
msgstr ""
|
||||
|
||||
#. UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:158
|
||||
msgid "Can manage"
|
||||
msgstr "Może zarządzać"
|
||||
|
||||
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:152
|
||||
msgid "Can upload"
|
||||
msgstr "Może przesyłać pliki"
|
||||
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:98 pkg/unifiedrole/roles.go:104
|
||||
#: pkg/unifiedrole/roles.go:110
|
||||
msgid "Can view"
|
||||
msgstr "Może oglądać"
|
||||
|
||||
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:164
|
||||
msgid "Can view (secure)"
|
||||
msgstr "Mogę zobaczyć ( źródło) "
|
||||
|
||||
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:170
|
||||
msgid "Cannot access"
|
||||
msgstr "Nie ma dostępu"
|
||||
|
||||
#. UnifiedRole FullDenial, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:167
|
||||
msgid "Deny all access."
|
||||
msgstr "Odmów dostępu wszystkim."
|
||||
|
||||
#. default description for new spaces
|
||||
#: pkg/service/v0/spacetemplates.go:32
|
||||
msgid "Here you can add a description for this Space."
|
||||
msgstr "Tutaj możesz dodać opis dla tej Przestrzeni"
|
||||
|
||||
#. UnifiedRole Viewer, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:95 pkg/unifiedrole/roles.go:107
|
||||
msgid "View and download."
|
||||
msgstr "Zobacz i pobierz"
|
||||
|
||||
#. UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:161
|
||||
msgid "View only documents, images and PDFs. Watermarks will be applied."
|
||||
msgstr ""
|
||||
|
||||
#. UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:137
|
||||
msgid "View, download and edit."
|
||||
msgstr "Wyświetl , Pobierz i edytuj "
|
||||
|
||||
#. UnifiedRole ViewerListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:101
|
||||
msgid "View, download and show all invited people."
|
||||
msgstr ""
|
||||
|
||||
#. UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:149
|
||||
msgid "View, download and upload."
|
||||
msgstr "Wyświetlanie, pobieranie i przesyłanie."
|
||||
|
||||
#. UnifiedRole FileEditorListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:143
|
||||
msgid "View, download, edit and show all invited people."
|
||||
msgstr ""
|
||||
|
||||
#. UnifiedRole Editor, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role Description (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:113 pkg/unifiedrole/roles.go:131
|
||||
msgid "View, download, upload, edit, add and delete."
|
||||
msgstr "Wyświetlanie, pobieranie, przesyłanie, edycja, dodawanie i usuwanie."
|
||||
|
||||
#. UnifiedRole Manager, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:155
|
||||
msgid "View, download, upload, edit, add, delete and manage members."
|
||||
msgstr ""
|
||||
"Wyświetlanie, pobieranie, przesyłanie, edycja, dodawanie, usuwanie i "
|
||||
"zarządzanie członkami."
|
||||
|
||||
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:119
|
||||
msgid "View, download, upload, edit, add, delete and show all invited people."
|
||||
msgstr ""
|
||||
"Wyświetlanie, pobieranie, przesyłanie, edycja, dodawanie, usuwanie i "
|
||||
"wyświetlanie wszystkich zaproszonych osób."
|
||||
|
||||
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:125
|
||||
msgid "View, download, upload, edit, add, delete including the history."
|
||||
msgstr ""
|
||||
"Wyświetlanie, pobieranie, przesyłanie, edycja, dodawanie, usuwanie włącznie "
|
||||
"z historią."
|
||||
@@ -1,139 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Mário Machado, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-17 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#. UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole EditorListGrants, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditorListGrants, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:116 pkg/unifiedrole/roles.go:122
|
||||
#: pkg/unifiedrole/roles.go:128 pkg/unifiedrole/roles.go:140
|
||||
#: pkg/unifiedrole/roles.go:146
|
||||
msgid "Can edit"
|
||||
msgstr "Pode editar"
|
||||
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:134
|
||||
msgid "Can edit without versions"
|
||||
msgstr "Pode editar sem versões"
|
||||
|
||||
#. UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:158
|
||||
msgid "Can manage"
|
||||
msgstr "Pode gerir"
|
||||
|
||||
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:152
|
||||
msgid "Can upload"
|
||||
msgstr "Pode carregar"
|
||||
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:98 pkg/unifiedrole/roles.go:104
|
||||
#: pkg/unifiedrole/roles.go:110
|
||||
msgid "Can view"
|
||||
msgstr "Pode visualizar"
|
||||
|
||||
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:164
|
||||
msgid "Can view (secure)"
|
||||
msgstr "Pode visualizar (seguro)"
|
||||
|
||||
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:170
|
||||
msgid "Cannot access"
|
||||
msgstr "Não pode aceder"
|
||||
|
||||
#. UnifiedRole FullDenial, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:167
|
||||
msgid "Deny all access."
|
||||
msgstr "Negar todo o acesso."
|
||||
|
||||
#. default description for new spaces
|
||||
#: pkg/service/v0/spacetemplates.go:32
|
||||
msgid "Here you can add a description for this Space."
|
||||
msgstr "Aqui pode adicionar uma descrição para este Espaço."
|
||||
|
||||
#. UnifiedRole Viewer, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:95 pkg/unifiedrole/roles.go:107
|
||||
msgid "View and download."
|
||||
msgstr "Visualizar e descarregar."
|
||||
|
||||
#. UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:161
|
||||
msgid "View only documents, images and PDFs. Watermarks will be applied."
|
||||
msgstr ""
|
||||
"Visualizar apenas documentos, imagens e PDFs. Serão aplicadas marcas de "
|
||||
"água."
|
||||
|
||||
#. UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:137
|
||||
msgid "View, download and edit."
|
||||
msgstr "Visualizar, descarregar e editar."
|
||||
|
||||
#. UnifiedRole ViewerListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:101
|
||||
msgid "View, download and show all invited people."
|
||||
msgstr "Visualizar, descarregar e mostrar todas as pessoas convidadas."
|
||||
|
||||
#. UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:149
|
||||
msgid "View, download and upload."
|
||||
msgstr "Visualizar, descarregar e carregar."
|
||||
|
||||
#. UnifiedRole FileEditorListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:143
|
||||
msgid "View, download, edit and show all invited people."
|
||||
msgstr ""
|
||||
"Visualizar, descarregar, editar e mostrar todas as pessoas convidadas."
|
||||
|
||||
#. UnifiedRole Editor, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role Description (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:113 pkg/unifiedrole/roles.go:131
|
||||
msgid "View, download, upload, edit, add and delete."
|
||||
msgstr "Visualizar, descarregar, carregar, editar, adicionar e eliminar."
|
||||
|
||||
#. UnifiedRole Manager, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:155
|
||||
msgid "View, download, upload, edit, add, delete and manage members."
|
||||
msgstr ""
|
||||
"Visualizar, descarregar, carregar, editar, adicionar, eliminar e gerir "
|
||||
"membros."
|
||||
|
||||
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:119
|
||||
msgid "View, download, upload, edit, add, delete and show all invited people."
|
||||
msgstr ""
|
||||
"Visualizar, descarregar, carregar, editar, adicionar, eliminar e mostrar "
|
||||
"todas as pessoas convidadas."
|
||||
|
||||
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:125
|
||||
msgid "View, download, upload, edit, add, delete including the history."
|
||||
msgstr ""
|
||||
"Visualizar, descarregar, carregar, editar, adicionar, eliminar, incluindo o "
|
||||
"histórico."
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-21 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-11-01 00:02+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"
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Daniel Nylander <po@danielnylander.se>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-08 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sv\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole EditorListGrants, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole FileEditorListGrants, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:116 pkg/unifiedrole/roles.go:122
|
||||
#: pkg/unifiedrole/roles.go:128 pkg/unifiedrole/roles.go:140
|
||||
#: pkg/unifiedrole/roles.go:146
|
||||
msgid "Can edit"
|
||||
msgstr "Kan redigera"
|
||||
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:134
|
||||
msgid "Can edit without versions"
|
||||
msgstr "Kan redigera utan versioner"
|
||||
|
||||
#. UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:158
|
||||
msgid "Can manage"
|
||||
msgstr "Kan hantera"
|
||||
|
||||
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:152
|
||||
msgid "Can upload"
|
||||
msgstr "Kan skicka upp"
|
||||
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
#. UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:98 pkg/unifiedrole/roles.go:104
|
||||
#: pkg/unifiedrole/roles.go:110
|
||||
msgid "Can view"
|
||||
msgstr "Kan visa"
|
||||
|
||||
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:164
|
||||
msgid "Can view (secure)"
|
||||
msgstr "Kan visa (säkert)"
|
||||
|
||||
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:170
|
||||
msgid "Cannot access"
|
||||
msgstr "Kan inte komma åt"
|
||||
|
||||
#. UnifiedRole FullDenial, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:167
|
||||
msgid "Deny all access."
|
||||
msgstr "Neka all åtkomst."
|
||||
|
||||
#. default description for new spaces
|
||||
#: pkg/service/v0/spacetemplates.go:32
|
||||
msgid "Here you can add a description for this Space."
|
||||
msgstr "Här kan du lägga till en beskrivning av denna arbetsyta."
|
||||
|
||||
#. UnifiedRole Viewer, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:95 pkg/unifiedrole/roles.go:107
|
||||
msgid "View and download."
|
||||
msgstr "Visa och hämta ner."
|
||||
|
||||
#. UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:161
|
||||
msgid "View only documents, images and PDFs. Watermarks will be applied."
|
||||
msgstr ""
|
||||
"Visa endast dokument, bilder och PDF. Vattenstämplar kommer att tillämpas."
|
||||
|
||||
#. UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:137
|
||||
msgid "View, download and edit."
|
||||
msgstr "Visa, hämta ner och redigera."
|
||||
|
||||
#. UnifiedRole ViewerListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:101
|
||||
msgid "View, download and show all invited people."
|
||||
msgstr "Visa, hämta ner och visa alla inbjudna personer."
|
||||
|
||||
#. UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:149
|
||||
msgid "View, download and upload."
|
||||
msgstr "Visa. hämta ner och skicka upp."
|
||||
|
||||
#. UnifiedRole FileEditorListGrants, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:143
|
||||
msgid "View, download, edit and show all invited people."
|
||||
msgstr "Visa, hämta ner, redigera och visa alla inbjudna personer."
|
||||
|
||||
#. UnifiedRole Editor, Role Description (resolves directly)
|
||||
#. UnifiedRole SpaseEditorWithoutVersions, Role Description (resolves
|
||||
#. directly)
|
||||
#: pkg/unifiedrole/roles.go:113 pkg/unifiedrole/roles.go:131
|
||||
msgid "View, download, upload, edit, add and delete."
|
||||
msgstr "Visa, hämta ner, skicka upp, redigera, lägga till och ta bort."
|
||||
|
||||
#. UnifiedRole Manager, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:155
|
||||
msgid "View, download, upload, edit, add, delete and manage members."
|
||||
msgstr ""
|
||||
"Visa, hämta ner, skicka upp, redigera, lägga till, ta bort och hantera "
|
||||
"medlemmar."
|
||||
|
||||
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:119
|
||||
msgid "View, download, upload, edit, add, delete and show all invited people."
|
||||
msgstr ""
|
||||
"Visa, hämta ner, skicka upp, redigera, lägga till, ta bort och visa alla "
|
||||
"inbjudna personer."
|
||||
|
||||
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
#: pkg/unifiedrole/roles.go:125
|
||||
msgid "View, download, upload, edit, add, delete including the history."
|
||||
msgstr ""
|
||||
"Visa, hämta ner, skicka upp, redigera, lägga till, ta bort inklusive "
|
||||
"historiken."
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-26 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-16 08:04+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -38,7 +38,6 @@ import (
|
||||
"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"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/validate"
|
||||
)
|
||||
@@ -90,7 +89,7 @@ type ListPermissionsQueryOptions struct {
|
||||
}
|
||||
|
||||
// NewDriveItemPermissionsService creates a new DriveItemPermissionsService
|
||||
func NewDriveItemPermissionsService(logger log.Logger, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], identityCache cache.IdentityCache, config *config.Config) (DriveItemPermissionsService, error) {
|
||||
func NewDriveItemPermissionsService(logger log.Logger, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], identityCache identity.IdentityCache, config *config.Config) (DriveItemPermissionsService, error) {
|
||||
return DriveItemPermissionsService{
|
||||
BaseGraphService: BaseGraphService{
|
||||
logger: &log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemService").Logger()},
|
||||
@@ -104,7 +103,6 @@ func NewDriveItemPermissionsService(logger log.Logger, gatewaySelector pool.Sele
|
||||
|
||||
// Invite invites a user to a drive item.
|
||||
func (s DriveItemPermissionsService) Invite(ctx context.Context, resourceId *storageprovider.ResourceId, invite libregraph.DriveItemInvite) (libregraph.Permission, error) {
|
||||
tenantId := revactx.ContextMustGetUser(ctx).GetId().GetTenantId()
|
||||
gatewayClient, err := s.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
return libregraph.Permission{}, err
|
||||
@@ -186,7 +184,7 @@ func (s DriveItemPermissionsService) Invite(ctx context.Context, resourceId *sto
|
||||
cTime = createShareResponse.GetShare().GetCtime()
|
||||
expiration = createShareResponse.GetShare().GetExpiration()
|
||||
default:
|
||||
user, err := s.identityCache.GetCS3User(ctx, tenantId, objectID)
|
||||
user, err := s.identityCache.GetCS3User(ctx, objectID)
|
||||
if errors.Is(err, identity.ErrNotFound) && s.config.IncludeOCMSharees {
|
||||
user, err = s.identityCache.GetAcceptedCS3User(ctx, objectID)
|
||||
if err == nil && IsSpaceRoot(statResponse.GetInfo().GetId()) {
|
||||
@@ -261,14 +259,14 @@ func (s DriveItemPermissionsService) Invite(ctx context.Context, resourceId *sto
|
||||
}
|
||||
|
||||
if user, ok := revactx.ContextGetUser(ctx); ok {
|
||||
userIdentity, err := userIdToIdentity(ctx, s.identityCache, tenantId, user.GetId().GetOpaqueId())
|
||||
identity, err := userIdToIdentity(ctx, s.identityCache, user.GetId().GetOpaqueId())
|
||||
if err != nil {
|
||||
s.logger.Error().Err(err).Msg("identity lookup failed")
|
||||
return libregraph.Permission{}, errorcode.New(errorcode.InvalidRequest, err.Error())
|
||||
}
|
||||
permission.SetInvitation(libregraph.SharingInvitation{
|
||||
InvitedBy: &libregraph.IdentitySet{
|
||||
User: &userIdentity,
|
||||
User: &identity,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,18 +11,18 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/mocks"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/config/defaults"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/linktype"
|
||||
service "github.com/opencloud-eu/opencloud/services/graph/pkg/service/v0"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
cs3mocks "github.com/opencloud-eu/reva/v2/tests/cs3mocks/mocks"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ var _ = Describe("createLinkTests", func() {
|
||||
gatewaySelector = mocks.NewSelectable[gateway.GatewayAPIClient](GinkgoT())
|
||||
gatewaySelector.On("Next").Return(gatewayClient, nil)
|
||||
|
||||
cache := cache.NewIdentityCache(cache.IdentityCacheWithGatewaySelector(gatewaySelector))
|
||||
cache := identity.NewIdentityCache(identity.IdentityCacheWithGatewaySelector(gatewaySelector))
|
||||
|
||||
cfg := defaults.FullDefaultConfig()
|
||||
svc, err = service.NewDriveItemPermissionsService(logger, gatewaySelector, cache, cfg)
|
||||
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/services/graph/mocks"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/config/defaults"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
|
||||
identitycache "github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/linktype"
|
||||
svc "github.com/opencloud-eu/opencloud/services/graph/pkg/service/v0"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
||||
@@ -56,7 +56,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
OpaqueId: "user",
|
||||
},
|
||||
}
|
||||
cache identitycache.IdentityCache
|
||||
cache identity.IdentityCache
|
||||
statResponse *provider.StatResponse
|
||||
driveItemId *provider.ResourceId
|
||||
ctx context.Context
|
||||
@@ -70,7 +70,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
gatewaySelector = mocks.NewSelectable[gateway.GatewayAPIClient](GinkgoT())
|
||||
gatewaySelector.On("Next").Return(gatewayClient, nil)
|
||||
|
||||
cache = identitycache.NewIdentityCache(identitycache.IdentityCacheWithGatewaySelector(gatewaySelector))
|
||||
cache = identity.NewIdentityCache(identity.IdentityCacheWithGatewaySelector(gatewaySelector))
|
||||
|
||||
cfg = defaults.FullDefaultConfig()
|
||||
service, err := svc.NewDriveItemPermissionsService(logger, gatewaySelector, cache, cfg)
|
||||
@@ -139,7 +139,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
Expiration: utils.TimeToTS(*driveItemInvite.ExpirationDateTime),
|
||||
}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(permission.GetId()).To(Equal("123"))
|
||||
Expect(permission.GetExpirationDateTime().Equal(*driveItemInvite.ExpirationDateTime)).To(BeTrue())
|
||||
@@ -149,7 +149,6 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
|
||||
It("creates group shares as expected (happy path)", func() {
|
||||
gatewayClient.On("GetGroup", mock.Anything, mock.Anything).Return(getGroupResponse, nil)
|
||||
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
|
||||
gatewayClient.On("CreateShare", mock.Anything, mock.Anything).Return(createShareResponse, nil)
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("2"), LibreGraphRecipientType: libregraph.PtrString("group")},
|
||||
@@ -160,7 +159,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
Expiration: utils.TimeToTS(*driveItemInvite.ExpirationDateTime),
|
||||
}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(permission.GetId()).To(Equal("123"))
|
||||
Expect(permission.GetExpirationDateTime().Equal(*driveItemInvite.ExpirationDateTime)).To(BeTrue())
|
||||
@@ -176,7 +175,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleViewerID}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(permission.GetRoles()).To(HaveLen(1))
|
||||
@@ -192,7 +191,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleEditorID}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(permission.GetRoles()).To(HaveLen(1))
|
||||
@@ -204,7 +203,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleManagerID}
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
Expect(permission).To(BeZero())
|
||||
@@ -215,7 +214,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleEditorID}
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
Expect(permission).To(BeZero())
|
||||
@@ -227,7 +226,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleFileEditorID}
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
Expect(permission).To(BeZero())
|
||||
@@ -242,7 +241,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
driveItemInvite.Roles = nil
|
||||
driveItemInvite.LibreGraphPermissionsActions = []string{unifiedrole.DriveItemContentRead}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(permission).NotTo(BeZero())
|
||||
@@ -253,7 +252,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
|
||||
It("fails with a missing driveritem", func() {
|
||||
statResponse.Status = status.NewNotFound(context.Background(), "not found")
|
||||
permission, err := driveItemPermissionsService.Invite(ctx, driveItemId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.ItemNotFound, "not found").WithOrigin(errorcode.ErrorOriginCS3)))
|
||||
Expect(permission).To(BeZero())
|
||||
@@ -269,7 +268,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleViewerID, unifiedrole.UnifiedRoleSecureViewerID}
|
||||
_, err = service.Invite(ctx, driveItemId, driveItemInvite)
|
||||
_, err = service.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).To(MatchError(unifiedrole.ErrUnknownRole))
|
||||
})
|
||||
})
|
||||
@@ -337,7 +336,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
Expiration: utils.TimeToTS(*driveItemInvite.ExpirationDateTime),
|
||||
}
|
||||
|
||||
permission, err := driveItemPermissionsService.SpaceRootInvite(ctx, driveId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.SpaceRootInvite(context.Background(), driveId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(permission.GetId()).To(Equal("123"))
|
||||
Expect(permission.GetExpirationDateTime().Equal(*driveItemInvite.ExpirationDateTime)).To(BeTrue())
|
||||
@@ -355,7 +354,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
Expiration: utils.TimeToTS(*driveItemInvite.ExpirationDateTime),
|
||||
}
|
||||
|
||||
permission, err := driveItemPermissionsService.SpaceRootInvite(ctx, driveId, driveItemInvite)
|
||||
permission, err := driveItemPermissionsService.SpaceRootInvite(context.Background(), driveId, driveItemInvite)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "unsupported space type")))
|
||||
Expect(permission).To(BeZero())
|
||||
@@ -1062,7 +1061,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
SpaceId: "2",
|
||||
OpaqueId: "2",
|
||||
}
|
||||
res, err := driveItemPermissionsService.UpdatePermission(ctx, spaceId, "u:userid", driveItemPermission)
|
||||
res, err := driveItemPermissionsService.UpdatePermission(context.Background(), spaceId, "u:userid", driveItemPermission)
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
Expect(res).To(BeZero())
|
||||
})
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
|
||||
@@ -30,7 +29,6 @@ import (
|
||||
"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"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/linktype"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
@@ -46,7 +44,7 @@ type BaseGraphProvider interface {
|
||||
type BaseGraphService struct {
|
||||
logger *log.Logger
|
||||
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
identityCache cache.IdentityCache
|
||||
identityCache identity.IdentityCache
|
||||
config *config.Config
|
||||
availableRoles []*libregraph.UnifiedRoleDefinition
|
||||
}
|
||||
@@ -172,8 +170,7 @@ func (g BaseGraphService) cs3SpacePermissionsToLibreGraph(ctx context.Context, s
|
||||
}
|
||||
isGroup = true
|
||||
} else {
|
||||
tenantId := revactx.ContextMustGetUser(ctx).GetId().GetTenantId()
|
||||
cs3Identity, err = userIdToIdentity(ctx, g.identityCache, tenantId, tmp)
|
||||
cs3Identity, err = userIdToIdentity(ctx, g.identityCache, tmp)
|
||||
if err != nil {
|
||||
g.logger.Warn().Str("userid", tmp).Msg("User not found by id")
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
ldapv3 "github.com/go-ldap/ldap/v3"
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/riandyrn/otelchi"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
|
||||
@@ -148,10 +147,10 @@ func NewService(opts ...Option) (Graph, error) { //nolint:maintidx
|
||||
)
|
||||
go spacePropertiesCache.Start()
|
||||
|
||||
identityCache := cache.NewIdentityCache(
|
||||
cache.IdentityCacheWithGatewaySelector(options.GatewaySelector),
|
||||
cache.IdentityCacheWithUsersTTL(time.Duration(options.Config.Spaces.UsersCacheTTL)),
|
||||
cache.IdentityCacheWithGroupsTTL(time.Duration(options.Config.Spaces.GroupsCacheTTL)),
|
||||
identityCache := identity.NewIdentityCache(
|
||||
identity.IdentityCacheWithGatewaySelector(options.GatewaySelector),
|
||||
identity.IdentityCacheWithUsersTTL(time.Duration(options.Config.Spaces.UsersCacheTTL)),
|
||||
identity.IdentityCacheWithGroupsTTL(time.Duration(options.Config.Spaces.GroupsCacheTTL)),
|
||||
)
|
||||
|
||||
baseGraphService := BaseGraphService{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
@@ -92,11 +92,11 @@ func IsShareJail(id *storageprovider.ResourceId) bool {
|
||||
|
||||
// userIdToIdentity looks the user for the supplied id using the cache and returns it
|
||||
// as a libregraph.Identity
|
||||
func userIdToIdentity(ctx context.Context, cache cache.IdentityCache, tennantId, userID string) (libregraph.Identity, error) {
|
||||
func userIdToIdentity(ctx context.Context, cache identity.IdentityCache, userID string) (libregraph.Identity, error) {
|
||||
identity := libregraph.Identity{
|
||||
Id: libregraph.PtrString(userID),
|
||||
}
|
||||
user, err := cache.GetUser(ctx, tennantId, userID)
|
||||
user, err := cache.GetUser(ctx, userID)
|
||||
if err == nil {
|
||||
identity.SetDisplayName(user.GetDisplayName())
|
||||
identity.SetLibreGraphUserType(user.GetUserType())
|
||||
@@ -106,7 +106,7 @@ func userIdToIdentity(ctx context.Context, cache cache.IdentityCache, tennantId,
|
||||
|
||||
// federatedIdToIdentity looks the user for the supplied id using the cache and returns it
|
||||
// as a libregraph.Identity
|
||||
func federatedIdToIdentity(ctx context.Context, cache cache.IdentityCache, userID string) (libregraph.Identity, error) {
|
||||
func federatedIdToIdentity(ctx context.Context, cache identity.IdentityCache, userID string) (libregraph.Identity, error) {
|
||||
identity := libregraph.Identity{
|
||||
Id: libregraph.PtrString(userID),
|
||||
LibreGraphUserType: libregraph.PtrString("Federated"),
|
||||
@@ -121,19 +121,19 @@ func federatedIdToIdentity(ctx context.Context, cache cache.IdentityCache, userI
|
||||
|
||||
// cs3UserIdToIdentity looks up the user for the supplied cs3 userid using the cache and returns it
|
||||
// as a libregraph.Identity. Skips the user lookup if the id type is USER_TYPE_SPACE_OWNER
|
||||
func cs3UserIdToIdentity(ctx context.Context, cache cache.IdentityCache, cs3UserID *cs3User.UserId) (libregraph.Identity, error) {
|
||||
func cs3UserIdToIdentity(ctx context.Context, cache identity.IdentityCache, cs3UserID *cs3User.UserId) (libregraph.Identity, error) {
|
||||
if cs3UserID.GetType() == cs3User.UserType_USER_TYPE_FEDERATED {
|
||||
return federatedIdToIdentity(ctx, cache, cs3UserID.GetOpaqueId())
|
||||
}
|
||||
if cs3UserID.GetType() != cs3User.UserType_USER_TYPE_SPACE_OWNER {
|
||||
return userIdToIdentity(ctx, cache, cs3UserID.GetTenantId(), cs3UserID.GetOpaqueId())
|
||||
return userIdToIdentity(ctx, cache, cs3UserID.GetOpaqueId())
|
||||
}
|
||||
return libregraph.Identity{Id: libregraph.PtrString(cs3UserID.GetOpaqueId())}, nil
|
||||
}
|
||||
|
||||
// groupIdToIdentity looks up the group for the supplied cs3 groupid using the cache and returns it
|
||||
// as a libregraph.Identity.
|
||||
func groupIdToIdentity(ctx context.Context, cache cache.IdentityCache, groupID string) (libregraph.Identity, error) {
|
||||
func groupIdToIdentity(ctx context.Context, cache identity.IdentityCache, groupID string) (libregraph.Identity, error) {
|
||||
identity := libregraph.Identity{
|
||||
Id: libregraph.PtrString(groupID),
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func identitySetToSpacePermissionID(identitySet libregraph.SharePointIdentitySet
|
||||
func cs3ReceivedSharesToDriveItems(ctx context.Context,
|
||||
logger *log.Logger,
|
||||
gatewayClient gateway.GatewayAPIClient,
|
||||
identityCache cache.IdentityCache,
|
||||
identityCache identity.IdentityCache,
|
||||
receivedShares []*collaboration.ReceivedShare,
|
||||
availableRoles []*libregraph.UnifiedRoleDefinition,
|
||||
) ([]libregraph.DriveItem, error) {
|
||||
@@ -341,7 +341,7 @@ func cs3ReceivedSharesToDriveItems(ctx context.Context,
|
||||
}
|
||||
|
||||
func fillDriveItemPropertiesFromReceivedShare(ctx context.Context, logger *log.Logger,
|
||||
identityCache cache.IdentityCache, receivedShares []*collaboration.ReceivedShare,
|
||||
identityCache identity.IdentityCache, receivedShares []*collaboration.ReceivedShare,
|
||||
resourceInfo *storageprovider.ResourceInfo, availableRoles []*libregraph.UnifiedRoleDefinition) (*libregraph.DriveItem, error) {
|
||||
|
||||
driveItem := libregraph.NewDriveItem()
|
||||
@@ -416,7 +416,7 @@ func fillDriveItemPropertiesFromReceivedShare(ctx context.Context, logger *log.L
|
||||
}
|
||||
|
||||
func cs3ReceivedShareToLibreGraphPermissions(ctx context.Context, logger *log.Logger,
|
||||
identityCache cache.IdentityCache, receivedShare *collaboration.ReceivedShare,
|
||||
identityCache identity.IdentityCache, receivedShare *collaboration.ReceivedShare,
|
||||
resourceInfo *storageprovider.ResourceInfo, availableRoles []*libregraph.UnifiedRoleDefinition) (*libregraph.Permission, error) {
|
||||
permission := libregraph.NewPermission()
|
||||
if id := receivedShare.GetShare().GetId().GetOpaqueId(); id != "" {
|
||||
@@ -510,7 +510,7 @@ func ExtractShareIdFromResourceId(rid *storageprovider.ResourceId) *collaboratio
|
||||
func cs3ReceivedOCMSharesToDriveItems(ctx context.Context,
|
||||
logger *log.Logger,
|
||||
gatewayClient gateway.GatewayAPIClient,
|
||||
identityCache cache.IdentityCache,
|
||||
identityCache identity.IdentityCache,
|
||||
receivedShares []*ocm.ReceivedShare, availableRoles []*libregraph.UnifiedRoleDefinition) ([]libregraph.DriveItem, error) {
|
||||
|
||||
group := new(errgroup.Group)
|
||||
@@ -696,7 +696,7 @@ func cs3ReceivedOCMSharesToDriveItems(ctx context.Context,
|
||||
}
|
||||
|
||||
func fillDriveItemPropertiesFromReceivedOCMShare(ctx context.Context, logger *log.Logger,
|
||||
identityCache cache.IdentityCache, receivedShares []*ocm.ReceivedShare,
|
||||
identityCache identity.IdentityCache, receivedShares []*ocm.ReceivedShare,
|
||||
resourceInfo *storageprovider.ResourceInfo, availableRoles []*libregraph.UnifiedRoleDefinition) (*libregraph.DriveItem, error) {
|
||||
|
||||
driveItem := libregraph.NewDriveItem()
|
||||
@@ -775,7 +775,7 @@ func fillDriveItemPropertiesFromReceivedOCMShare(ctx context.Context, logger *lo
|
||||
}
|
||||
|
||||
func cs3ReceivedOCMShareToLibreGraphPermissions(ctx context.Context, logger *log.Logger,
|
||||
identityCache cache.IdentityCache, receivedShare *ocm.ReceivedShare,
|
||||
identityCache identity.IdentityCache, receivedShare *ocm.ReceivedShare,
|
||||
resourceInfo *storageprovider.ResourceInfo, availableRoles []*libregraph.UnifiedRoleDefinition) (*libregraph.Permission, error) {
|
||||
permission := libregraph.NewPermission()
|
||||
if id := receivedShare.GetId().GetOpaqueId(); id != "" {
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
rConversions "github.com/opencloud-eu/reva/v2/pkg/conversions"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storagespace"
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/conversions"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity/cache"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
|
||||
service "github.com/opencloud-eu/opencloud/services/graph/pkg/service/v0"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
@@ -116,7 +116,7 @@ var _ = Describe("Utils", func() {
|
||||
permission, err := service.CS3ReceivedShareToLibreGraphPermissions(
|
||||
context.Background(),
|
||||
nil,
|
||||
cache.IdentityCache{},
|
||||
identity.IdentityCache{},
|
||||
&collaboration.ReceivedShare{
|
||||
Share: &collaboration.Share{
|
||||
Permissions: &collaboration.SharePermissions{
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
# Groups
|
||||
|
||||
The `groups` service provides the CS3 Groups API for OpenCloud. It is responsible for managing group information and memberships within the OpenCloud instance.
|
||||
|
||||
This service implements the CS3 identity group provider interface, allowing other services to query and manage groups. It works as a backend provider for the `graph` service when using the CS3 backend mode.
|
||||
|
||||
## Backend Integration
|
||||
|
||||
The groups service can work with different storage backends:
|
||||
- LDAP integration through the graph service
|
||||
- Direct CS3 API implementation
|
||||
|
||||
When using the `graph` service with the CS3 backend (`GRAPH_IDENTITY_BACKEND=cs3`), the graph service queries group information through this service.
|
||||
|
||||
## API
|
||||
|
||||
The service provides CS3 gRPC APIs for:
|
||||
- Listing groups
|
||||
- Getting group information
|
||||
- Finding groups by name or ID
|
||||
- Managing group memberships
|
||||
|
||||
## Usage
|
||||
|
||||
The groups service is only used internally by other OpenCloud services and not being accessed directly by clients. The `frontend` and `ocs` services translate HTTP API requests into CS3 API calls to this service.
|
||||
|
||||
## Scalability
|
||||
|
||||
Since the groups service queries backend systems (like LDAP through the configured identity backend), it can be scaled horizontally without additional configuration when using stateless backends.
|
||||
@@ -4,7 +4,7 @@ This service provides a builtin minimal OpenID Connect provider based on [LibreG
|
||||
|
||||
It is mainly targeted at smaller installations. For larger setups it is recommended to replace IDP with an external OpenID Connect Provider.
|
||||
|
||||
By default, it is configured to use the OpenCloud IDM service as its LDAP backend for looking up and authenticating users. Other backends like an external LDAP server can be configured via a set of [enviroment variables](https://docs.opencloud.eu/docs/dev/server/services/idp/environment-variables).
|
||||
By default, it is configured to use the OpenCloud IDM service as its LDAP backend for looking up and authenticating users. Other backends like an external LDAP server can be configured via a set of [enviroment variables](https://docs.opencloud.eu/services/idp/configuration/#environment-variables).
|
||||
|
||||
Note that translations provided by the IDP service are not maintained via OpenCloud but part of the embedded [LibreGraph Connect Identifier](https://github.com/libregraph/lico/tree/master/identifier) package.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-23 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-11-02 00:02+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"
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-24 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. UnsharedSpace email template, resolves via {{ .CallToAction }}
|
||||
#: pkg/email/templates.go:65
|
||||
msgid "Click here to check it: {ShareLink}"
|
||||
msgstr "Napsauta tästä tarkistaaksesi sen: {ShareLink}"
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .CallToAction }}
|
||||
#. SharedSpace email template, resolves via {{ .CallToAction }}
|
||||
#: pkg/email/templates.go:23 pkg/email/templates.go:50
|
||||
msgid "Click here to view it: {ShareLink}"
|
||||
msgstr "Napsauta tästä nähdäksesi sen: {ShareLink}"
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:19
|
||||
msgid "Hello {ShareGrantee}"
|
||||
msgstr "Hei {ShareGrantee}"
|
||||
|
||||
#. ShareExpired email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:32
|
||||
msgid "Hello {ShareGrantee},"
|
||||
msgstr "Hei {ShareGrantee}"
|
||||
|
||||
#. SharedSpace email template, resolves via {{ .Greeting }}
|
||||
#. UnsharedSpace email template, resolves via {{ .Greeting }}
|
||||
#. MembershipExpired email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:46 pkg/email/templates.go:59
|
||||
#: pkg/email/templates.go:74
|
||||
msgid "Hello {SpaceGrantee},"
|
||||
msgstr "Hei {SpaceGrantee}"
|
||||
|
||||
#. Grouped email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:118
|
||||
msgid "Hi {DisplayName},"
|
||||
msgstr "Hei {DisplayName}"
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, resolves via {{ .Greeting
|
||||
#. }}
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, resolves
|
||||
#. via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:87 pkg/email/templates.go:104
|
||||
msgid "Hi,"
|
||||
msgstr "Hei"
|
||||
|
||||
#. MembershipExpired email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:72
|
||||
msgid "Membership of '{SpaceName}' expired at {ExpiredAt}"
|
||||
msgstr "Avaruuden '{SpaceName}' jäsenyys vanheni {ExpiredAt}"
|
||||
|
||||
#. Grouped email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:116
|
||||
msgid "Report"
|
||||
msgstr "Ilmoita"
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, Subject field (resolves
|
||||
#. directly)
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, Subject
|
||||
#. field (resolves directly)
|
||||
#: pkg/email/templates.go:85 pkg/email/templates.go:102
|
||||
msgid "ScienceMesh: {InitiatorName} wants to collaborate with you"
|
||||
msgstr "ScienceMesh: {InitiatorName} haluaa tehdä yhteistyötä kanssasi"
|
||||
|
||||
#. ShareExpired email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:30
|
||||
msgid "Share to '{ShareFolder}' expired at {ExpiredAt}"
|
||||
msgstr "Jako kansioon '{ShareFolder}' vanheni {ExpiredAt}"
|
||||
|
||||
#. MembershipExpired email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:76
|
||||
msgid ""
|
||||
"Your membership of space {SpaceName} has expired at {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Even though this membership has expired you still might have access through other shares and/or space memberships"
|
||||
msgstr ""
|
||||
|
||||
#. ShareExpired email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:34
|
||||
msgid ""
|
||||
"Your share to {ShareFolder} has expired at {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Even though this share has been revoked you still might have access through other shares and/or space memberships."
|
||||
msgstr ""
|
||||
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, resolves
|
||||
#. via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:106
|
||||
msgid ""
|
||||
"{ShareSharer} ({ShareSharerMail}) wants to start sharing collaboration resources with you.\n"
|
||||
"Please visit your federation settings and use the following details:\n"
|
||||
" Token: {Token}\n"
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, resolves via {{
|
||||
#. .MessageBody }}
|
||||
#: pkg/email/templates.go:89
|
||||
msgid ""
|
||||
"{ShareSharer} ({ShareSharerMail}) wants to start sharing collaboration resources with you.\n"
|
||||
"To accept the invite, please visit the following URL:\n"
|
||||
"{ShareLink}\n"
|
||||
"\n"
|
||||
"Alternatively, you can visit your federation settings and use the following details:\n"
|
||||
" Token: {Token}\n"
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:21
|
||||
msgid "{ShareSharer} has shared \"{ShareFolder}\" with you."
|
||||
msgstr "{ShareSharer} on jakanut kansion \"{ShareFolder}\" kanssasi."
|
||||
|
||||
#. ShareCreated email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:17
|
||||
msgid "{ShareSharer} shared '{ShareFolder}' with you"
|
||||
msgstr "{ShareSharer} jakoi '{ShareFolder}' kanssasi"
|
||||
|
||||
#. SharedSpace email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:48
|
||||
msgid "{SpaceSharer} has invited you to join \"{SpaceName}\"."
|
||||
msgstr "{SpaceSharer} kutsui sinut avaruuteen \"{SpaceName}\"."
|
||||
|
||||
#. UnsharedSpace email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:61
|
||||
msgid ""
|
||||
"{SpaceSharer} has removed you from \"{SpaceName}\".\n"
|
||||
"\n"
|
||||
"You might still have access through your other groups or direct membership."
|
||||
msgstr ""
|
||||
"{SpaceSharer} on poistanut sinut avaruudesta \"{SpaceName}\".\n"
|
||||
"\n"
|
||||
"Sinulla saattaa silti olla pääsy muiden ryhmien tai suoran jäsenyyden kautta."
|
||||
|
||||
#. SharedSpace email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:44
|
||||
msgid "{SpaceSharer} invited you to join {SpaceName}"
|
||||
msgstr "{SpaceSharer} kutsui sinut avaruuteen {SpaceName}"
|
||||
|
||||
#. UnsharedSpace email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:57
|
||||
msgid "{SpaceSharer} removed you from {SpaceName}"
|
||||
msgstr "{SpaceSharer} poisti sinut avaruudesta {SpaceName}"
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-15 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-26 00:00+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"
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Mário Machado, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-18 00:02+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"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#. UnsharedSpace email template, resolves via {{ .CallToAction }}
|
||||
#: pkg/email/templates.go:65
|
||||
msgid "Click here to check it: {ShareLink}"
|
||||
msgstr "Clique aqui para verificar: {ShareLink}"
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .CallToAction }}
|
||||
#. SharedSpace email template, resolves via {{ .CallToAction }}
|
||||
#: pkg/email/templates.go:23 pkg/email/templates.go:50
|
||||
msgid "Click here to view it: {ShareLink}"
|
||||
msgstr "Clique aqui para visualizar: {ShareLink}"
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:19
|
||||
msgid "Hello {ShareGrantee}"
|
||||
msgstr "Olá {ShareGrantee}"
|
||||
|
||||
#. ShareExpired email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:32
|
||||
msgid "Hello {ShareGrantee},"
|
||||
msgstr "Olá {ShareGrantee},"
|
||||
|
||||
#. SharedSpace email template, resolves via {{ .Greeting }}
|
||||
#. UnsharedSpace email template, resolves via {{ .Greeting }}
|
||||
#. MembershipExpired email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:46 pkg/email/templates.go:59
|
||||
#: pkg/email/templates.go:74
|
||||
msgid "Hello {SpaceGrantee},"
|
||||
msgstr "Olá {SpaceGrantee},"
|
||||
|
||||
#. Grouped email template, resolves via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:118
|
||||
msgid "Hi {DisplayName},"
|
||||
msgstr "Olá {DisplayName},"
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, resolves via {{ .Greeting
|
||||
#. }}
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, resolves
|
||||
#. via {{ .Greeting }}
|
||||
#: pkg/email/templates.go:87 pkg/email/templates.go:104
|
||||
msgid "Hi,"
|
||||
msgstr "Olá,"
|
||||
|
||||
#. MembershipExpired email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:72
|
||||
msgid "Membership of '{SpaceName}' expired at {ExpiredAt}"
|
||||
msgstr "A subscrição em «{SpaceName}» expirou em {ExpiredAt}"
|
||||
|
||||
#. Grouped email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:116
|
||||
msgid "Report"
|
||||
msgstr "Relatório"
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, Subject field (resolves
|
||||
#. directly)
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, Subject
|
||||
#. field (resolves directly)
|
||||
#: pkg/email/templates.go:85 pkg/email/templates.go:102
|
||||
msgid "ScienceMesh: {InitiatorName} wants to collaborate with you"
|
||||
msgstr "ScienceMesh: {InitiatorName} quer colaborar consigo"
|
||||
|
||||
#. ShareExpired email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:30
|
||||
msgid "Share to '{ShareFolder}' expired at {ExpiredAt}"
|
||||
msgstr "A partilha para «{ShareFolder}» expirou em {ExpiredAt}"
|
||||
|
||||
#. MembershipExpired email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:76
|
||||
msgid ""
|
||||
"Your membership of space {SpaceName} has expired at {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Even though this membership has expired you still might have access through other shares and/or space memberships"
|
||||
msgstr ""
|
||||
"A sua subscrição no espaço {SpaceName} expirou em {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Ainda que esta subscrição tenha expirado, poderá continuar a ter acesso através de outras partilhas e/ou subscrições de espaço"
|
||||
|
||||
#. ShareExpired email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:34
|
||||
msgid ""
|
||||
"Your share to {ShareFolder} has expired at {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Even though this share has been revoked you still might have access through other shares and/or space memberships."
|
||||
msgstr ""
|
||||
"A sua partilha para {ShareFolder} expirou em {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Ainda que esta partilha tenha sido revogada, poderá continuar a ter acesso através de outras partilhas e/ou subscrições de espaço."
|
||||
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, resolves
|
||||
#. via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:106
|
||||
msgid ""
|
||||
"{ShareSharer} ({ShareSharerMail}) wants to start sharing collaboration resources with you.\n"
|
||||
"Please visit your federation settings and use the following details:\n"
|
||||
" Token: {Token}\n"
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
"{ShareSharer} ({ShareSharerMail}) quer iniciar a partilha de recursos de colaboração consigo.\n"
|
||||
"Por favor, visite as definições de federação e utilize os seguintes dados:\n"
|
||||
"Token: {Token} \n"
|
||||
"Podevor de Dominio: {ProviderDomain}"
|
||||
|
||||
#. ScienceMeshInviteTokenGenerated email template, resolves via {{
|
||||
#. .MessageBody }}
|
||||
#: pkg/email/templates.go:89
|
||||
msgid ""
|
||||
"{ShareSharer} ({ShareSharerMail}) wants to start sharing collaboration resources with you.\n"
|
||||
"To accept the invite, please visit the following URL:\n"
|
||||
"{ShareLink}\n"
|
||||
"\n"
|
||||
"Alternatively, you can visit your federation settings and use the following details:\n"
|
||||
" Token: {Token}\n"
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
"{ShareSharer} ({ShareSharerMail}) quer iniciar a partilha de recursos de colaboração consigo.\n"
|
||||
"Para aceitar o convite, visite a seguinte URL: {ShareLink}\n"
|
||||
"\n"
|
||||
"Em alternativa, pode visitar as definições de federação e utilizar os seguintes dados:\n"
|
||||
"Token: {Token} Provedor de Dominio: {ProviderDomain}"
|
||||
|
||||
#. ShareCreated email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:21
|
||||
msgid "{ShareSharer} has shared \"{ShareFolder}\" with you."
|
||||
msgstr "{ShareSharer} partilhou «{ShareFolder}» consigo."
|
||||
|
||||
#. ShareCreated email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:17
|
||||
msgid "{ShareSharer} shared '{ShareFolder}' with you"
|
||||
msgstr "{ShareSharer} partilhou «{ShareFolder}» consigo"
|
||||
|
||||
#. SharedSpace email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:48
|
||||
msgid "{SpaceSharer} has invited you to join \"{SpaceName}\"."
|
||||
msgstr "{SpaceSharer} convidou-o/a a juntar-se a «{SpaceName}»."
|
||||
|
||||
#. UnsharedSpace email template, resolves via {{ .MessageBody }}
|
||||
#: pkg/email/templates.go:61
|
||||
msgid ""
|
||||
"{SpaceSharer} has removed you from \"{SpaceName}\".\n"
|
||||
"\n"
|
||||
"You might still have access through your other groups or direct membership."
|
||||
msgstr ""
|
||||
"{SpaceSharer} removeu-o/a de «{SpaceName}».\n"
|
||||
"\n"
|
||||
"Poderá ainda ter acesso através dos seus outros grupos ou subscrição direta."
|
||||
|
||||
#. SharedSpace email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:44
|
||||
msgid "{SpaceSharer} invited you to join {SpaceName}"
|
||||
msgstr "{SpaceSharer} convidou-o/a a juntar-se a {SpaceName}"
|
||||
|
||||
#. UnsharedSpace email template, Subject field (resolves directly)
|
||||
#: pkg/email/templates.go:57
|
||||
msgid "{SpaceSharer} removed you from {SpaceName}"
|
||||
msgstr "{SpaceSharer} removeu-o/a de {SpaceName}"
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-16 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-27 00:01+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"
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
#
|
||||
# Translators:
|
||||
# Davis Kaza, 2025
|
||||
# Daniel Nylander <po@danielnylander.se>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-08 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+0000\n"
|
||||
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
|
||||
"Last-Translator: Daniel Nylander <po@danielnylander.se>, 2025\n"
|
||||
"Last-Translator: Davis Kaza, 2025\n"
|
||||
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -107,7 +106,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Din delning till {ShareFolder} har löpt ut {ExpiredAt}\n"
|
||||
"\n"
|
||||
"Även om denna delning har löpt ut kan du fortfarande ha tillgång via andra delningar och/eller medlemskap i arbetsytor."
|
||||
"Även om denna delning har löpt ut kan du fortfarande ha tillgång via andra delningar och/eller medlemskap i arbetsytor"
|
||||
|
||||
#. ScienceMeshInviteTokenGeneratedWithoutShareLink email template, resolves
|
||||
#. via {{ .MessageBody }}
|
||||
@@ -119,7 +118,7 @@ msgid ""
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
"{ShareSharer} ({ShareSharerMail}) vill börja dela samarbetsresurser med dig.\n"
|
||||
"Kolla dina federationsinställningar och använd följande uppgifter:\n"
|
||||
"Var vänlig och kolla dina federationsinställningar och använd följande uppgifter:\n"
|
||||
"Token: {Token}\n"
|
||||
"ProviderDomain: {ProviderDomain}"
|
||||
|
||||
@@ -136,7 +135,7 @@ msgid ""
|
||||
" ProviderDomain: {ProviderDomain}"
|
||||
msgstr ""
|
||||
"{ShareSharer} ({ShareSharerMail}) vill börja dela samarbetsresurser med dig.\n"
|
||||
"Besök följande URL för att acceptera inbjudan:\n"
|
||||
"Var vänlig och besök följande URL för att acceptera inbjudan:\n"
|
||||
"{ShareLink}\n"
|
||||
"\n"
|
||||
"Alternativt kan du kolla dina federationsinställningar och använda följande uppgifter:\n"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2025-11-09 00:02+0000\n"
|
||||
"POT-Creation-Date: 2025-10-20 00:01+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"
|
||||
|
||||
@@ -95,7 +95,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
ocdav.WithTraceProvider(traceProvider),
|
||||
ocdav.RegisterTTL(registry.GetRegisterTTL()),
|
||||
ocdav.RegisterInterval(registry.GetRegisterInterval()),
|
||||
ocdav.URLSigningSharedSecret(cfg.Commons.URLSigningSecret),
|
||||
ocdav.URLSigningSharedSecret(cfg.URLSigningSharedSecret),
|
||||
}
|
||||
|
||||
s, err := ocdav.Service(opts...)
|
||||
|
||||
@@ -34,8 +34,9 @@ type Config struct {
|
||||
|
||||
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY;OCDAV_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
|
||||
|
||||
Context context.Context `yaml:"-"`
|
||||
Status Status `yaml:"-"`
|
||||
URLSigningSharedSecret string `yaml:"url_signing_shared_secret" env:"OC_URL_SIGNING_SHARED_SECRET" desc:"The shared secret used to sign URLs." introductionVersion:"4.0.0"`
|
||||
Context context.Context `yaml:"-"`
|
||||
Status Status `yaml:"-"`
|
||||
|
||||
AllowPropfindDepthInfinity bool `yaml:"allow_propfind_depth_infinity" env:"OCDAV_ALLOW_PROPFIND_DEPTH_INFINITY" desc:"Allow the use of depth infinity in PROPFINDS. When enabled, a propfind will traverse through all subfolders. If many subfolders are expected, depth infinity can cause heavy server load and/or delayed response times." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
@@ -37,14 +37,9 @@ func Validate(cfg *config.Config) error {
|
||||
if cfg.TokenManager.JWTSecret == "" {
|
||||
return shared.MissingJWTTokenError(cfg.Service.Name)
|
||||
}
|
||||
|
||||
if cfg.MachineAuthAPIKey == "" {
|
||||
return shared.MissingMachineAuthApiKeyError(cfg.Service.Name)
|
||||
}
|
||||
|
||||
if cfg.Commons.URLSigningSecret == "" {
|
||||
return shared.MissingURLSigningSecret(cfg.Service.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -105,9 +105,8 @@ When all instances of a federation should trust each other, an `ocmproviders.jso
|
||||
]
|
||||
```
|
||||
|
||||
:::info
|
||||
::: info
|
||||
Note: the `domain` must not contain the protocol as it has to match the [GOCDB site object domain](https://developer.sciencemesh.io/docs/technical-documentation/central-database/#site-object).
|
||||
:::
|
||||
|
||||
The above federation consists of two instances: `cloud1.opencloud.test` and `cloud2.opencloud.test` that can use the Invitation workflow described below to generate, send and accept invitations.
|
||||
|
||||
@@ -115,18 +114,17 @@ The above federation consists of two instances: `cloud1.opencloud.test` and `clo
|
||||
|
||||
Before sharing a resource with a remote user this user has to be invited by the sharer.
|
||||
|
||||
In order to do so a POST request is sent to the `generate-invite` endpoint of the sciencemesh API. The generated token is passed on to the receiver, who will then use the `accept-invite` endpoint to accept the invitation. As a result remote users will be added to the `ocminvitemanager` on both sides. See [invitation flow](invitation-flow) for the according sequence diagram.
|
||||
In order to do so a POST request is sent to the `generate-invite` endpoint of the sciencemesh API. The generated token is passed on to the receiver, who will then use the `accept-invite` endpoint to accept the invitation. As a result remote users will be added to the `ocminvitemanager` on both sides. See [invitation flow](invitation_flow) for the according sequence diagram.
|
||||
|
||||
The data backend of the `ocminvitemanager` is configurable. The only supported backend currently is `json` which stores the data in a json file on disk.
|
||||
|
||||
## Creating Shares
|
||||
|
||||
:::info
|
||||
::: info
|
||||
The below info is outdated as we allow creating federated shares using the graph API. Clients can now discover the available sharing roles and invite federated users using the graph API.
|
||||
:::
|
||||
|
||||
OCM Shares are currently created using the ocs API, just like regular shares. The difference is the share type, which is 6 (ShareTypeFederatedCloudShare) in this case, and a few additional parameters required for identifying the remote user.
|
||||
|
||||
See [Create share flow](create-share-flow) for the according sequence diagram.
|
||||
See [Create share flow](create_share_flow) for the according sequence diagram.
|
||||
|
||||
The data backends of the `ocmshareprovider` and `ocmcore` services are configurable. The only supported backend currently is `json` which stores the data in a json file on disk.
|
||||
|
||||
@@ -136,7 +136,7 @@ Note that additional steps can be configured and their position in the list defi
|
||||
|
||||
## Rego Key Match
|
||||
|
||||
To identify available keys for OPA, you need to look at [engine.go](https://github.com/opencloud-eu/opencloud/blob/main/services/policies/pkg/engine/engine.go) and the [policies.swagger.json](https://github.com/opencloud-eu/opencloud/blob/master/protogen/gen/opencloud/services/policies/v0/policies.swagger.json) file. Note that which keys are available depends on from which module it is used.
|
||||
To identify available keys for OPA, you need to look at [engine.go](https://github.com/opencloud-eu/opencloud/blob/main/services/policies/pkg/engine/engine.go) and the [policies.swagger.json](https://github.com/opencloud/blob/blob/master/protogen/gen/opencloud/services/policies/v0/policies.swagger.json) file. Note that which keys are available depends on from which module it is used.
|
||||
|
||||
## Extend Mimetype File Extension Mapping
|
||||
|
||||
|
||||
@@ -311,11 +311,15 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
|
||||
RevaGatewaySelector: gatewaySelector,
|
||||
})
|
||||
|
||||
signURLVerifier, err := signedurl.NewJWTSignedURL(signedurl.WithSecret(cfg.Commons.URLSigningSecret))
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("Failed to initialize signed URL configuration.")
|
||||
}
|
||||
var signURLVerifier signedurl.Verifier
|
||||
|
||||
if cfg.PreSignedURL.JWTSigningSharedSecret != "" {
|
||||
var err error
|
||||
signURLVerifier, err = signedurl.NewJWTSignedURL(signedurl.WithSecret(cfg.PreSignedURL.JWTSigningSharedSecret))
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("Failed to initialize signed URL configuration.")
|
||||
}
|
||||
}
|
||||
authenticators = append(authenticators, middleware.SignedURLAuthenticator{
|
||||
Logger: logger,
|
||||
PreSignedURLConfig: cfg.PreSignedURL,
|
||||
|
||||
@@ -24,28 +24,27 @@ type Config struct {
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GrpcClient client.Client `yaml:"-"`
|
||||
|
||||
RoleQuotas map[string]uint64 `yaml:"role_quotas"`
|
||||
Policies []Policy `yaml:"policies"`
|
||||
AdditionalPolicies []Policy `yaml:"additional_policies"`
|
||||
OIDC OIDC `yaml:"oidc"`
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
RoleAssignment RoleAssignment `yaml:"role_assignment"`
|
||||
PolicySelector *PolicySelector `yaml:"policy_selector"`
|
||||
PreSignedURL PreSignedURL `yaml:"pre_signed_url"`
|
||||
AccountBackend string `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE" desc:"Account backend the PROXY service should use. Currently only 'cs3' is possible here." introductionVersion:"1.0.0"`
|
||||
UserOIDCClaim string `yaml:"user_oidc_claim" env:"PROXY_USER_OIDC_CLAIM" desc:"The name of an OpenID Connect claim that is used for resolving users with the account backend. The value of the claim must hold a per user unique, stable and non re-assignable identifier. The availability of claims depends on your Identity Provider. There are common claims available for most Identity providers like 'email' or 'preferred_username' but you can also add your own claim." introductionVersion:"1.0.0"`
|
||||
UserCS3Claim string `yaml:"user_cs3_claim" env:"PROXY_USER_CS3_CLAIM" desc:"The name of a CS3 user attribute (claim) that should be mapped to the 'user_oidc_claim'. Supported values are 'username', 'mail' and 'userid'." introductionVersion:"1.0.0"`
|
||||
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services." introductionVersion:"1.0.0" mask:"password"`
|
||||
AutoprovisionAccounts bool `yaml:"auto_provision_accounts" env:"PROXY_AUTOPROVISION_ACCOUNTS" desc:"Set this to 'true' to automatically provision users that do not yet exist in the users service on-demand upon first sign-in. To use this a write-enabled libregraph user backend needs to be setup an running." introductionVersion:"1.0.0"`
|
||||
AutoProvisionClaims AutoProvisionClaims `yaml:"auto_provision_claims"`
|
||||
EnableBasicAuth bool `yaml:"enable_basic_auth" env:"PROXY_ENABLE_BASIC_AUTH" desc:"Set this to true to enable 'basic authentication' (username/password)." introductionVersion:"1.0.0"`
|
||||
InsecureBackends bool `yaml:"insecure_backends" env:"PROXY_INSECURE_BACKENDS" desc:"Disable TLS certificate validation for all HTTP backend connections." introductionVersion:"1.0.0"`
|
||||
BackendHTTPSCACert string `yaml:"backend_https_cacert" env:"PROXY_HTTPS_CACERT" desc:"Path/File for the root CA certificate used to validate the server’s TLS certificate for https enabled backend services." introductionVersion:"1.0.0"`
|
||||
AuthMiddleware AuthMiddleware `yaml:"auth_middleware"`
|
||||
PoliciesMiddleware PoliciesMiddleware `yaml:"policies_middleware"`
|
||||
CSPConfigFileLocation string `yaml:"csp_config_file_location" env:"PROXY_CSP_CONFIG_FILE_LOCATION" desc:"The location of the CSP configuration file." introductionVersion:"1.0.0"`
|
||||
CSPConfigFileOverrideLocation string `yaml:"csp_config_file_override_location" env:"PROXY_CSP_CONFIG_FILE_OVERRIDE_LOCATION" desc:"The location of the CSP configuration file override." introductionVersion:"%%NEXT%%"`
|
||||
Events Events `yaml:"events"`
|
||||
RoleQuotas map[string]uint64 `yaml:"role_quotas"`
|
||||
Policies []Policy `yaml:"policies"`
|
||||
AdditionalPolicies []Policy `yaml:"additional_policies"`
|
||||
OIDC OIDC `yaml:"oidc"`
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
RoleAssignment RoleAssignment `yaml:"role_assignment"`
|
||||
PolicySelector *PolicySelector `yaml:"policy_selector"`
|
||||
PreSignedURL PreSignedURL `yaml:"pre_signed_url"`
|
||||
AccountBackend string `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE" desc:"Account backend the PROXY service should use. Currently only 'cs3' is possible here." introductionVersion:"1.0.0"`
|
||||
UserOIDCClaim string `yaml:"user_oidc_claim" env:"PROXY_USER_OIDC_CLAIM" desc:"The name of an OpenID Connect claim that is used for resolving users with the account backend. The value of the claim must hold a per user unique, stable and non re-assignable identifier. The availability of claims depends on your Identity Provider. There are common claims available for most Identity providers like 'email' or 'preferred_username' but you can also add your own claim." introductionVersion:"1.0.0"`
|
||||
UserCS3Claim string `yaml:"user_cs3_claim" env:"PROXY_USER_CS3_CLAIM" desc:"The name of a CS3 user attribute (claim) that should be mapped to the 'user_oidc_claim'. Supported values are 'username', 'mail' and 'userid'." introductionVersion:"1.0.0"`
|
||||
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY;PROXY_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services." introductionVersion:"1.0.0" mask:"password"`
|
||||
AutoprovisionAccounts bool `yaml:"auto_provision_accounts" env:"PROXY_AUTOPROVISION_ACCOUNTS" desc:"Set this to 'true' to automatically provision users that do not yet exist in the users service on-demand upon first sign-in. To use this a write-enabled libregraph user backend needs to be setup an running." introductionVersion:"1.0.0"`
|
||||
AutoProvisionClaims AutoProvisionClaims `yaml:"auto_provision_claims"`
|
||||
EnableBasicAuth bool `yaml:"enable_basic_auth" env:"PROXY_ENABLE_BASIC_AUTH" desc:"Set this to true to enable 'basic authentication' (username/password)." introductionVersion:"1.0.0"`
|
||||
InsecureBackends bool `yaml:"insecure_backends" env:"PROXY_INSECURE_BACKENDS" desc:"Disable TLS certificate validation for all HTTP backend connections." introductionVersion:"1.0.0"`
|
||||
BackendHTTPSCACert string `yaml:"backend_https_cacert" env:"PROXY_HTTPS_CACERT" desc:"Path/File for the root CA certificate used to validate the server’s TLS certificate for https enabled backend services." introductionVersion:"1.0.0"`
|
||||
AuthMiddleware AuthMiddleware `yaml:"auth_middleware"`
|
||||
PoliciesMiddleware PoliciesMiddleware `yaml:"policies_middleware"`
|
||||
CSPConfigFileLocation string `yaml:"csp_config_file_location" env:"PROXY_CSP_CONFIG_FILE_LOCATION" desc:"The location of the CSP configuration file." introductionVersion:"1.0.0"`
|
||||
Events Events `yaml:"events"`
|
||||
|
||||
Context context.Context `json:"-" yaml:"-"`
|
||||
}
|
||||
@@ -181,9 +180,10 @@ type StaticSelectorConf struct {
|
||||
|
||||
// PreSignedURL is the config for the pre-signed url middleware
|
||||
type PreSignedURL struct {
|
||||
AllowedHTTPMethods []string `yaml:"allowed_http_methods"`
|
||||
Enabled bool `yaml:"enabled" env:"PROXY_ENABLE_PRESIGNEDURLS" desc:"Allow OCS to get a signing key to sign requests." introductionVersion:"1.0.0"`
|
||||
SigningKeys *SigningKeys `yaml:"signing_keys"`
|
||||
AllowedHTTPMethods []string `yaml:"allowed_http_methods"`
|
||||
Enabled bool `yaml:"enabled" env:"PROXY_ENABLE_PRESIGNEDURLS" desc:"Allow OCS to get a signing key to sign requests." introductionVersion:"1.0.0"`
|
||||
SigningKeys *SigningKeys `yaml:"signing_keys"`
|
||||
JWTSigningSharedSecret string `yaml:"url_signing_shared_secret" env:"OC_URL_SIGNING_SHARED_SECRET" desc:"The shared secret used to sign URLs." introductionVersion:"4.0.0"`
|
||||
}
|
||||
|
||||
// SigningKeys is a store configuration.
|
||||
|
||||
@@ -5,7 +5,6 @@ directives:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/opencloud-eu/awesome-apps/'
|
||||
- 'https://update.opencloud.eu/'
|
||||
default-src:
|
||||
- '''none'''
|
||||
font-src:
|
||||
|
||||
@@ -92,10 +92,9 @@ func DefaultConfig() *config.Config {
|
||||
DisplayName: "name",
|
||||
Groups: "groups",
|
||||
},
|
||||
EnableBasicAuth: false,
|
||||
InsecureBackends: false,
|
||||
CSPConfigFileLocation: "",
|
||||
CSPConfigFileOverrideLocation: "",
|
||||
EnableBasicAuth: false,
|
||||
InsecureBackends: false,
|
||||
CSPConfigFileLocation: "",
|
||||
Events: config.Events{
|
||||
Endpoint: "127.0.0.1:9233",
|
||||
Cluster: "opencloud-cluster",
|
||||
|
||||
@@ -56,14 +56,9 @@ func Validate(cfg *config.Config) error {
|
||||
if cfg.ServiceAccount.ServiceAccountID == "" {
|
||||
return shared.MissingServiceAccountID(cfg.Service.Name)
|
||||
}
|
||||
|
||||
if cfg.ServiceAccount.ServiceAccountSecret == "" {
|
||||
return shared.MissingServiceAccountSecret(cfg.Service.Name)
|
||||
}
|
||||
|
||||
if cfg.Commons.URLSigningSecret == "" {
|
||||
return shared.MissingURLSigningSecret(cfg.Service.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,48 +3,30 @@ package middleware
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
gofig "github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/yaml"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/config"
|
||||
"github.com/unrolled/secure"
|
||||
"github.com/unrolled/secure/cspbuilder"
|
||||
yamlv3 "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// LoadCSPConfig loads CSP header configuration from a yaml file.
|
||||
func LoadCSPConfig(proxyCfg *config.Config) (*config.CSP, error) {
|
||||
yamlContent, customYamlContent, err := loadCSPYaml(proxyCfg)
|
||||
yamlContent, err := loadCSPYaml(proxyCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return loadCSPConfig(yamlContent, customYamlContent)
|
||||
return loadCSPConfig(yamlContent)
|
||||
}
|
||||
|
||||
// LoadCSPConfig loads CSP header configuration from a yaml file.
|
||||
func loadCSPConfig(presetYamlContent, customYamlContent []byte) (*config.CSP, error) {
|
||||
func loadCSPConfig(yamlContent []byte) (*config.CSP, error) {
|
||||
// substitute env vars and load to struct
|
||||
gofig.WithOptions(gofig.ParseEnv)
|
||||
gofig.AddDriver(yaml.Driver)
|
||||
|
||||
presetMap := map[string]interface{}{}
|
||||
err := yamlv3.Unmarshal(presetYamlContent, &presetMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customMap := map[string]interface{}{}
|
||||
err = yamlv3.Unmarshal(customYamlContent, &customMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mergedMap := deepMerge(presetMap, customMap)
|
||||
mergedYamlContent, err := yamlv3.Marshal(mergedMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = gofig.LoadSources("yaml", mergedYamlContent)
|
||||
err := gofig.LoadSources("yaml", yamlContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -59,78 +41,11 @@ func loadCSPConfig(presetYamlContent, customYamlContent []byte) (*config.CSP, er
|
||||
return &cspConfig, nil
|
||||
}
|
||||
|
||||
// deepMerge recursively merges map2 into map1.
|
||||
// - nested maps are merged recursively
|
||||
// - slices are concatenated, preserving order and avoiding duplicates
|
||||
// - scalar or type-mismatched values from map2 overwrite map1
|
||||
func deepMerge(map1, map2 map[string]interface{}) map[string]interface{} {
|
||||
if map1 == nil {
|
||||
out := make(map[string]interface{}, len(map2))
|
||||
for k, v := range map2 {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
for k, v2 := range map2 {
|
||||
if v1, ok := map1[k]; ok {
|
||||
// both maps -> recurse
|
||||
if m1, ok1 := v1.(map[string]interface{}); ok1 {
|
||||
if m2, ok2 := v2.(map[string]interface{}); ok2 {
|
||||
map1[k] = deepMerge(m1, m2)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// both slices -> merge unique
|
||||
if s1, ok1 := v1.([]interface{}); ok1 {
|
||||
if s2, ok2 := v2.([]interface{}); ok2 {
|
||||
merged := append([]interface{}{}, s1...)
|
||||
for _, item := range s2 {
|
||||
if !sliceContains(merged, item) {
|
||||
merged = append(merged, item)
|
||||
}
|
||||
}
|
||||
map1[k] = merged
|
||||
continue
|
||||
}
|
||||
// s1 is slice, v2 single -> append if missing
|
||||
if !sliceContains(s1, v2) {
|
||||
map1[k] = append(s1, v2)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// default: overwrite
|
||||
map1[k] = v2
|
||||
} else {
|
||||
// new key -> just set
|
||||
map1[k] = v2
|
||||
}
|
||||
}
|
||||
|
||||
return map1
|
||||
}
|
||||
|
||||
func sliceContains(slice []interface{}, val interface{}) bool {
|
||||
for _, v := range slice {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func loadCSPYaml(proxyCfg *config.Config) ([]byte, []byte, error) {
|
||||
if proxyCfg.CSPConfigFileOverrideLocation != "" {
|
||||
overrideCSPYaml, err := os.ReadFile(proxyCfg.CSPConfigFileOverrideLocation)
|
||||
return overrideCSPYaml, []byte{}, err
|
||||
}
|
||||
func loadCSPYaml(proxyCfg *config.Config) ([]byte, error) {
|
||||
if proxyCfg.CSPConfigFileLocation == "" {
|
||||
return []byte(config.DefaultCSPConfig), nil, nil
|
||||
return []byte(config.DefaultCSPConfig), nil
|
||||
}
|
||||
customCSPYaml, err := os.ReadFile(proxyCfg.CSPConfigFileLocation)
|
||||
return []byte(config.DefaultCSPConfig), customCSPYaml, err
|
||||
return os.ReadFile(proxyCfg.CSPConfigFileLocation)
|
||||
}
|
||||
|
||||
// Security is a middleware to apply security relevant http headers like CSP.
|
||||
|
||||
@@ -4,12 +4,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLoadCSPConfig(t *testing.T) {
|
||||
// setup test env
|
||||
presetYaml := `
|
||||
yaml := `
|
||||
directives:
|
||||
frame-src:
|
||||
- '''self'''
|
||||
@@ -18,23 +17,12 @@ directives:
|
||||
- 'https://${COLLABORA_DOMAIN|collabora.opencloud.test}/'
|
||||
`
|
||||
|
||||
customYaml := `
|
||||
directives:
|
||||
img-src:
|
||||
- '''self'''
|
||||
- 'data:'
|
||||
frame-src:
|
||||
- 'https://some.custom.domain/'
|
||||
`
|
||||
config, err := loadCSPConfig([]byte(presetYaml), []byte(customYaml))
|
||||
config, err := loadCSPConfig([]byte(yaml))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Assert(t, cmp.Contains(config.Directives["frame-src"], "'self'"))
|
||||
assert.Assert(t, cmp.Contains(config.Directives["frame-src"], "https://embed.diagrams.net/"))
|
||||
assert.Assert(t, cmp.Contains(config.Directives["frame-src"], "https://onlyoffice.opencloud.test/"))
|
||||
assert.Assert(t, cmp.Contains(config.Directives["frame-src"], "https://collabora.opencloud.test/"))
|
||||
|
||||
assert.Assert(t, cmp.Contains(config.Directives["img-src"], "'self'"))
|
||||
assert.Assert(t, cmp.Contains(config.Directives["img-src"], "data:"))
|
||||
assert.Equal(t, config.Directives["frame-src"][0], "'self'")
|
||||
assert.Equal(t, config.Directives["frame-src"][1], "https://embed.diagrams.net/")
|
||||
assert.Equal(t, config.Directives["frame-src"][2], "https://onlyoffice.opencloud.test/")
|
||||
assert.Equal(t, config.Directives["frame-src"][3], "https://collabora.opencloud.test/")
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"go-micro.dev/v4"
|
||||
|
||||
pkgcrypto "github.com/opencloud-eu/opencloud/pkg/crypto"
|
||||
"github.com/opencloud-eu/opencloud/pkg/service/http"
|
||||
"github.com/opencloud-eu/opencloud/pkg/shared"
|
||||
"github.com/opencloud-eu/opencloud/pkg/version"
|
||||
"go-micro.dev/v4"
|
||||
)
|
||||
|
||||
// Server initializes the http service and server.
|
||||
@@ -40,6 +41,7 @@ func Server(opts ...Option) (http.Service, error) {
|
||||
Cert: options.Config.HTTP.TLSCert,
|
||||
Key: options.Config.HTTP.TLSKey,
|
||||
}),
|
||||
http.TimeoutConfig(options.Config.Commons.HTTPServiceTimeout),
|
||||
http.Logger(options.Logger),
|
||||
http.Address(options.Config.HTTP.Addr),
|
||||
http.Namespace(options.Config.HTTP.Namespace),
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events/raw"
|
||||
@@ -85,37 +84,30 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
|
||||
eng = bleve.NewBackend(idx, bleveQuery.DefaultCreator, logger)
|
||||
case "open-search":
|
||||
clientConfig := opensearchgo.Config{
|
||||
Addresses: cfg.Engine.OpenSearch.Client.Addresses,
|
||||
Username: cfg.Engine.OpenSearch.Client.Username,
|
||||
Password: cfg.Engine.OpenSearch.Client.Password,
|
||||
Header: cfg.Engine.OpenSearch.Client.Header,
|
||||
RetryOnStatus: cfg.Engine.OpenSearch.Client.RetryOnStatus,
|
||||
DisableRetry: cfg.Engine.OpenSearch.Client.DisableRetry,
|
||||
EnableRetryOnTimeout: cfg.Engine.OpenSearch.Client.EnableRetryOnTimeout,
|
||||
MaxRetries: cfg.Engine.OpenSearch.Client.MaxRetries,
|
||||
CompressRequestBody: cfg.Engine.OpenSearch.Client.CompressRequestBody,
|
||||
DiscoverNodesOnStart: cfg.Engine.OpenSearch.Client.DiscoverNodesOnStart,
|
||||
DiscoverNodesInterval: cfg.Engine.OpenSearch.Client.DiscoverNodesInterval,
|
||||
EnableMetrics: cfg.Engine.OpenSearch.Client.EnableMetrics,
|
||||
EnableDebugLogger: cfg.Engine.OpenSearch.Client.EnableDebugLogger,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: cfg.Engine.OpenSearch.Client.Insecure,
|
||||
client, err := opensearchgoAPI.NewClient(opensearchgoAPI.Config{
|
||||
Client: opensearchgo.Config{
|
||||
Addresses: cfg.Engine.OpenSearch.Client.Addresses,
|
||||
Username: cfg.Engine.OpenSearch.Client.Username,
|
||||
Password: cfg.Engine.OpenSearch.Client.Password,
|
||||
Header: cfg.Engine.OpenSearch.Client.Header,
|
||||
CACert: cfg.Engine.OpenSearch.Client.CACert,
|
||||
RetryOnStatus: cfg.Engine.OpenSearch.Client.RetryOnStatus,
|
||||
DisableRetry: cfg.Engine.OpenSearch.Client.DisableRetry,
|
||||
EnableRetryOnTimeout: cfg.Engine.OpenSearch.Client.EnableRetryOnTimeout,
|
||||
MaxRetries: cfg.Engine.OpenSearch.Client.MaxRetries,
|
||||
CompressRequestBody: cfg.Engine.OpenSearch.Client.CompressRequestBody,
|
||||
DiscoverNodesOnStart: cfg.Engine.OpenSearch.Client.DiscoverNodesOnStart,
|
||||
DiscoverNodesInterval: cfg.Engine.OpenSearch.Client.DiscoverNodesInterval,
|
||||
EnableMetrics: cfg.Engine.OpenSearch.Client.EnableMetrics,
|
||||
EnableDebugLogger: cfg.Engine.OpenSearch.Client.EnableDebugLogger,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: cfg.Engine.OpenSearch.Client.Insecure,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if cfg.Engine.OpenSearch.Client.CACert != "" {
|
||||
certBytes, err := os.ReadFile(cfg.Engine.OpenSearch.Client.CACert)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read CA cert: %w", err)
|
||||
}
|
||||
clientConfig.CACert = certBytes
|
||||
}
|
||||
|
||||
client, err := opensearchgoAPI.NewClient(opensearchgoAPI.Config{Client: clientConfig})
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create OpenSearch client: %w", err)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user