Compare commits

...

26 Commits

Author SHA1 Message Date
Viktor Scharf
6589b4a1fe replace CI images 2025-12-24 11:24:55 +01:00
Florian Schade
19a8ff314d Merge pull request #2060 from fschade/fix-edition-error-and-default
Fix edition error and image arg default value
2025-12-23 10:37:50 +01:00
opencloudeu
97eb9a421e [tx] updated from transifex 2025-12-23 00:06:04 +00:00
Florian Schade
dd4b36a4bb fix(oci): set EDITION ard default value to dev which suppresses the init edition startup error 2025-12-22 15:57:51 +01:00
Florian Schade
50ef4f2ef1 fix: propagate the current edition channel in the edition validation error 2025-12-22 15:57:51 +01:00
opencloudeu
f341ad4fcb [tx] updated from transifex 2025-12-20 00:05:52 +00:00
Florian Schade
2e7b4dbb9c Merge pull request #2047 from fschade/issue-2044-cobra-flags
fix: cobra viper flags and env
2025-12-19 21:47:54 +01:00
Florian Schade
5486216350 fix: cobra viper flags and env 2025-12-19 12:15:48 +01:00
dependabot[bot]
4132d79ea6 build(deps): bump github.com/testcontainers/testcontainers-go/modules/opensearch
Bumps [github.com/testcontainers/testcontainers-go/modules/opensearch](https://github.com/testcontainers/testcontainers-go) from 0.39.0 to 0.40.0.
- [Release notes](https://github.com/testcontainers/testcontainers-go/releases)
- [Commits](https://github.com/testcontainers/testcontainers-go/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: github.com/testcontainers/testcontainers-go/modules/opensearch
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-19 10:36:27 +01:00
opencloudeu
9fb773891f [tx] updated from transifex 2025-12-19 00:06:36 +00:00
dependabot[bot]
21d5703b4a build(deps): bump golang.org/x/net from 0.47.0 to 0.48.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.47.0 to 0.48.0.
- [Commits](https://github.com/golang/net/compare/v0.47.0...v0.48.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-18 17:25:52 +01:00
Viktor Scharf
9b62a97857 [full-ci] use graph api in the enforcePasswordPublicLink.feature (#2050)
* use graph api in the enforcePasswordPublicLink.feature

* delete from expected failures file
2025-12-18 14:05:52 +01:00
dependabot[bot]
82c82f8ae2 build(deps): bump github.com/open-policy-agent/opa from 1.10.1 to 1.11.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.10.1 to 1.11.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.10.1...v1.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-18 13:33:02 +01:00
Jörn Friedrich Dreyer
5ed944dfc3 fix service name in suture logs
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2025-12-18 11:54:51 +01:00
opencloudeu
a7defc2d70 [tx] updated from transifex 2025-12-18 00:05:52 +00:00
opencloudeu
97070e2a05 [tx] updated from transifex 2025-12-17 00:04:21 +00:00
Jörn Friedrich Dreyer
196a4abfaa Merge pull request #2040 from opencloud-eu/http2
allow http2 connections to proxy
2025-12-16 17:13:42 +01:00
Jörn Friedrich Dreyer
79a0fe0cec devtools: use http2 for backend connection
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2025-12-16 14:34:22 +01:00
Sawjan Gurung
3ea736c283 [full-ci][tests-only] test: check last email content with retries as emails can be delayed (#2038)
* test: check last email content with retries

Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com>

* test: cleanup unused const

Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com>

---------

Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com>
2025-12-16 18:08:22 +05:45
Ralf Haferkamp
eb1545c087 fix(ci): use relative path for font to avoid hardcoded repo name 2025-12-16 12:56:48 +01:00
Ralf Haferkamp
e991facc29 fix(ci): Use woodpecker variable for repo name 2025-12-16 12:56:48 +01:00
Ralf Haferkamp
a95a7a1ada fix(ci): adjust default font path 2025-12-16 12:56:48 +01:00
Ralf Haferkamp
3446c1922b fix(ci): Use relative path to allow running from different fork 2025-12-16 12:56:48 +01:00
Ralf Haferkamp
5f40284abc fix: avoid hardcoded repo name 2025-12-16 12:56:48 +01:00
Jörn Friedrich Dreyer
b19307f1be allow http2 connections to proxy
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2025-12-16 12:03:55 +01:00
Viktor Scharf
06c401d755 skip collaborativePosix tests in CI (#2039) 2025-12-16 11:30:33 +01:00
227 changed files with 9250 additions and 3024 deletions

View File

@@ -3,7 +3,7 @@
# Repository
repo_slug = "opencloud-eu/opencloud"
repo_slug = "${CI_REPO}"
docker_repo_slug = "opencloudeu/opencloud"
# images
@@ -15,16 +15,16 @@ OPEN_SEARCH = "opensearchproject/opensearch:2"
INBUCKET_INBUCKET = "inbucket/inbucket"
MINIO_MC = "minio/mc:RELEASE.2021-10-07T04-19-58Z"
OC_CI_ALPINE = "owncloudci/alpine:latest"
OC_CI_BAZEL_BUILDIFIER = "owncloudci/bazel-buildifier:latest"
OC_CI_BAZEL_BUILDIFIER = "scharfvi/bazel-buildifier:latest"
OC_CI_CLAMAVD = "owncloudci/clamavd"
OC_CI_DRONE_ANSIBLE = "owncloudci/drone-ansible:latest"
OC_CI_GOLANG = "registry.heinlein.group/opencloud/golang-ci:1.25"
OC_CI_NODEJS = "owncloudci/nodejs:%s"
OC_CI_PHP = "owncloudci/php:%s"
OC_CI_WAIT_FOR = "owncloudci/wait-for:latest"
OC_CI_GOLANG = "quay.io/opencloudeu/golang-ci:1.25"
OC_CI_NODEJS = "scharfvi/nodeci:24"
OC_CI_NODEJS_ALPINE = "scharfvi/nodeci-alpine:24"
OC_CI_PHP = "scharfvi/php-ci:%s"
OC_CI_WAIT_FOR = "scharfvi/wait-for:latest"
OC_CS3_API_VALIDATOR = "opencloudeu/cs3api-validator:latest"
OC_LITMUS = "owncloudci/litmus:latest"
OC_UBUNTU = "owncloud/ubuntu:20.04"
ONLYOFFICE_DOCUMENT_SERVER = "onlyoffice/documentserver:7.5.1"
PLUGINS_DOCKER_BUILDX = "woodpeckerci/plugin-docker-buildx:latest"
PLUGINS_NOTATION = "registry.heinlein.group/opencloud/notation-wp-plugin:latest"
@@ -37,25 +37,24 @@ REDIS = "redis:6-alpine"
READY_RELEASE_GO = "woodpeckerci/plugin-ready-release-go:latest"
OPENLDAP = "bitnamilegacy/openldap:2.6"
DEFAULT_PHP_VERSION = "8.2"
DEFAULT_NODEJS_VERSION = "20"
DEFAULT_PHP_VERSION = "8.4"
CACHE_S3_SERVER = "https://s3.ci.opencloud.eu"
dirs = {
"base": "/woodpecker/src/github.com/opencloud-eu/opencloud",
"web": "/woodpecker/src/github.com/opencloud-eu/opencloud/webTestRunner",
"zip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip",
"webZip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/web.tar.gz",
"webPnpmZip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/web-pnpm.tar.gz",
"playwrightBrowsersArchive": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/playwright-browsers.tar.gz",
"baseGo": "/go/src/github.com/opencloud-eu/opencloud",
"base": "/woodpecker/src/github.com/%s" % repo_slug,
"web": "/woodpecker/src/github.com/%s/webTestRunner" % repo_slug,
"zip": "/woodpecker/src/github.com/%s/zip" % repo_slug,
"webZip": "/woodpecker/src/github.com/%s/zip/web.tar.gz" % repo_slug,
"webPnpmZip": "/woodpecker/src/github.com/%s/zip/web-pnpm.tar.gz" % repo_slug,
"playwrightBrowsersArchive": "/woodpecker/src/github.com/%s/zip/playwright-browsers.tar.gz" % repo_slug,
"baseGo": "/go/src/github.com/%s" % repo_slug,
"gobinTar": "go-bin.tar.gz",
"gobinTarPath": "/go/src/github.com/opencloud-eu/opencloud/go-bin.tar.gz",
"gobinTarPath": "/go/src/github.com/%s/go-bin.tar.gz" % repo_slug,
"opencloudConfig": "tests/config/woodpecker/opencloud-config.json",
"opencloudRevaDataRoot": "/woodpecker/src/github.com/opencloud-eu/opencloud/srv/app/tmp/ocis/owncloud/data",
"multiServiceOcBaseDataPath": "/woodpecker/src/github.com/opencloud-eu/opencloud/multiServiceData",
"ocWrapper": "/woodpecker/src/github.com/opencloud-eu/opencloud/tests/ocwrapper",
"opencloudRevaDataRoot": "/woodpecker/src/github.com/%s/srv/app/tmp/ocis/owncloud/data" % repo_slug,
"multiServiceOcBaseDataPath": "/woodpecker/src/github.com/%s/multiServiceData" % repo_slug,
"ocWrapper": "/woodpecker/src/github.com/%s/tests/ocwrapper" % repo_slug,
"bannedPasswordList": "tests/config/woodpecker/banned-password-list.txt",
"ocmProviders": "tests/config/woodpecker/providers.json",
"opencloudBinPath": "opencloud/bin",
@@ -137,7 +136,8 @@ config = {
"suites": [
"apiGraph",
"apiServiceAvailability",
"collaborativePosix",
# skip tests for collaborativePosix. see https://github.com/opencloud-eu/opencloud/issues/2036
#"collaborativePosix",
],
"skip": False,
"withRemotePhp": [True],
@@ -413,7 +413,7 @@ GRAPH_AVAILABLE_ROLES = "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5,a8d5fe5e-96e3-418d
workspace = \
{
"base": "/go",
"path": "src/github.com/opencloud-eu/opencloud/",
"path": "src/github.com/%s/" % repo_slug,
}
# minio mc environment variables
@@ -555,7 +555,6 @@ def main(ctx):
def cachePipeline(ctx, name, steps):
return {
"name": "build-%s-cache" % name,
"skip_clone": True,
"steps": steps,
"when": [
{
@@ -671,7 +670,7 @@ def cacheGoBin():
},
{
"name": "archive-go-bin",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
". ./.env",
"if $BIN_CACHE_FOUND; then exit 0; fi",
@@ -709,7 +708,7 @@ def restoreGoBinCache():
},
{
"name": "extract-go-bin-cache",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
"tar -xvmf %s -C /" % dirs["gobinTarPath"],
],
@@ -903,7 +902,7 @@ def checkGherkinLint(ctx):
"steps": [
{
"name": "lint-feature-files",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS_ALPINE,
"commands": [
"npm install -g @gherlint/gherlint@1.1.0",
"make test-gherkin-lint",
@@ -1231,7 +1230,7 @@ def wopiValidatorTests(ctx, storage, wopiServerType, accounts_hash_difficulty =
"commands": [
"curl -v -X PUT '%s/remote.php/webdav/test.wopitest' -k --fail --retry-connrefused --retry 7 --retry-all-errors -u admin:admin -D headers.txt" % OC_URL,
"cat headers.txt",
"export FILE_ID=$(cat headers.txt | sed -n -e 's/^.*Oc-Fileid: //p')",
"export FILE_ID=$(cat headers.txt | sed -n -e 's/^.*oc-fileid: //Ip')",
"export URL=\"%s/app/open?app_name=FakeOffice&file_id=$FILE_ID\"" % OC_URL,
"export URL=$(echo $URL | tr -d '[:cntrl:]')",
"curl -v -X POST \"$URL\" -k --fail --retry-connrefused --retry 7 --retry-all-errors -u admin:admin > open.json",
@@ -1408,7 +1407,7 @@ def e2eTestPipeline(ctx, watch_fs_enabled = False):
step_e2e = {
"name": "e2e-tests",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"environment": {
"OC_BASE_URL": OC_DOMAIN,
"HEADLESS": True,
@@ -1567,7 +1566,7 @@ def multiServiceE2ePipeline(ctx, watch_fs_enabled = False):
storage_users_services + \
[{
"name": "e2e-tests",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"environment": {
"OC_BASE_URL": OC_DOMAIN,
"HEADLESS": True,
@@ -1894,14 +1893,14 @@ def licenseCheck(ctx):
"steps": restoreGoBinCache() + [
{
"name": "node-check-licenses",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS_ALPINE,
"commands": [
"make ci-node-check-licenses",
],
},
{
"name": "node-save-licenses",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS_ALPINE,
"commands": [
"make ci-node-save-licenses",
],
@@ -2021,7 +2020,7 @@ def makeNodeGenerate(module):
return [
{
"name": "generate nodejs",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"environment": {
"CHROMEDRIVER_SKIP_DOWNLOAD": True, # install fails on arm and chromedriver is a test only dependency
},
@@ -2499,7 +2498,7 @@ def genericBuildArtifactCache(ctx, name, action, path):
return genericCache(name, action, [path], cache_path)
if action == "purge":
return purgeCache("purge_opencloud_build_artifact_cache", "cache/opencloud-eu/opencloud", 1)
return purgeCache("purge_opencloud_build_artifact_cache", "cache/%s" % repo_slug, 1)
return []
def restoreBuildArtifactCache(ctx, name, path):
@@ -2694,7 +2693,7 @@ def litmus(ctx, storage):
def setupForLitmus():
return [{
"name": "setup-for-litmus",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"environment": {
"TEST_SERVER_URL": OC_URL,
},
@@ -2705,15 +2704,13 @@ def setupForLitmus():
}]
def getWoodpeckerEnvAndCheckScript(ctx):
opencloud_git_base_url = "https://raw.githubusercontent.com/opencloud-eu/opencloud"
path_to_woodpecker_env = "%s/%s/.woodpecker.env" % (opencloud_git_base_url, ctx.build.commit)
path_to_check_script = "%s/%s/tests/config/woodpecker/check_web_cache.sh" % (opencloud_git_base_url, ctx.build.commit)
path_to_woodpecker_env = "%s/.woodpecker.env" % dirs["base"]
path_to_check_script = "%s/tests/config/woodpecker/check_web_cache.sh" % dirs["base"]
return {
"name": "get-woodpecker-env-and-check-script",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
"curl -s -o .woodpecker.env %s" % path_to_woodpecker_env,
"curl -s -o check_web_cache.sh %s" % path_to_check_script,
"cp %s check_web_cache.sh" % path_to_check_script,
],
}
@@ -2730,7 +2727,7 @@ def checkForWebCache(name):
def cloneWeb():
return {
"name": "clone-web",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS_ALPINE,
"commands": [
". ./.woodpecker.env",
"if $WEB_CACHE_FOUND; then exit 0; fi",
@@ -2747,7 +2744,7 @@ def generateWebPnpmCache(ctx):
cloneWeb(),
{
"name": "install-pnpm",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"commands": [
". ./.woodpecker.env",
"if $WEB_CACHE_FOUND; then exit 0; fi",
@@ -2759,7 +2756,7 @@ def generateWebPnpmCache(ctx):
},
{
"name": "zip-pnpm",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"commands": [
". ./.woodpecker.env",
"if $WEB_CACHE_FOUND; then exit 0; fi",
@@ -2821,7 +2818,7 @@ def cacheBrowsers(ctx):
browser_cache_steps = [
{
"name": "install-browsers",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"environment": {
"PLAYWRIGHT_BROWSERS_PATH": ".playwright",
},
@@ -2829,7 +2826,7 @@ def cacheBrowsers(ctx):
"cd %s" % dirs["web"],
". ./.woodpecker.env",
"if $BROWSER_CACHE_FOUND; then exit 0; fi",
"pnpm exec playwright install --with-deps",
"pnpm exec playwright install",
"pnpm exec playwright install --list",
"tar -czf %s .playwright" % dirs["playwrightBrowsersArchive"],
],
@@ -2864,7 +2861,7 @@ def generateWebCache(ctx):
cloneWeb(),
{
"name": "zip-web",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
". ./.woodpecker.env",
"if $WEB_CACHE_FOUND; then exit 0; fi",
@@ -2900,7 +2897,7 @@ def restoreWebCache():
],
}, {
"name": "unzip-web-cache",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
"tar -xf %s -C ." % dirs["webZip"],
],
@@ -2919,7 +2916,7 @@ def restoreWebPnpmCache(extra_commands = []):
}, {
# we need to install again because the node_modules are not cached
"name": "unzip-and-install-pnpm",
"image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
"image": OC_CI_NODEJS,
"commands": extra_commands + [
"cd %s" % dirs["web"],
"rm -rf .pnpm-store",
@@ -2945,9 +2942,9 @@ def restoreBrowsersCache():
},
{
"name": "unzip-browsers-cache",
"image": OC_UBUNTU,
"image": OC_CI_NODEJS,
"commands": [
"tar -xf /woodpecker/src/github.com/opencloud-eu/opencloud/webTestRunner/playwright-browsers.tar.gz -C .",
"tar -xf /woodpecker/src/github.com/%s/webTestRunner/playwright-browsers.tar.gz -C ." % repo_slug,
],
},
]
@@ -2963,7 +2960,7 @@ def waitForEmailService():
"name": "wait-for-email",
"image": OC_CI_WAIT_FOR,
"commands": [
"wait-for -it email:9000 -t 600",
"wait-for -host email -port 9000 -timeout 600",
],
}]
@@ -2978,7 +2975,7 @@ def waitForClamavService():
"name": "wait-for-clamav",
"image": OC_CI_WAIT_FOR,
"commands": [
"wait-for -it clamav:3310 -t 600",
"wait-for -host clamav -port 3310 -timeout 600",
],
}]
@@ -3021,7 +3018,7 @@ def waitForLdapService():
"name": "wait-for-ldap",
"image": OC_CI_WAIT_FOR,
"commands": [
"wait-for -it ldap-server:1636 -t 600",
"wait-for -host ldap-server -port 1636 -timeout 600",
],
}]
@@ -3084,7 +3081,7 @@ def tikaService():
"name": "wait-for-tika-service",
"image": OC_CI_WAIT_FOR,
"commands": [
"wait-for -it tika:9998 -t 300",
"wait-for -host tika -port 9998 -timeout 300",
],
}]
@@ -3135,7 +3132,7 @@ def k6LoadTests(ctx):
if "skip" in config["k6LoadTests"] and config["k6LoadTests"]["skip"]:
return []
opencloud_git_base_url = "https://raw.githubusercontent.com/opencloud-eu/opencloud"
opencloud_git_base_url = "https://raw.githubusercontent.com/%s" % repo_slug
script_link = "%s/%s/tests/config/woodpecker/run_k6_tests.sh" % (opencloud_git_base_url, ctx.build.commit)
event_array = ["cron"]
@@ -3194,13 +3191,18 @@ def k6LoadTests(ctx):
}]
def waitForServices(name, services = []):
services = ",".join(services)
commands = []
for service in services:
host, port = service.split(":", 1)
commands.append(
"wait-for -host %s -port %s -timeout 300" % (host, port),
)
return [{
"name": "wait-for-%s" % name,
"image": OC_CI_WAIT_FOR,
"commands": [
"wait-for -it %s -t 300" % services,
],
"commands": commands,
}]
def openCloudHealthCheck(name, services = []):

View File

@@ -19,6 +19,11 @@ services:
- "--entryPoints.http.http.redirections.entryPoint.to=https"
- "--entryPoints.http.http.redirections.entryPoint.scheme=https"
- "--entryPoints.https.address=:443"
# http2 optimizations
- "--entryPoints.https.http2.maxConcurrentStreams=512"
- "--serversTransport.maxIdleConnsPerHost=100"
# allow self signed certificate from OpenCloud
- "--serversTransport.insecureSkipVerify=true"
# change default timeouts for long-running requests
# this is needed for webdav clients that do not support the TUS protocol
- "--entryPoints.https.transport.respondingTimeouts.readTimeout=12h"

View File

@@ -25,7 +25,7 @@ services:
OC_LOG_COLOR: "${LOG_PRETTY:-false}"
OC_LOG_PRETTY: "${LOG_PRETTY:-false}"
# do not use SSL between Traefik and OpenCloud
PROXY_TLS: "false"
PROXY_TLS: "true"
# make the REVA gateway accessible to the app drivers
GATEWAY_GRPC_ADDR: 0.0.0.0:9142
# INSECURE: needed if OpenCloud / Traefik is using self generated certificates
@@ -72,6 +72,7 @@ services:
- "traefik.http.routers.opencloud.tls.certresolver=http"
- "traefik.http.routers.opencloud.service=opencloud"
- "traefik.http.services.opencloud.loadbalancer.server.port=9200"
- "traefik.http.services.opencloud.loadbalancer.server.scheme=https"
logging:
driver: ${LOG_DRIVER:-local}
restart: always

34
go.mod
View File

@@ -61,7 +61,7 @@ require (
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.11.1
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.41.0
@@ -83,7 +83,7 @@ require (
github.com/stretchr/testify v1.11.1
github.com/test-go/testify v1.1.4
github.com/testcontainers/testcontainers-go v0.40.0
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0
github.com/theckman/yacspin v0.13.12
github.com/thejerf/suture/v4 v4.0.6
github.com/tidwall/gjson v1.18.0
@@ -102,14 +102,14 @@ require (
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
golang.org/x/crypto v0.45.0
golang.org/x/crypto v0.46.0
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
golang.org/x/image v0.33.0
golang.org/x/net v0.47.0
golang.org/x/net v0.48.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/sync v0.19.0
golang.org/x/term v0.38.0
golang.org/x/text v0.32.0
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.10
@@ -172,7 +172,7 @@ require (
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/containerd/platforms v1.0.0-rc.2 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
github.com/cornelk/hashmap v1.0.8 // indirect
@@ -237,7 +237,7 @@ require (
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/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomodule/redigo v1.9.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -271,7 +271,7 @@ require (
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.1 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.11 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.12 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/libregraph/oidc-go v1.1.0 // indirect
@@ -302,7 +302,7 @@ require (
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -341,7 +341,7 @@ require (
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/asm v1.2.1 // indirect
github.com/segmentio/kafka-go v0.4.49 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
@@ -367,9 +367,9 @@ require (
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
github.com/trustelem/zxcvbn v1.0.1 // indirect
github.com/urfave/cli/v2 v2.27.5 // indirect
github.com/urfave/cli/v2 v2.27.7 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
github.com/vektah/gqlparser/v2 v2.5.31 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wk8/go-ordered-map v1.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
@@ -390,10 +390,10 @@ require (
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.38.0 // indirect
golang.org/x/tools v0.39.0 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect

70
go.sum
View File

@@ -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/v39 v39.0.1 h1:RibaT47yiyCRxMOj/l2cvL8cWiWBSqDXHyqsa9sGcCE=
github.com/bytecodealliance/wasmtime-go/v39 v39.0.1/go.mod h1:miR4NYIEBXeDNamZIzpskhJ0z/p8al+lwMWylQ/ZJb4=
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=
@@ -239,8 +239,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
github.com/containerd/platforms v1.0.0-rc.2/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=
@@ -511,8 +511,9 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -776,8 +777,8 @@ github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZ
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc/v3 v3.0.1 h1:3n7Es68YYGZb2Jf+k//llA4FTZMl3yCwIjFIk4ubevI=
github.com/lestrrat-go/httprc/v3 v3.0.1/go.mod h1:2uAvmbXE4Xq8kAUjVrZOq1tZVYYYs5iP62Cmtru00xk=
github.com/lestrrat-go/jwx/v3 v3.0.11 h1:yEeUGNUuNjcez/Voxvr7XPTYNraSQTENJgtVTfwvG/w=
github.com/lestrrat-go/jwx/v3 v3.0.11/go.mod h1:XSOAh2SiXm0QgRe3DulLZLyt+wUuEdFo81zuKTLcvgQ=
github.com/lestrrat-go/jwx/v3 v3.0.12 h1:p25r68Y4KrbBdYjIsQweYxq794CtGCzcrc5dGzJIRjg=
github.com/lestrrat-go/jwx/v3 v3.0.12/go.mod h1:HiUSaNmMLXgZ08OmGBaPVvoZQgJVOQphSrGr5zMamS8=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss=
@@ -897,8 +898,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@@ -955,8 +957,8 @@ 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.11.1 h1:4bMlG6DjRZTRAswRyF+KUCgxHu1Gsk0h9EbZ4W9REvM=
github.com/open-policy-agent/opa v1.11.1/go.mod h1:QimuJO4T3KYxWzrmAymqlFvsIanCjKrGjmmC8GgAdgE=
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=
@@ -1107,8 +1109,8 @@ github.com/samber/slog-zerolog/v2 v2.9.0 h1:6LkOabJmZdNLaUWkTC3IVVA+dq7b/V0FM6lz
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=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/kafka-go v0.4.49 h1:GJiNX1d/g+kG6ljyJEoi9++PUMdXGAxb7JGPiDCuNmk=
github.com/segmentio/kafka-go v0.4.49/go.mod h1:Y1gn60kzLEEaW28YshXyk2+VCUKbJ3Qr6DrnT3i4+9E=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
@@ -1204,8 +1206,8 @@ github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE
github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU=
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0 h1:IkJUhR8AigQxv7qHZho/OtTU6JtiSdBGVh76o175JGo=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0/go.mod h1:B7AhrDmQ4QbpzA0BeWvqzaJ8vbwcdEQDzybr35sBRfw=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0 h1:3TIrGk0zXyO9CG2N6APo7auwWIwAvhkwE1reISif8LM=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0/go.mod h1:VA0UCTPu+Gcs7MzdzBnSl0qDnxquuphv3ngSGdX97Xs=
github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o=
github.com/thanhpk/randstr v1.0.6/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4=
@@ -1239,15 +1241,15 @@ github.com/tus/tusd/v2 v2.8.0/go.mod h1:3/zEOVQQIwmJhvNam8phV4x/UQt68ZmZiTzeuJUN
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE=
github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/vektah/gqlparser/v2 v2.5.31 h1:YhWGA1mfTjID7qJhd1+Vxhpk5HTgydrGU9IgkWBTJ7k=
github.com/vektah/gqlparser/v2 v2.5.31/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts=
github.com/vinyldns/go-vinyldns v0.0.0-20200917153823-148a5f6b8f14/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
@@ -1373,8 +1375,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.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
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=
@@ -1416,8 +1418,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.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
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=
@@ -1471,8 +1473,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1499,8 +1501,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.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.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=
@@ -1584,8 +1586,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.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=
@@ -1597,8 +1599,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.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.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
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=
@@ -1613,8 +1615,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
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=
@@ -1677,8 +1679,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
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=

View File

@@ -3,7 +3,7 @@ ARG TARGETOS
ARG TARGETARCH
ARG VERSION
ARG STRING
ARG EDITION
ARG EDITION="dev"
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev

View File

@@ -23,7 +23,7 @@ func InitCommand(_ *config.Config) *cobra.Command {
Short: "initialise an OpenCloud config",
GroupID: CommandGroupServer,
RunE: func(cmd *cobra.Command, args []string) error {
insecureFlag, _ := cmd.Flags().GetString("insecure")
insecureFlag := viper.GetString("insecure")
insecure := false
if insecureFlag == "ask" {
answer := strings.ToLower(stringPrompt("Do you want to configure OpenCloud with certificate checking disabled?\n This is not recommended for public instances! [yes | no = default]"))
@@ -33,10 +33,10 @@ func InitCommand(_ *config.Config) *cobra.Command {
} else if insecureFlag == strings.ToLower("true") || insecureFlag == strings.ToLower("yes") || insecureFlag == strings.ToLower("y") {
insecure = true
}
forceOverwriteFlag, _ := cmd.Flags().GetBool("force-overwrite")
diffFlag, _ := cmd.Flags().GetBool("force-overwrite")
configPathFlag, _ := cmd.Flags().GetString("config-path")
adminPasswordFlag, _ := cmd.Flags().GetString("admin-password")
forceOverwriteFlag := viper.GetBool("force-overwrite")
diffFlag, _ := cmd.Flags().GetBool("diff")
configPathFlag := viper.GetString("config-path")
adminPasswordFlag := viper.GetString("admin-password")
err := ocinit.CreateConfig(insecure, forceOverwriteFlag, diffFlag, configPathFlag, adminPasswordFlag)
if err != nil {
log.Fatalf("Could not create config: %s", err)
@@ -74,7 +74,7 @@ func stringPrompt(label string) string {
input := ""
reader := bufio.NewReader(os.Stdin)
for {
fmt.Fprint(os.Stderr, label+" ")
_, _ = fmt.Fprint(os.Stderr, label+" ")
input, _ = reader.ReadString('\n')
if input != "" {
break

View File

@@ -8,6 +8,8 @@ import (
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/config/parser"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@@ -18,8 +20,14 @@ func ListCommand(cfg *config.Config) *cobra.Command {
listCmd := &cobra.Command{
Use: "list",
Short: "list OpenCloud services running in the runtime (supervised mode)",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return configlog.ReturnError(parser.ParseConfig(cfg, true))
},
RunE: func(cmd *cobra.Command, args []string) error {
client, err := rpc.DialHTTP("tcp", net.JoinHostPort(cfg.Runtime.Host, cfg.Runtime.Port))
host := viper.GetString("hostname")
port := viper.GetString("port")
client, err := rpc.DialHTTP("tcp", net.JoinHostPort(host, port))
if err != nil {
log.Fatalf("Failed to connect to the runtime. Has the runtime been started and did you configure the right runtime address (\"%s\")", cfg.Runtime.Host+":"+cfg.Runtime.Port)
}
@@ -35,6 +43,7 @@ func ListCommand(cfg *config.Config) *cobra.Command {
return nil
},
}
listCmd.Flags().String("hostname", "localhost", "hostname of the runtime")
_ = viper.BindEnv("hostname", "OC_RUNTIME_HOST")
_ = viper.BindPFlag("hostname", listCmd.Flags().Lookup("hostname"))

View File

@@ -3,6 +3,8 @@ package command
import (
"errors"
"github.com/spf13/viper"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
@@ -15,7 +17,6 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3"
"github.com/opencloud-eu/reva/v2/pkg/share/manager/registry"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/spf13/viper"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
@@ -77,7 +78,7 @@ func cleanupCmd(cfg *config.Config) *cobra.Command {
return cleanCmd
}
func cleanup(cmd *cobra.Command, cfg *config.Config) error {
func cleanup(_ *cobra.Command, cfg *config.Config) error {
driver := cfg.Sharing.UserSharingDriver
// cleanup is only implemented for the jsoncs3 share manager
if driver != "jsoncs3" {
@@ -108,8 +109,8 @@ func cleanup(cmd *cobra.Command, cfg *config.Config) error {
return configlog.ReturnError(err)
}
serviceAccountIDFlag, _ := cmd.Flags().GetString("service-account-id")
serviceAccountSecretFlag, _ := cmd.Flags().GetString("service-account-secret")
serviceAccountIDFlag := viper.GetString("service-account-id")
serviceAccountSecretFlag := viper.GetString("service-account-secret")
serviceUserCtx, err := utils.GetServiceUserContext(serviceAccountIDFlag, client, serviceAccountSecretFlag)
if err != nil {
return configlog.ReturnError(err)
@@ -167,39 +168,6 @@ func revaShareConfig(cfg *sharing.Config) map[string]interface{} {
}
}
func revaPublicShareConfig(cfg *sharing.Config) map[string]interface{} {
return map[string]interface{}{
"json": map[string]interface{}{
"file": cfg.PublicSharingDrivers.JSON.File,
"gateway_addr": cfg.Reva.Address,
},
"jsoncs3": map[string]interface{}{
"gateway_addr": cfg.Reva.Address,
"provider_addr": cfg.PublicSharingDrivers.JSONCS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.JSONCS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.JSONCS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.JSONCS3.SystemUserAPIKey,
},
"sql": map[string]interface{}{
"db_username": cfg.PublicSharingDrivers.SQL.DBUsername,
"db_password": cfg.PublicSharingDrivers.SQL.DBPassword,
"db_host": cfg.PublicSharingDrivers.SQL.DBHost,
"db_port": cfg.PublicSharingDrivers.SQL.DBPort,
"db_name": cfg.PublicSharingDrivers.SQL.DBName,
"password_hash_cost": cfg.PublicSharingDrivers.SQL.PasswordHashCost,
"enable_expired_shares_cleanup": cfg.PublicSharingDrivers.SQL.EnableExpiredSharesCleanup,
"janitor_run_interval": cfg.PublicSharingDrivers.SQL.JanitorRunInterval,
},
"cs3": map[string]interface{}{
"gateway_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr,
"provider_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.CS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.CS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.CS3.SystemUserAPIKey,
},
}
}
func logger() *zerolog.Logger {
log := oclog.NewLogger(
oclog.Name("migrate"),

View File

@@ -124,7 +124,7 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) {
if s.Services[priority] == nil {
s.Services[priority] = make(serviceFuncMap)
}
s.Services[priority][name] = NewSutureServiceBuilder(exec)
s.Services[priority][name] = NewSutureServiceBuilder(name, exec)
}
// nats is in priority group 0. It needs to start before all other services
@@ -316,7 +316,7 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) {
// populate optional services
areg := func(name string, exec func(context.Context, *occfg.Config) error) {
s.Additional[name] = NewSutureServiceBuilder(exec)
s.Additional[name] = NewSutureServiceBuilder(name, exec)
}
areg(opts.Config.Antivirus.Service.Name, func(ctx context.Context, cfg *occfg.Config) error {
cfg.Antivirus.Context = ctx

View File

@@ -10,15 +10,17 @@ import (
// SutureService allows for the settings command to be embedded and supervised by a suture supervisor tree.
type SutureService struct {
exec func(ctx context.Context) error
name string
}
// NewSutureServiceBuilder creates a new suture service
func NewSutureServiceBuilder(f func(context.Context, *occfg.Config) error) func(*occfg.Config) suture.Service {
func NewSutureServiceBuilder(name string, f func(context.Context, *occfg.Config) error) func(*occfg.Config) suture.Service {
return func(cfg *occfg.Config) suture.Service {
return SutureService{
exec: func(ctx context.Context) error {
return f(ctx, cfg)
},
name: name,
}
}
}
@@ -27,3 +29,8 @@ func NewSutureServiceBuilder(f func(context.Context, *occfg.Config) error) func(
func (s SutureService) Serve(ctx context.Context) error {
return s.exec(ctx)
}
// String to fullfil fmt.Stringer interface, used to log the service name
func (s SutureService) String() string {
return s.name
}

View File

@@ -49,6 +49,8 @@ func NewService(opts ...Option) (Service, error) {
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
NextProtos: []string{"h2", "http/1.1"},
}
mServer = mhttps.NewServer(server.TLSConfig(tlsConfig))
} else {

View File

@@ -79,8 +79,11 @@ func initEdition() error {
_, err := semver.NewVersion(editionParts[1])
return err == nil
}) {
Edition = Dev
return fmt.Errorf(`unknown edition channel "%s"`, Edition)
defer func() {
Edition = Dev
}()
return fmt.Errorf(`unknown edition channel '%s'`, Edition)
}
return nil

View File

@@ -2,6 +2,7 @@ package version_test
import (
"fmt"
"strings"
"testing"
"github.com/opencloud-eu/opencloud/pkg/version"
@@ -59,6 +60,8 @@ func TestChannel(t *testing.T) {
fallthrough
case test.valid != (err == nil):
t.Fatalf("invalid edition: %s", version.Edition)
case !test.valid && !strings.Contains(err.Error(), "'"+test.got+"'"):
t.Fatalf("no mention of invalid edition '%s' in error: %s", test.got, err.Error())
}
})
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,102 @@
# 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:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-18 00:04+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "詳細"
#: pkg/service/response.go:43
msgid "display name"
msgstr "表示名"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "有効期限"
#: pkg/service/response.go:41
msgid "password"
msgstr "パスワード"
#: pkg/service/response.go:40
msgid "permission"
msgstr "権限"
#: pkg/service/response.go:39
msgid "some field"
msgstr "特定の項目"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} が公開リンク {token} 経由でダウンロードされました"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} が %{resource} を {folder} に追加しました"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} が {sharee} を {space} のメンバーに追加しました"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} が {folder} から {resource} を削除しました"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} が {resource} を {folder} に移動しました"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} が {resource} へのリンクを解除しました"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} が {resource} の共有から {sharee} を削除しました"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} が {space} の共有から {sharee} を削除しました"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} が {oldResource} の名前を {resource} に変更しました"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} がリンク経由で {resource} を共有しました"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} が {resource} を {sharee} と共有しました"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} が {resource} のリンク {token}の {field} を更新しました"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} が {resource} の {field} を更新しました"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} が {folder} 内の {resource} を更新しました"

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,102 @@
# 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:
# Quan Tran, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-17 00:03+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Quan Tran, 2025\n"
"Language-Team: Vietnamese (https://app.transifex.com/opencloud-eu/teams/204053/vi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "mô tả"
#: pkg/service/response.go:43
msgid "display name"
msgstr "tên hiển thị"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "ngày hết hạn"
#: pkg/service/response.go:41
msgid "password"
msgstr "mật khẩu"
#: pkg/service/response.go:40
msgid "permission"
msgstr "quyền"
#: pkg/service/response.go:39
msgid "some field"
msgstr "một số trường"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} được tải xuống qua đường dẫn công khai {token}"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} thêm {resource} vào {folder}"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} thêm {sharee} vào {space}"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} xóa {resource} khỏi {folder}"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} chuyển{resource} đến {folder}"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} xóa đường liên kết tới {resource}"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} xóa {sharee} khỏi {resource}"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} xóa {sharee} khỏi {space}"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} đổi tên {oldResource} thành {resource}"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} chia sẻ {resource} qua đường liên kết"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} chia sẻ {resource} với {sharee}"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} cập nhật {field} của đường liên kết {token} đến {resource}"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} cập nhật {field} của {resource}"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} cập nhật {resource} trong {folder}"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,130 @@
# 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:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-18 00:04+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\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 "編集可"
#. 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 "管理可能"
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:152
msgid "Can upload"
msgstr "アップロード可能"
#. 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 "閲覧可能"
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:164
msgid "Can view (secure)"
msgstr "セキュア閲覧(閲覧のみ)"
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:170
msgid "Cannot access"
msgstr "アクセス不可"
#. UnifiedRole FullDenial, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:167
msgid "Deny all access."
msgstr "すべてのアクセスを拒否"
#. default description for new spaces
#: pkg/service/v0/spacetemplates.go:32
msgid "Here you can add a description for this Space."
msgstr "説明を追加"
#. 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 "閲覧とダウンロード"
#. UnifiedRole SecureViewer, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:161
msgid "View only documents, images and PDFs. Watermarks will be applied."
msgstr "ドキュメント、画像、PDFの閲覧のみ。透かしウォーターマークが適用"
#. UnifiedRole FileEditor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:137
msgid "View, download and edit."
msgstr "閲覧、ダウンロード、編集"
#. 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 "閲覧、ダウンロード、アップロード"
#. 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 "閲覧、ダウンロード、アップロード、編集、追加、削除"
#. UnifiedRole Manager, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:155
msgid "View, download, upload, edit, add, delete and manage members."
msgstr "閲覧、ダウンロード、アップロード、編集、追加、削除、およびメンバー管理"
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:119
msgid "View, download, upload, edit, add, delete and show all invited people."
msgstr "閲覧、ダウンロード、アップロード、編集、追加、削除、および全招待ユーザーの表示"
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:125
msgid "View, download, upload, edit, add, delete including the history."
msgstr "閲覧、ダウンロード、アップロード、編集、追加、削除(履歴を含む)"

View File

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

View File

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

View File

@@ -0,0 +1,132 @@
# 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:
# Quan Tran, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-17 00:03+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Quan Tran, 2025\n"
"Language-Team: Vietnamese (https://app.transifex.com/opencloud-eu/teams/204053/vi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0;\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 "Có quyền chỉnh sửa"
#. UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves
#. directly)
#: pkg/unifiedrole/roles.go:134
msgid "Can edit without versions"
msgstr "Có quyền chỉnh sửa không tạo phiên bản"
#. UnifiedRole Manager, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:158
msgid "Can manage"
msgstr "Có quyền quản lý"
#. UnifiedRole EditorLite, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:152
msgid "Can upload"
msgstr "Có quyền đăng tải"
#. 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 "Có quyền xem"
#. UnifiedRole SecureViewer, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:164
msgid "Can view (secure)"
msgstr "Có quyền xem (bảo mật)"
#. UnifiedRole FullDenial, Role DisplayName (resolves directly)
#: pkg/unifiedrole/roles.go:170
msgid "Cannot access"
msgstr "Không có quyền truy cập"
#. UnifiedRole FullDenial, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:167
msgid "Deny all access."
msgstr "Cấm mọi quyền truy cập."
#. default description for new spaces
#: pkg/service/v0/spacetemplates.go:32
msgid "Here you can add a description for this Space."
msgstr ""
#. 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 "Xem và tải về."
#. UnifiedRole SecureViewer, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:161
msgid "View only documents, images and PDFs. Watermarks will be applied."
msgstr "Chỉ được xem tài liệu, hình ảnh và PDF. Sẽ hiển thị hình mờ."
#. UnifiedRole FileEditor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:137
msgid "View, download and edit."
msgstr "Xem, tải về và chỉnh sửa."
#. UnifiedRole ViewerListGrants, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:101
msgid "View, download and show all invited people."
msgstr "Xem, tải về và hiển thị danh sách người được mời."
#. UnifiedRole EditorLite, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:149
msgid "View, download and upload."
msgstr "Xem, tải về và tải lên."
#. UnifiedRole FileEditorListGrants, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:143
msgid "View, download, edit and show all invited people."
msgstr "Xem, tải về, chỉnh sửa và hiển thị danh sách người được mời."
#. 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 "Xem, tải về, tải lên, chỉnh sửa, thêm và xóa."
#. UnifiedRole Manager, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:155
msgid "View, download, upload, edit, add, delete and manage members."
msgstr "Xem, tải về, tải lên, chỉnh sửa, thêm, xóa và quản lý thành viên."
#. UnifiedRoleListGrants Editor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:119
msgid "View, download, upload, edit, add, delete and show all invited people."
msgstr ""
"Xem, tải về, tải lên, chỉnh sửa, thêm, xóa và hiển thị danh sách người được "
"mời."
#. UnifiedRole SpaseEditor, Role Description (resolves directly)
#: pkg/unifiedrole/roles.go:125
msgid "View, download, upload, edit, add, delete including the history."
msgstr "Xem, tải về, tải lên, chỉnh sửa, thêm và xóa bao gồm lịch sử."

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,176 @@
# 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:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-18 00:04+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#. UnsharedSpace email template, resolves via {{ .CallToAction }}
#: pkg/email/templates.go:65
msgid "Click here to check it: {ShareLink}"
msgstr "こちらをクリックして確認してください: {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 "こちらをクリックして表示してください: {ShareLink}"
#. ShareCreated email template, resolves via {{ .Greeting }}
#: pkg/email/templates.go:19
msgid "Hello {ShareGrantee}"
msgstr "{Grantee} 様"
#. ShareExpired email template, resolves via {{ .Greeting }}
#: pkg/email/templates.go:32
msgid "Hello {ShareGrantee},"
msgstr "{Grantee} 様"
#. 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 "{Grantee} 様"
#. Grouped email template, resolves via {{ .Greeting }}
#: pkg/email/templates.go:118
msgid "Hi {DisplayName},"
msgstr "{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 "こんにちは"
#. MembershipExpired email template, Subject field (resolves directly)
#: pkg/email/templates.go:72
msgid "Membership of '{SpaceName}' expired at {ExpiredAt}"
msgstr "「{SpaceName}」のメンバーシップ期限が {ExpiredAt} に終了しました"
#. Grouped email template, Subject field (resolves directly)
#: pkg/email/templates.go:116
msgid "Report"
msgstr "レポート"
#. 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} があなたとのコラボレーションを希望しています"
#. ShareExpired email template, Subject field (resolves directly)
#: pkg/email/templates.go:30
msgid "Share to '{ShareFolder}' expired at {ExpiredAt}"
msgstr "「{ShareFolder}」の共有期限が {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 ""
"スペース「{SpaceName}」のメンバーシップ期限が {ExpiredAt} に終了しました\n"
"\n"
"期限は終了しましたが、他の共有やメンバーシップを通じて引き続きアクセスできる場合があります"
#. 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 ""
"「{ShareFolder}」の共有期限が {ExpiredAt} に終了しました\n"
"\n"
"共有は解除されましたが、他の共有やメンバーシップを通じて引き続きアクセスできる場合があります"
#. 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}) があなたとリソースの共有を希望しています\n"
"フェデレーション設定に移動し、以下の情報を入力してください\n"
"トークン: {Token} プロバイダドメイン: {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}) があなたとリソースの共有を希望しています。\n"
"招待を承諾するには、以下のURLにアクセスしてください。 {ShareLink}\n"
"\n"
"または、フェデレーション設定で以下の情報を使用することもできます。 \n"
"トークン: {Token} プロバイダドメイン: {ProviderDomain}"
#. ShareCreated email template, resolves via {{ .MessageBody }}
#: pkg/email/templates.go:21
msgid "{ShareSharer} has shared \"{ShareFolder}\" with you."
msgstr "{ShareSharer} が「{ShareFolder}」を共有しました"
#. ShareCreated email template, Subject field (resolves directly)
#: pkg/email/templates.go:17
msgid "{ShareSharer} shared '{ShareFolder}' with you"
msgstr "{ShareSharer} が「{ShareFolder}」を共有しました"
#. SharedSpace email template, resolves via {{ .MessageBody }}
#: pkg/email/templates.go:48
msgid "{SpaceSharer} has invited you to join \"{SpaceName}\"."
msgstr "{SpaceSharer} があなたを「{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} があなたを「{SpaceName}」から削除しました。\n"
"\n"
"他のグループや直接のメンバーシップを通じて、引き続きアクセスできる可能性があります。"
#. SharedSpace email template, Subject field (resolves directly)
#: pkg/email/templates.go:44
msgid "{SpaceSharer} invited you to join {SpaceName}"
msgstr "{SpaceSharer} があなたを「{SpaceName}」に招待しました"
#. UnsharedSpace email template, Subject field (resolves directly)
#: pkg/email/templates.go:57
msgid "{SpaceSharer} removed you from {SpaceName}"
msgstr "{SpaceSharer} があなたを「{SpaceName}」から削除しました。"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,144 @@
# 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:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-18 00:04+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#. name of the notification option 'Space Shared'
#: pkg/store/defaults/templates.go:20
msgid "Added as space member"
msgstr "スペースメンバーへの追加"
#. translation for the 'daily' email interval option
#: pkg/store/defaults/templates.go:50
msgid "Daily"
msgstr "毎日"
#. name of the notification option 'Email Interval'
#: pkg/store/defaults/templates.go:44
msgid "Email sending interval"
msgstr "メール送信間隔"
#. name of the notification option 'File Rejected'
#: pkg/store/defaults/templates.go:40
msgid "File rejected"
msgstr "ファイルの拒否"
#. translation for the 'instant' email interval option
#: pkg/store/defaults/templates.go:48
msgid "Instant"
msgstr "即時 "
#. translation for the 'never' email interval option
#: pkg/store/defaults/templates.go:54
msgid "Never"
msgstr "しない"
#. description of the notification option 'Space Shared'
#: pkg/store/defaults/templates.go:22
msgid "Notify when I have been added as a member to a space"
msgstr "スペースのメンバーに追加された時に通知する"
#. description of the notification option 'Space Unshared'
#: pkg/store/defaults/templates.go:26
msgid "Notify when I have been removed as member from a space"
msgstr "スペースのメンバーから削除された時に通知する"
#. description of the notification option 'Share Received'
#: pkg/store/defaults/templates.go:10
msgid "Notify when I have received a share"
msgstr "共有を受け取った時に通知する"
#. description of the notification option 'File Rejected'
#: pkg/store/defaults/templates.go:42
msgid ""
"Notify when a file I uploaded was rejected because of a virus infection or "
"policy violation"
msgstr "アップロードしたファイルがウイルスやポリシー違反で拒否された時に通知する"
#. description of the notification option 'Share Removed'
#: pkg/store/defaults/templates.go:14
msgid "Notify when a received share has been removed"
msgstr "受け取った共有が削除された時に通知する"
#. description of the notification option 'Share Expired'
#: pkg/store/defaults/templates.go:18
msgid "Notify when a received share has expired"
msgstr "受け取った共有の期限が切れた時に通知する"
#. description of the notification option 'Space Deleted'
#: pkg/store/defaults/templates.go:38
msgid "Notify when a space I am member of has been deleted"
msgstr "参加しているスペースが削除された時に通知する"
#. description of the notification option 'Space Disabled'
#: pkg/store/defaults/templates.go:34
msgid "Notify when a space I am member of has been disabled"
msgstr "参加しているスペースが無効化された時に通知する"
#. description of the notification option 'Space Membership Expired'
#: pkg/store/defaults/templates.go:30
msgid "Notify when a space membership has expired"
msgstr "スペースのメンバーシップ期限が切れた時に通知する"
#. name of the notification option 'Space Unshared'
#: pkg/store/defaults/templates.go:24
msgid "Removed as space member"
msgstr "スペースメンバーからの削除"
#. description of the notification option 'Email Interval'
#: pkg/store/defaults/templates.go:46
msgid "Selected value:"
msgstr "選択された値:"
#. name of the notification option 'Share Expired'
#: pkg/store/defaults/templates.go:16
msgid "Share Expired"
msgstr " 共有期限切れ"
#. name of the notification option 'Share Received'
#: pkg/store/defaults/templates.go:8
msgid "Share Received"
msgstr "共有受け取った時"
#. name of the notification option 'Share Removed'
#: pkg/store/defaults/templates.go:12
msgid "Share Removed"
msgstr "共有削除"
#. name of the notification option 'Space Deleted'
#: pkg/store/defaults/templates.go:36
msgid "Space deleted"
msgstr "スペース削除"
#. name of the notification option 'Space Disabled'
#: pkg/store/defaults/templates.go:32
msgid "Space disabled"
msgstr "スペース無効化"
#. name of the notification option 'Space Membership Expired'
#: pkg/store/defaults/templates.go:28
msgid "Space membership expired"
msgstr "スペース期限切れ"
#. translation for the 'weekly' email interval option
#: pkg/store/defaults/templates.go:52
msgid "Weekly"
msgstr "毎週"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,115 @@
# 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:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-19 00:05+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: pkg/service/templates.go:39
msgid "Access to Space {space} lost"
msgstr "スペース {space} へのアクセス権が失われました"
#: pkg/service/templates.go:54
msgid "Access to {resource} expired"
msgstr "{resource} へのアクセス期限が切れました"
#: pkg/service/templates.go:59
msgid ""
"Attention! The instance will be shut down and deprovisioned on {date}. "
"Download all your data before that date as no access past that date is "
"possible."
msgstr ""
"【重要】このインスタンスは {date} "
"に停止および削除されます。その日以降はアクセスできなくなるため、期日までにすべてのデータをダウンロードしてください。"
#: pkg/service/templates.go:14
msgid "File {resource} was deleted because it violates the policies"
msgstr "ファイル {resource} はポリシーに違反しているため削除されました"
#: pkg/service/templates.go:58
msgid "Instance will be shut down and deprovisioned"
msgstr "インスタンスは停止および削除されます"
#: pkg/service/templates.go:38
msgid "Membership expired"
msgstr "メンバーシップの期限が切れました"
#: pkg/service/templates.go:13
msgid "Policies enforced"
msgstr " ポリシーが適用されました"
#: pkg/service/templates.go:23
msgid "Removed from Space"
msgstr "スペースから削除されました"
#: pkg/service/templates.go:43
msgid "Resource shared"
msgstr "リソースが共有されました"
#: pkg/service/templates.go:48
msgid "Resource unshared"
msgstr "リソースの共有が解除されました"
#: pkg/service/templates.go:53
msgid "Share expired"
msgstr "共有期限が切れました"
#: pkg/service/templates.go:33
msgid "Space deleted"
msgstr "スペースが削除されました"
#: pkg/service/templates.go:28
msgid "Space disabled"
msgstr "スペースが無効化されました"
#: pkg/service/templates.go:18
msgid "Space shared"
msgstr "スペースが共有されました"
#: pkg/service/templates.go:8
msgid "Virus found"
msgstr " ウイルスが検出されました"
#: pkg/service/templates.go:9
msgid "Virus found in {resource}. Upload not possible. Virus: {virus}"
msgstr "{resource} 内にウイルスが検出されました。アップロードできません。ウイルス名: {virus}"
#: pkg/service/templates.go:19
msgid "{user} added you to Space {space}"
msgstr "{user} があなたをスペース「{space}」に追加しました"
#: pkg/service/templates.go:34
msgid "{user} deleted Space {space}"
msgstr "{user} がスペース「{space}」を削除しました"
#: pkg/service/templates.go:29
msgid "{user} disabled Space {space}"
msgstr "{user} がスペース「{space}」を無効にしました"
#: pkg/service/templates.go:24
msgid "{user} removed you from Space {space}"
msgstr "{user} があなたをスペース「{space}」から削除しました"
#: pkg/service/templates.go:44
msgid "{user} shared {resource} with you"
msgstr "{user} が {resource} をあなたと共有しました"
#: pkg/service/templates.go:49
msgid "{user} unshared {resource} with you"
msgstr "{user} が {resource} の共有を解除しました"

View File

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

View File

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

View File

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

View File

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

View File

@@ -127,13 +127,10 @@ class EmailHelper {
}
/**
* Returns the body of the last received email for the provided receiver according to the provided email address and the serial number
* For email number, 1 means the latest one
* Returns the body of the last received email for the provided receiver
*
* @param string $emailAddress
* @param string|null $xRequestId
* @param int|null $emailNumber For email number, 1 means the latest one
* @param int|null $waitTimeSec Time to wait for the email if the email has been delivered
* @param string $xRequestId
*
* @return string
* @throws GuzzleException
@@ -142,48 +139,40 @@ class EmailHelper {
public static function getBodyOfLastEmail(
string $emailAddress,
string $xRequestId,
?int $emailNumber = 1,
?int $waitTimeSec = EMAIL_WAIT_TIMEOUT_SEC
): string {
$currentTime = \time();
$endTime = $currentTime + $waitTimeSec;
$mailBox = self::getMailBoxFromEmail($emailAddress);
while ($currentTime <= $endTime) {
$mailboxResponse = self::getMailboxInformation($mailBox, $xRequestId);
if (!empty($mailboxResponse) && \sizeof($mailboxResponse) >= $emailNumber) {
$mailboxId = $mailboxResponse[\sizeof($mailboxResponse) - $emailNumber]->id;
$response = self::getBodyOfAnEmailById($mailBox, $mailboxId, $xRequestId);
$body = \str_replace(
"\r\n",
"\n",
\quoted_printable_decode($response->body->text . "\n" . $response->body->html)
);
return $body;
}
\usleep(STANDARD_SLEEP_TIME_MICROSEC * 50);
$currentTime = \time();
$emails = self::getMailboxInformation($mailBox, $xRequestId);
if (!empty($emails)) {
$emailId = \array_pop($emails)->id;
$response = self::getBodyOfAnEmailById($mailBox, $emailId, $xRequestId);
$body = \str_replace(
"\r\n",
"\n",
\quoted_printable_decode($response->body->text . "\n" . $response->body->html)
);
return $body;
}
throw new Exception("Could not find the email to the address: " . $emailAddress);
return "";
}
/**
* Deletes all the emails for the provided mailbox
*
* @param string $localInbucketUrl
* @param string|null $xRequestId
* @param string $url
* @param string $mailBox
* @param string $xRequestId
*
* @return ResponseInterface
* @throws GuzzleException
*/
public static function deleteAllEmailsForAMailbox(
string $localInbucketUrl,
?string $xRequestId,
string $mailBox
public static function deleteAllEmails(
string $url,
string $mailBox,
string $xRequestId,
): ResponseInterface {
return HttpRequestHelper::delete(
$localInbucketUrl . "/api/v1/mailbox/" . $mailBox,
$xRequestId
$url . "/api/v1/mailbox/" . $mailBox,
$xRequestId,
);
}
}

View File

@@ -57,7 +57,7 @@ class HttpRequestHelper {
public static function numRetriesOnHttpTooEarly(): int {
// Currently reva and OpenCloud may return HTTP_TOO_EARLY
// So try up to 10 times before giving up.
return 10;
return STANDARD_RETRY_COUNT;
}
/**
@@ -732,7 +732,7 @@ class HttpRequestHelper {
*/
public static function getRequestTimeout(): int {
$timeout = \getenv("REQUEST_TIMEOUT");
return (int)$timeout ?: 60;
return (int)$timeout ?: HTTP_REQUEST_TIMEOUT;
}
/**

View File

@@ -589,36 +589,68 @@ class NotificationContext implements Context {
): void {
$address = $this->featureContext->getEmailAddressForUser($user);
$this->featureContext->pushEmailRecipientAsMailBox($address);
$actualEmailBodyContent = EmailHelper::getBodyOfLastEmail($address, $this->featureContext->getStepLineRef());
if ($ignoreWhiteSpace) {
$expectedEmailBodyContent = preg_replace('/\s+/', '', $expectedEmailBodyContent);
$actualEmailBodyContent = preg_replace('/\s+/', '', $actualEmailBodyContent);
}
// assert with retries as email delivery might be delayed
$retried = 0;
do {
$actualEmailBodyContent = EmailHelper::getBodyOfLastEmail(
$address,
$this->featureContext->getStepLineRef()
);
if ($ignoreWhiteSpace) {
$expectedEmailBodyContent = preg_replace('/\s+/', '', $expectedEmailBodyContent);
$actualEmailBodyContent = preg_replace('/\s+/', '', $actualEmailBodyContent);
}
$tryAgain = !\str_contains($actualEmailBodyContent, $expectedEmailBodyContent)
&& $retried <= STANDARD_RETRY_COUNT;
$retried++;
if ($tryAgain) {
$mailBox = EmailHelper::getMailBoxFromEmail($address);
echo "[INFO] Checking last email content for '$mailBox'. (Retry $retried)\n";
// wait for 1 second before trying again
sleep(1);
}
} while ($tryAgain);
Assert::assertStringContainsString(
$expectedEmailBodyContent,
$actualEmailBodyContent,
"The email address '$address' should have received an"
. "email with the body containing $expectedEmailBodyContent
but the received email is $actualEmailBodyContent"
. " email with the body containing '$expectedEmailBodyContent'"
. " but the received email is '$actualEmailBodyContent'"
);
}
/**
* Delete all the inbucket emails
* Delete all emails from the mailboxes
*
* @AfterScenario @email
*
* @return void
*/
public function clearInbucketMessages(): void {
public function clearMailboxes(): void {
$users = \array_keys($this->featureContext->getCreatedUsers());
try {
if (!empty($this->featureContext->emailRecipients)) {
foreach ($this->featureContext->emailRecipients as $emailRecipient) {
EmailHelper::deleteAllEmailsForAMailbox(
EmailHelper::getLocalEmailUrl(),
$this->featureContext->getStepLineRef(),
$emailRecipient
);
if (!empty($users)) {
foreach ($users as $emailRecipient) {
$retried = 0;
do {
$res = EmailHelper::deleteAllEmails(
EmailHelper::getLocalEmailUrl(),
$emailRecipient,
$this->featureContext->getStepLineRef(),
);
$deleteStatus = $res->getStatusCode();
$mailBox = EmailHelper::getMailboxInformation($emailRecipient);
$tryAgain = ($deleteStatus !== 200 || !empty($mailBox)) && $retried <= STANDARD_RETRY_COUNT;
$retried++;
if ($tryAgain) {
echo "[INFO] Clearing mailbox '$emailRecipient'."
. " Status: $deleteStatus. Emails: " . \count($mailBox) . "."
. " (Retry $retried)\n";
// wait for 1 second before trying again
sleep(1);
}
} while ($tryAgain);
}
}
} catch (Exception $e) {

View File

@@ -731,6 +731,7 @@ class SharingNgContext implements Context {
/**
* @When /^user "([^"]*)" creates the following resource link share using the Graph API:$/
* @When /^user "([^"]*)" tries to create the following resource link share using the Graph API:$/
*
* @param string $user
* @param TableNode $body
@@ -821,6 +822,7 @@ class SharingNgContext implements Context {
/**
* @When user :user updates the last public link share using the permissions endpoint of the Graph API:
* @When user :user tries to update the last public link share using the permissions endpoint of the Graph API:
*
* @param string $user
* @param TableNode $body
@@ -944,6 +946,7 @@ class SharingNgContext implements Context {
/**
* @When user :user sets the following password for the last link share using the Graph API:
* @When user :user tries to set the following password for the last link share using the Graph API:
*
* @param string $user
* @param TableNode $body

View File

@@ -27,51 +27,20 @@ $classLoader->addPsr4("TestHelpers\\", __DIR__ . "/../TestHelpers", true);
$classLoader->register();
// Sleep for 10 milliseconds
if (!\defined('STANDARD_SLEEP_TIME_MILLISEC')) {
\define('STANDARD_SLEEP_TIME_MILLISEC', 10);
}
if (!\defined('STANDARD_SLEEP_TIME_MICROSEC')) {
\define('STANDARD_SLEEP_TIME_MICROSEC', STANDARD_SLEEP_TIME_MILLISEC * 1000);
}
// Long timeout for use in code that needs to wait for known slow UI
if (!\defined('LONG_UI_WAIT_TIMEOUT_MILLISEC')) {
\define('LONG_UI_WAIT_TIMEOUT_MILLISEC', 60000);
}
// Default timeout for use in code that needs to wait for the UI
if (!\defined('STANDARD_UI_WAIT_TIMEOUT_MILLISEC')) {
\define('STANDARD_UI_WAIT_TIMEOUT_MILLISEC', 10000);
}
// Minimum timeout for use in code that needs to wait for the UI
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC')) {
\define('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC', 500);
}
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC')) {
\define('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC', MINIMUM_UI_WAIT_TIMEOUT_MILLISEC * 1000);
}
// Minimum timeout for emails
if (!\defined('EMAIL_WAIT_TIMEOUT_SEC')) {
\define('EMAIL_WAIT_TIMEOUT_SEC', 10);
}
if (!\defined('EMAIL_WAIT_TIMEOUT_MILLISEC')) {
\define('EMAIL_WAIT_TIMEOUT_MILLISEC', EMAIL_WAIT_TIMEOUT_SEC * 1000);
}
// Default number of times to retry where retries are useful
if (!\defined('STANDARD_RETRY_COUNT')) {
\define('STANDARD_RETRY_COUNT', 5);
\define('STANDARD_RETRY_COUNT', 10);
}
// Minimum number of times to retry where retries are useful
if (!\defined('MINIMUM_RETRY_COUNT')) {
\define('MINIMUM_RETRY_COUNT', 2);
}
// Minimum number of times to retry where retries are useful
if (!\defined('HTTP_REQUEST_TIMEOUT')) {
\define('HTTP_REQUEST_TIMEOUT', 60);
}
// The remote server-under-test might or might not happen to have this directory.
// If it does not exist, then the tests may end up creating it.
if (!\defined('ACCEPTANCE_TEST_DIR_ON_REMOTE_SERVER')) {

View File

@@ -124,20 +124,6 @@
#### [Downloading public files without remote.php returns 401 unauthorized error](https://github.com/owncloud/ocis/issues/9724)
- [apiGraph/enforcePasswordPublicLink.feature:79](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L79)
- [apiGraph/enforcePasswordPublicLink.feature:80](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L80)
- [apiGraph/enforcePasswordPublicLink.feature:107](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L107)
- [apiGraph/enforcePasswordPublicLink.feature:108](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L108)
- [apiGraph/enforcePasswordPublicLink.feature:171](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L171)
- [apiGraph/enforcePasswordPublicLink.feature:172](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L172)
- [apiGraph/enforcePasswordPublicLink.feature:229](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L229)
- [apiGraph/enforcePasswordPublicLink.feature:230](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L230)
- [apiGraph/enforcePasswordPublicLink.feature:231](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L231)
- [apiGraph/enforcePasswordPublicLink.feature:232](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L232)
- [apiGraph/enforcePasswordPublicLink.feature:233](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L233)
- [apiGraph/enforcePasswordPublicLink.feature:234](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L234)
- [apiGraph/enforcePasswordPublicLink.feature:235](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L235)
- [apiGraph/enforcePasswordPublicLink.feature:236](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/enforcePasswordPublicLink.feature#L236)
- [apiSpaces/editPublicLinkOfSpace.feature:48](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpaces/editPublicLinkOfSpace.feature#L48)
- [apiSpaces/editPublicLinkOfSpace.feature:49](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpaces/editPublicLinkOfSpace.feature#L49)
- [apiSpacesShares/publicLinkDownload.feature:16](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/publicLinkDownload.feature#L16)

View File

@@ -12,136 +12,207 @@ Feature: enforce password on public link
| OC_PASSWORD_POLICY_MIN_DIGITS | 1 |
| OC_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS | 1 |
Scenario Outline: create a public link with edit permission without a password when enforce-password is enabled
Given the following configs have been set:
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
Background:
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 3 |
Then the HTTP status code should be "<http-status-code>"
And the OCS status code should be "400"
And the OCS status message should be "missing required password"
Scenario Outline: create a public link without a password when enforce-password for writable share is enabled
Given the following configs have been set:
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
When user "Alice" creates the following resource link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | <permissions-role> |
Then the HTTP status code should be "<status-code>"
Examples:
| ocs-api-version | http-status-code |
| 1 | 200 |
| 2 | 400 |
| permissions-role | status-code |
| view | 200 |
| edit | 400 |
Scenario Outline: create a public link with viewer permission without a password when enforce-password is enabled
Scenario: try to update a public link to edit permission without a password
Given the following configs have been set:
| config | value |
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 1 |
Then the OCS status code should be "<ocs-status-code>"
And the HTTP status code should be "200"
Examples:
| ocs-api-version | ocs-status-code |
| 1 | 100 |
| 2 | 200 |
@issue-9724 @issue-10331
Scenario Outline: updates a public link to edit permission with a password
Given the following configs have been set:
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
And using SharingNG
And user "Alice" has created the following resource link share:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | view |
When user "Alice" updates the last public link share using the sharing API with
| permissions | 3 |
| password | %public% |
When user "Alice" tries to update the last public link share using the permissions endpoint of the Graph API:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | edit |
Then the HTTP status code should be "400"
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"pattern": "invalidRequest"
},
"message": {
"const": "password protection is enforced"
}
}
}
}
}
"""
@issue-2048
Scenario: update a public link to edit permission. Need set pasword first
Given the following configs have been set:
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
And user "Alice" has created the following resource link share:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | view |
When user "Alice" sets the following password for the last link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| password | %public% |
Then the HTTP status code should be "200"
And the OCS status code should be "<ocs-status-code>"
And the OCS status message should be "OK"
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API without a password
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "wrong pass"
But the public should be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "%public%"
Examples:
| ocs-api-version | ocs-status-code |
| 1 | 100 |
| 2 | 200 |
And user "Alice" updates the last public link share using the permissions endpoint of the Graph API:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | edit |
And the HTTP status code should be "200"
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"hasPassword",
"link"
],
"properties": {
"hasPassword": { "const": true },
"link": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": { "const": "edit" }
}
}
}
}
"""
@issue-9724 @issue-10331
Scenario Outline: create a public link with a password in accordance with the password policy
Scenario: create a public link with a password in accordance with the password policy
Given the following configs have been set:
| config | value |
| config | value |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 13 |
| OC_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS | 3 |
| OC_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS | 2 |
| OC_PASSWORD_POLICY_MIN_DIGITS | 2 |
| OC_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS | 2 |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 3 |
| password | 3s:5WW9uE5h=A |
When user "Alice" creates the following resource link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | edit |
| password | 3s:5WW9uE5h=A |
Then the HTTP status code should be "200"
And the OCS status code should be "<ocs-status-code>"
And the OCS status message should be "OK"
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API without a password
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "wrong pass"
But the public should be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "3s:5WW9uE5h=A"
Examples:
| ocs-api-version | ocs-status-code |
| 1 | 100 |
| 2 | 200 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [
"hasPassword",
"id",
"link"
],
"properties": {
"hasPassword": { "const": true },
"id": {
"type": "string",
"pattern": "^[a-zA-Z]{15}$"
},
"link": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": { "const": "edit" }
}
}
}
}
"""
Scenario Outline: try to create a public link with a password that does not comply with the password policy
Scenario: try to create a public link with a password that does not comply with the password policy
Given the following configs have been set:
| config | value |
| config | value |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 13 |
| OC_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS | 3 |
| OC_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS | 2 |
| OC_PASSWORD_POLICY_MIN_DIGITS | 2 |
| OC_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS | 2 |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 3 |
| password | Pas1 |
Then the HTTP status code should be "<http-status-code>"
And the OCS status code should be "400"
And the OCS status message should be:
When user "Alice" tries to create the following resource link share using the Graph API:
| space | Personal |
| resource | testfile.txt |
| permissionsRole | edit |
| password | Pas1 |
Then the HTTP status code should be "400"
And the JSON data of the response should match
"""
At least 13 characters are required
at least 3 lowercase letters are required
at least 2 uppercase letters are required
at least 2 numbers are required
at least 2 special characters are required !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
{
"type": "object",
"required": ["error"],
"properties": {
"error": {
"type": "object",
"required": [
"code",
"innererror",
"message"
],
"properties": {
"code": { "const": "invalidRequest" },
"innererror": {
"type": "object",
"required": [
"date",
"request-id"
]
},
"message": {
"type": "string",
"pattern": "at least 13 characters are required\\s+at least 3 lowercase letters are required\\s+at least 2 uppercase letters are required\\s+at least 2 numbers are required\\s+at least 2 special characters are required\\s+[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~]+"
}
}
}
}
}
"""
Examples:
| ocs-api-version | http-status-code |
| 1 | 200 |
| 2 | 400 |
@issue-9724 @issue-10331
Scenario Outline: update a public link with a password in accordance with the password policy
Scenario: update a public link with a password in accordance with the password policy
Given the following configs have been set:
| config | value |
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 13 |
@@ -149,32 +220,30 @@ Feature: enforce password on public link
| OC_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS | 2 |
| OC_PASSWORD_POLICY_MIN_DIGITS | 1 |
| OC_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS | 2 |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
And using SharingNG
And user "Alice" has created the following resource link share:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | view |
When user "Alice" updates the last public link share using the sharing API with
| permissions | 3 |
| password | 6a0Q;A3 +i^m[ |
When user "Alice" sets the following password for the last link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| password | 6a0Q;A3 +i^m[ |
Then the HTTP status code should be "200"
And the OCS status code should be "<ocs-status-code>"
And the OCS status message should be "OK"
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API without a password
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "wrong pass"
But the public should be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "6a0Q;A3 +i^m["
Examples:
| ocs-api-version | ocs-status-code |
| 1 | 100 |
| 2 | 200 |
And the JSON data of the response should match
"""
{
"type": "object",
"required": [ "hasPassword" ],
"properties": {
"hasPassword": { "const": true }
}
}
"""
Scenario Outline: try to update a public link with a password that does not comply with the password policy
Given the following configs have been set:
| config | value |
| config | value |
| OC_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD | false |
| OC_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD | true |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 13 |
@@ -182,8 +251,6 @@ Feature: enforce password on public link
| OC_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS | 2 |
| OC_PASSWORD_POLICY_MIN_DIGITS | 1 |
| OC_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS | 2 |
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using OCS API version "<ocs-api-version>"
And using SharingNG
And user "Alice" has created the following resource link share:
@@ -193,39 +260,42 @@ Feature: enforce password on public link
When user "Alice" updates the last public link share using the sharing API with
| permissions | 3 |
| password | Pws^ |
Then the HTTP status code should be "<http-status-code>"
And the OCS status code should be "400"
And the OCS status message should be:
And user "Alice" tries to set the following password for the last link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| password | Pws^ |
Then the HTTP status code should be "400"
And the JSON data of the response should match
"""
At least 13 characters are required
at least 3 lowercase letters are required
at least 2 uppercase letters are required
at least 1 numbers are required
at least 2 special characters are required !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
{
"type": "object",
"required": [ "error" ],
"properties": {
"error": {
"type": "object",
"required": [ "message" ],
"properties": {
"message": {
"type": "string",
"pattern": "at least 13 characters are required\\s+at least 3 lowercase letters are required\\s+at least 2 uppercase letters are required\\s+at least 1 numbers are required\\s+at least 2 special characters are required\\s+[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~]+"
}
}
}
}
}
"""
Examples:
| ocs-api-version | http-status-code |
| 1 | 200 |
| 2 | 400 |
@issue-9724 @issue-10331
Scenario Outline: create a public link with a password in accordance with the password policy (valid cases)
Given the config "<config>" has been set to "<config-value>"
And using OCS API version "2"
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 1 |
| password | <password> |
When user "Alice" creates the following resource link share using the Graph API:
| space | Personal |
| resource | testfile.txt |
| permissionsRole | view |
| password | <password> |
Then the HTTP status code should be "200"
And the OCS status code should be "200"
And the OCS status message should be "OK"
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API without a password
And the public should not be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "wrong pass"
But the public should be able to download file "/testfile.txt" from inside the last public link shared folder using the public WebDAV API with password "<password>"
Examples:
| config | config-value | password |
| config | config-value | password |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 4 | Ps-1 |
| OC_PASSWORD_POLICY_MIN_CHARACTERS | 14 | Ps1:with space |
| OC_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS | 4 | PS1:test |
@@ -237,61 +307,99 @@ Feature: enforce password on public link
Scenario Outline: try to create a public link with a password that does not comply with the password policy (invalid cases)
Given using OCS API version "2"
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 3 |
| password | <password> |
When user "Alice" tries to create the following resource link share using the Graph API:
| space | Personal |
| resource | testfile.txt |
| permissionsRole | view |
| password | <password> |
Then the HTTP status code should be "400"
And the OCS status code should be "400"
And the OCS status message should be "<message>"
And the JSON data of the response should match
"""
{
"type": "object",
"required": [ "error" ],
"properties": {
"error": {
"type": "object",
"required": [ "message" ],
"properties": {
"message": {
"const": "<message>"
}
}
}
}
}
"""
Examples:
| password | message |
| 1Pw: | At least 8 characters are required |
| 1P:12345 | At least 1 lowercase letters are required |
| test-123 | At least 1 uppercase letters are required |
| Test-psw | At least 1 numbers are required |
| 1Pw: | at least 8 characters are required |
| 1P:12345 | at least 1 lowercase letters are required |
| test-123 | at least 1 uppercase letters are required |
| Test-psw | at least 1 numbers are required |
Scenario Outline: update a public link with a password that is listed in the Banned-Password-List
Given the config "OC_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" has been set to path "config/woodpecker/banned-password-list.txt"
And using OCS API version "2"
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
And using SharingNG
And user "Alice" has created the following resource link share:
| resource | testfile.txt |
| space | Personal |
| permissionsRole | internal |
When user "Alice" updates the last public link share using the sharing API with
| permissions | 3 |
| password | <password> |
Then the HTTP status code should be "<http-status-code>"
And the OCS status code should be "<ocs-status-code>"
And the OCS status message should be "<message>"
| permissionsRole | view |
| password | %public% |
And user "Alice" tries to set the following password for the last link share using the Graph API:
| resource | testfile.txt |
| space | Personal |
| password | <password> |
Then the HTTP status code should be "400"
And the JSON data of the response should match
"""
{
"type": "object",
"required": [ "error" ],
"properties": {
"error": {
"type": "object",
"required": [ "message" ],
"properties": {
"message": { "const": "<message>" }
}
}
}
}
"""
Examples:
| password | http-status-code | ocs-status-code | message |
| 123 | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| OpenCloud | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | message |
| 123 | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| OpenCloud | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
Scenario Outline: create a public link with a password that is listed in the Banned-Password-List
Given the config "OC_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" has been set to path "config/woodpecker/banned-password-list.txt"
And using OCS API version "2"
And user "Alice" has been created with default attributes
And user "Alice" has uploaded file with content "test file" to "/testfile.txt"
When user "Alice" creates a public link share using the sharing API with settings
| path | /testfile.txt |
| permissions | 3 |
| password | <password> |
Then the HTTP status code should be "<http-status-code>"
And the OCS status code should be "<ocs-status-code>"
And the OCS status message should be "<message>"
When user "Alice" tries to create the following resource link share using the Graph API:
| space | Personal |
| resource | testfile.txt |
| permissionsRole | view |
| password | <password> |
Then the HTTP status code should be "400"
And the JSON data of the response should match
"""
{
"type": "object",
"required": [ "error" ],
"properties": {
"error": {
"type": "object",
"required": [ "message" ],
"properties": {
"message": { "const": "<message>" }
}
}
}
}
"""
Examples:
| password | http-status-code | ocs-status-code | message |
| 123 | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| OpenCloud | 400 | 400 | Unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | message |
| 123 | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| password | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |
| OpenCloud | unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety |

View File

@@ -1,33 +0,0 @@
Feature: create a public link share when share_folder is set to Shares
As a user
I want to create public links
So that I can share resources to people who aren't OpenCloud users
Background:
Given user "Alice" has been created with default attributes
Scenario Outline: creating a new public link share of a file gives the correct response
Given using OCS API version "<ocs-api-version>"
And user "Alice" has uploaded file with content "Random data" to "/randomfile.txt"
When user "Alice" creates a public link share using the sharing API with settings
| path | randomfile.txt |
| password | %public% |
Then the OCS status code should be "<ocs-status-code>"
And the HTTP status code should be "200"
And the fields of the last response to user "Alice" should include
| item_type | file |
| mimetype | text/plain |
| file_target | /randomfile.txt |
| path | /randomfile.txt |
| permissions | read |
| share_type | public_link |
| displayname_file_owner | %displayname% |
| displayname_owner | %displayname% |
| uid_file_owner | %username% |
| uid_owner | %username% |
| name | |
Examples:
| ocs-api-version | ocs-status-code |
| 1 | 100 |
| 2 | 200 |

View File

@@ -1,3 +1,3 @@
{
"defaultFont": "/woodpecker/src/github.com/opencloud-eu/opencloud/tests/config/woodpecker/NotoSans.ttf"
"defaultFont": "NotoSans.ttf"
}

View File

@@ -1,5 +1,5 @@
#!/bin/sh
while true; do
echo -e "HTTP/1.1 200 OK\n\n$(cat /woodpecker/src/github.com/opencloud-eu/opencloud/tests/config/woodpecker/hosting-discovery.xml)" | nc -l -k -p 8080
echo -e "HTTP/1.1 200 OK\n\n$(cat tests/config/woodpecker/hosting-discovery.xml)" | nc -l -k -p 8080
done

View File

@@ -38,5 +38,5 @@ func DefaultSpec() specs.Platform {
// Default returns the current platform's default platform specification.
func Default() MatchComparer {
return Only(DefaultSpec())
return &windowsMatchComparer{Matcher: NewMatcher(DefaultSpec())}
}

View File

@@ -42,18 +42,30 @@ const (
// rs5 (version 1809, codename "Redstone 5") corresponds to Windows Server
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
rs5 = 17763
// ltsc2019 (Windows Server 2019) is an alias for [RS5].
ltsc2019 = rs5
// v21H2Server corresponds to Windows Server 2022 (ltsc2022).
v21H2Server = 20348
// ltsc2022 (Windows Server 2022) is an alias for [v21H2Server]
ltsc2022 = v21H2Server
// v22H2Win11 corresponds to Windows 11 (2022 Update).
v22H2Win11 = 22621
// v23H2 is the 23H2 release in the Windows Server annual channel.
v23H2 = 25398
// Windows Server 2025 build 26100
v25H1Server = 26100
ltsc2025 = v25H1Server
)
// List of stable ABI compliant ltsc releases
// Note: List must be sorted in ascending order
var compatLTSCReleases = []uint16{
v21H2Server,
ltsc2022,
ltsc2025,
}
// CheckHostAndContainerCompat checks if given host and container
@@ -70,18 +82,27 @@ func checkWindowsHostAndContainerCompat(host, ctr windowsOSVersion) bool {
}
// If host is < WS 2022, exact version match is required
if host.Build < v21H2Server {
if host.Build < ltsc2022 {
return host.Build == ctr.Build
}
var supportedLtscRelease uint16
// Find the latest LTSC version that is earlier than the host version.
// This is the earliest version of container that the host can run.
//
// If the host version is an LTSC, then it supports compatibility with
// everything from the previous LTSC up to itself, so we want supportedLTSCRelease
// to be the previous entry.
//
// If no match is found, then we know that the host is LTSC2022 exactly,
// since we already checked that it's not less than LTSC2022.
var supportedLTSCRelease uint16 = ltsc2022
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
if host.Build >= compatLTSCReleases[i] {
supportedLtscRelease = compatLTSCReleases[i]
if host.Build > compatLTSCReleases[i] {
supportedLTSCRelease = compatLTSCReleases[i]
break
}
}
return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
return supportedLTSCRelease <= ctr.Build && ctr.Build <= host.Build
}
func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion {
@@ -114,18 +135,6 @@ func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion {
}
}
func winRevision(v string) int {
parts := strings.Split(v, ".")
if len(parts) < 4 {
return 0
}
r, err := strconv.Atoi(parts[3])
if err != nil {
return 0
}
return r
}
type windowsVersionMatcher struct {
windowsOSVersion
}
@@ -149,8 +158,7 @@ type windowsMatchComparer struct {
func (c *windowsMatchComparer) Less(p1, p2 specs.Platform) bool {
m1, m2 := c.Match(p1), c.Match(p2)
if m1 && m2 {
r1, r2 := winRevision(p1.OSVersion), winRevision(p2.OSVersion)
return r1 > r2
return p1.OSVersion > p2.OSVersion
}
return m1 && !m2
}

View File

@@ -106,6 +106,9 @@ linters:
- revive
path: jwt/internal/types/
text: "var-naming: avoid meaningless package names"
- linters:
- godoclint
path: (^|/)internal/
paths:
- third_party$
- builtin$

View File

@@ -4,6 +4,49 @@ Changes
v3 has many incompatibilities with v2. To see the full list of differences between
v2 and v3, please read the Changes-v3.md file (https://github.com/lestrrat-go/jwx/blob/develop/v3/Changes-v3.md)
v3.0.12 20 Oct 2025
* [jwe] As part of the next change, now per-recipient headers that are empty
are no longer serialized in flattened JSON serialization.
* [jwe] Introduce `jwe.WithLegacyHeaderMerging(bool)` option to control header
merging behavior in during JWE encryption. This only applies to flattened
JSON serialization.
Previously, when using flattened JSON serialization (i.e. you specified
JSON serialization via `jwe.WithJSON()` and only supplied one key), per-recipient
headers were merged into the protected headers during encryption, and then
were left to be included in the final serialization as-is. This caused duplicate
headers to be present in both the protected headers and the per-recipient headers.
Since there maybe users who rely on this behavior already, instead of changing the
default behavior to fix this duplication, a new option to `jwe.Encrypt()` was added
to allow clearing the per-recipient headers after merging to leave the `"headers"`
field empty. This in effect makes the flattened JSON serialization more similar to
the compact serialization, where there are no per-recipient headers present, and
leaves the headers disjoint.
Note that in compact mode, there are no per-recipient headers and thus the
headers need to be merged regardless. In full JSON serialization, we never
merge the headers, so it is left up to the user to keep the headers disjoint.
* [jws] Calling the deprecated `jws.NewSigner()` function for the time will cause
legacy signers to be loaded automatically. Previously, you had to explicitly
call `jws.Settings(jws.WithLegacySigners(true))` to enable legacy signers.
We incorrectly assumed that users would not be using `jws.NewSigner()`, and thus
disabled legacy signers by default. However, it turned out that some users
were using `jws.NewSigner()` in their code, which lead to breakages in
existing code. In hindsight we should have known that any API made public before will
be used by _somebody_.
As a side effect, jws.Settings(jws.WithLegacySigners(...)) is now a no-op.
However, please do note that jws.Signer (and similar) objects were always intended to be
used for _registering_ new signing/verifying algorithms, and not for end users to actually
use them directly. If you are using them for other purposes, please consider changing
your code, as it is more than likely that we will somehow deprecate/remove/discouraged
their use in the future.
v3.0.11 14 Sep 2025
* [jwk] Add `(jwk.Cache).Shutdown()` method that delegates to the httprc controller
object, to shutdown the cache.

View File

@@ -9,9 +9,9 @@ bazel_dep(name = "rules_go", version = "0.55.1")
bazel_dep(name = "gazelle", version = "0.44.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.11.0")
# Go SDK setup - using Go 1.24.4 to match the toolchain in go.mod
# Go SDK setup from go.mod
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.24.4")
go_sdk.from_file(go_mod = "//:go.mod")
# Go dependencies from go.mod
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")

View File

@@ -22,8 +22,9 @@ const _FormatKind_name = "InvalidFormatUnknownFormatJWEJWSJWKJWKSJWT"
var _FormatKind_index = [...]uint8{0, 13, 26, 29, 32, 35, 39, 42}
func (i FormatKind) String() string {
if i < 0 || i >= FormatKind(len(_FormatKind_index)-1) {
idx := int(i) - 0
if i < 0 || idx >= len(_FormatKind_index)-1 {
return "FormatKind(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _FormatKind_name[_FormatKind_index[i]:_FormatKind_index[i+1]]
return _FormatKind_name[_FormatKind_index[idx]:_FormatKind_index[idx+1]]
}

View File

@@ -99,15 +99,20 @@ func (b *recipientBuilder) Build(r Recipient, cek []byte, calg jwa.ContentEncryp
rawKey = raw
}
// Extract ECDH-ES specific parameters if needed
// Extract ECDH-ES specific parameters if needed.
var apu, apv []byte
if b.headers != nil {
if val, ok := b.headers.AgreementPartyUInfo(); ok {
apu = val
}
if val, ok := b.headers.AgreementPartyVInfo(); ok {
apv = val
}
hdr := b.headers
if hdr == nil {
hdr = NewHeaders()
}
if val, ok := hdr.AgreementPartyUInfo(); ok {
apu = val
}
if val, ok := hdr.AgreementPartyVInfo(); ok {
apv = val
}
// Create the encrypter using the new jwebb pattern
@@ -116,20 +121,20 @@ func (b *recipientBuilder) Build(r Recipient, cek []byte, calg jwa.ContentEncryp
return nil, fmt.Errorf(`jwe.Encrypt: recipientBuilder: failed to create encrypter: %w`, err)
}
if hdrs := b.headers; hdrs != nil {
_ = r.SetHeaders(hdrs)
}
_ = r.SetHeaders(hdr)
if err := r.Headers().Set(AlgorithmKey, b.alg); err != nil {
// Populate headers with stuff that we automatically set
if err := hdr.Set(AlgorithmKey, b.alg); err != nil {
return nil, fmt.Errorf(`failed to set header: %w`, err)
}
if keyID != "" {
if err := r.Headers().Set(KeyIDKey, keyID); err != nil {
if err := hdr.Set(KeyIDKey, keyID); err != nil {
return nil, fmt.Errorf(`failed to set header: %w`, err)
}
}
// Handle the encrypted key
var rawCEK []byte
enckey, err := enc.EncryptKey(cek)
if err != nil {
@@ -143,8 +148,9 @@ func (b *recipientBuilder) Build(r Recipient, cek []byte, calg jwa.ContentEncryp
}
}
// finally, anything specific should go here
if hp, ok := enckey.(populater); ok {
if err := hp.Populate(r.Headers()); err != nil {
if err := hp.Populate(hdr); err != nil {
return nil, fmt.Errorf(`failed to populate: %w`, err)
}
}
@@ -154,7 +160,9 @@ func (b *recipientBuilder) Build(r Recipient, cek []byte, calg jwa.ContentEncryp
// Encrypt generates a JWE message for the given payload and returns
// it in serialized form, which can be in either compact or
// JSON format. Default is compact.
// JSON format. Default is compact. When JSON format is specified and
// there is only one recipient, the resulting serialization is
// automatically converted to flattened JSON serialization format.
//
// You must pass at least one key to `jwe.Encrypt()` by using `jwe.WithKey()`
// option.
@@ -172,6 +180,10 @@ func (b *recipientBuilder) Build(r Recipient, cek []byte, calg jwa.ContentEncryp
//
// Look for options that return `jwe.EncryptOption` or `jws.EncryptDecryptOption`
// for a complete list of options that can be passed to this function.
//
// As of v3.0.12, users can specify `jwe.WithLegacyHeaderMerging()` to
// disable header merging behavior that was the default prior to v3.0.12.
// Read the documentation for `jwe.WithLegacyHeaderMerging()` for more information.
func Encrypt(payload []byte, options ...EncryptOption) ([]byte, error) {
ec := encryptContextPool.Get()
defer encryptContextPool.Put(ec)
@@ -410,10 +422,26 @@ func (dc *decryptContext) decryptContent(msg *Message, alg jwa.KeyEncryptionAlgo
Tag(msg.tag).
CEK(dc.cek)
if v, ok := recipient.Headers().Algorithm(); !ok || v != alg {
// algorithms don't match
// The "alg" header can be in either protected/unprotected headers.
// prefer per-recipient headers (as it might be the case that the algorithm differs
// by each recipient), then look at protected headers.
var algMatched bool
for _, hdr := range []Headers{recipient.Headers(), protectedHeaders} {
v, ok := hdr.Algorithm()
if !ok {
continue
}
if v == alg {
algMatched = true
break
}
// if we found something but didn't match, it's a failure
return nil, fmt.Errorf(`jwe.Decrypt: key (%q) and recipient (%q) algorithms do not match`, alg, v)
}
if !algMatched {
return nil, fmt.Errorf(`jwe.Decrypt: failed to find "alg" header in either protected or per-recipient headers`)
}
h2, err := protectedHeaders.Clone()
if err != nil {
@@ -534,11 +562,12 @@ func (dc *decryptContext) decryptContent(msg *Message, alg jwa.KeyEncryptionAlgo
// encryptContext holds the state during JWE encryption, similar to JWS signContext
type encryptContext struct {
calg jwa.ContentEncryptionAlgorithm
compression jwa.CompressionAlgorithm
format int
builders []*recipientBuilder
protected Headers
calg jwa.ContentEncryptionAlgorithm
compression jwa.CompressionAlgorithm
format int
builders []*recipientBuilder
protected Headers
legacyHeaderMerging bool
}
var encryptContextPool = pool.New(allocEncryptContext, freeEncryptContext)
@@ -561,6 +590,7 @@ func freeEncryptContext(ec *encryptContext) *encryptContext {
}
func (ec *encryptContext) ProcessOptions(options []EncryptOption) error {
ec.legacyHeaderMerging = true
var mergeProtected bool
var useRawCEK bool
for _, option := range options {
@@ -577,7 +607,11 @@ func (ec *encryptContext) ProcessOptions(options []EncryptOption) error {
if v == jwa.DIRECT() || v == jwa.ECDH_ES() {
useRawCEK = true
}
ec.builders = append(ec.builders, &recipientBuilder{alg: v, key: wk.key, headers: wk.headers})
ec.builders = append(ec.builders, &recipientBuilder{
alg: v,
key: wk.key,
headers: wk.headers,
})
case identContentEncryptionAlgorithm{}:
var c jwa.ContentEncryptionAlgorithm
if err := option.Value(&c); err != nil {
@@ -616,6 +650,12 @@ func (ec *encryptContext) ProcessOptions(options []EncryptOption) error {
return err
}
ec.format = fmtOpt
case identLegacyHeaderMerging{}:
var v bool
if err := option.Value(&v); err != nil {
return err
}
ec.legacyHeaderMerging = v
}
}
@@ -732,7 +772,8 @@ func (ec *encryptContext) EncryptMessage(payload []byte, cek []byte) ([]byte, er
}
}
recipients := recipientSlicePool.GetCapacity(len(ec.builders))
lbuilders := len(ec.builders)
recipients := recipientSlicePool.GetCapacity(lbuilders)
defer recipientSlicePool.Put(recipients)
for i, builder := range ec.builders {
@@ -767,14 +808,55 @@ func (ec *encryptContext) EncryptMessage(payload []byte, cek []byte) ([]byte, er
}
}
// If there's only one recipient, you want to include that in the
// protected header
if len(recipients) == 1 {
// fmtCompact does not have per-recipient headers, nor a "header" field.
// In this mode, we're going to have to merge everything to the protected
// header.
if ec.format == fmtCompact {
// We have already established that the number of builders is 1 in
// ec.ProcessOptions(). But we're going to be pedantic
if lbuilders != 1 {
return nil, fmt.Errorf(`internal error: expected exactly one recipient builder (got %d)`, lbuilders)
}
// when we're using compact format, we can safely merge per-recipient
// headers into the protected header, if any
h, err := protected.Merge(recipients[0].Headers())
if err != nil {
return nil, fmt.Errorf(`failed to merge protected headers: %w`, err)
return nil, fmt.Errorf(`failed to merge protected headers for compact serialization: %w`, err)
}
protected = h
// per-recipient headers, if any, will be ignored in compact format
} else {
// If it got here, it's JSON (could be pretty mode, too).
if lbuilders == 1 {
// If it got here, then we're doing flattened JSON serialization.
// In this mode, we should merge per-recipient headers into the protected header,
// but we also need to make sure that the "header" field is reset so that
// it does not contain the same fields as the protected header.
//
// However, old behavior was to merge per-recipient headers into the
// protected header when there was only one recipient, AND leave the
// original "header" field as is, so we need to support that for backwards compatibility.
//
// The legacy merging only takes effect when there is exactly one recipient.
//
// This behavior can be disabled by passing jwe.WithLegacyHeaderMerging(false)
// If the user has explicitly asked for merging, do it
h, err := protected.Merge(recipients[0].Headers())
if err != nil {
return nil, fmt.Errorf(`failed to merge protected headers for flattenend JSON format: %w`, err)
}
protected = h
if !ec.legacyHeaderMerging {
// Clear per-recipient headers, since they have been merged.
// But we only do it when legacy merging is disabled.
// Note: we should probably introduce a Reset() method in v4
if err := recipients[0].SetHeaders(NewHeaders()); err != nil {
return nil, fmt.Errorf(`failed to clear per-recipient headers after merging: %w`, err)
}
}
}
}
aad, err := protected.Encode()

View File

@@ -265,14 +265,23 @@ func (m *Message) MarshalJSON() ([]byte, error) {
if recipients := m.Recipients(); len(recipients) > 0 {
if len(recipients) == 1 { // Use flattened format
if hdrs := recipients[0].Headers(); hdrs != nil {
buf.Reset()
if err := enc.Encode(hdrs); err != nil {
return nil, fmt.Errorf(`failed to encode %s field: %w`, HeadersKey, err)
var skipHeaders bool
if zeroer, ok := hdrs.(isZeroer); ok {
if zeroer.isZero() {
skipHeaders = true
}
}
if !skipHeaders {
buf.Reset()
if err := enc.Encode(hdrs); err != nil {
return nil, fmt.Errorf(`failed to encode %s field: %w`, HeadersKey, err)
}
fields = append(fields, jsonKV{
Key: HeadersKey,
Value: strings.TrimSpace(buf.String()),
})
}
fields = append(fields, jsonKV{
Key: HeadersKey,
Value: strings.TrimSpace(buf.String()),
})
}
if ek := recipients[0].EncryptedKey(); len(ek) > 0 {
@@ -369,13 +378,18 @@ func (m *Message) UnmarshalJSON(buf []byte) error {
// field. TODO: do both of these conditions need to meet, or just one?
if proxy.Headers != nil || len(proxy.EncryptedKey) > 0 {
recipient := NewRecipient()
hdrs := NewHeaders()
if err := json.Unmarshal(proxy.Headers, hdrs); err != nil {
return fmt.Errorf(`failed to decode headers field: %w`, err)
}
if err := recipient.SetHeaders(hdrs); err != nil {
return fmt.Errorf(`failed to set new headers: %w`, err)
// `"heders"` could be empty. If that's the case, just skip the
// following unmarshaling step
if proxy.Headers != nil {
hdrs := NewHeaders()
if err := json.Unmarshal(proxy.Headers, hdrs); err != nil {
return fmt.Errorf(`failed to decode headers field: %w`, err)
}
if err := recipient.SetHeaders(hdrs); err != nil {
return fmt.Errorf(`failed to set new headers: %w`, err)
}
}
if v := proxy.EncryptedKey; len(v) > 0 {

View File

@@ -6,8 +6,9 @@ import (
"github.com/lestrrat-go/option/v2"
)
// Specify contents of the protected header. Some fields such as
// "enc" and "zip" will be overwritten when encryption is performed.
// WithProtectedHeaders is used to specify contents of the protected header.
// Some fields such as "enc" and "zip" will be overwritten when encryption is
// performed.
//
// There is no equivalent for unprotected headers in this implementation
func WithProtectedHeaders(h Headers) EncryptOption {

View File

@@ -169,4 +169,42 @@ options:
If set to an invalid value, the default value is used.
In v2, this option was called MaxBufferSize.
This option has a global effect.
This option has a global effect.
- ident: LegacyHeaderMerging
interface: EncryptOption
argument_type: bool
option_name: WithLegacyHeaderMerging
comment: |
WithLegacyHeaderMerging specifies whether to perform legacy header merging
when encrypting a JWE message in JSON serialization, when there is a single recipient.
This behavior is enabled by default for backwards compatibility.
When a JWE message is encrypted in JSON serialization, and there is only
one recipient, this library automatically serializes the message in
flattened JSON serialization format. In older versions of this library,
the protected headers and the per-recipient headers were merged together
before computing the AAD (Additional Authenticated Data), but the per-recipient
headers were kept as-is in the `header` field of the recipient object.
This behavior is not compliant with the JWE specification, which states that
the headers must be disjoint.
Passing this option with a value of `false` disables this legacy behavior,
and while the per-recipient headers and protected headers are still merged
for the purpose of computing AAD, the per-recipient headers are cleared
after merging, so that the resulting JWE message is compliant with the
specification.
This option has no effect when there are multiple recipients, or when
the serialization format is compact serialization. For multiple recipients
(i.e. full JSON serialization), the protected headers and per-recipient
headers are never merged, and it is the caller's responsibility to ensure
that the headers are disjoint. In compact serialization, there are no per-recipient
headers; in fact, the protected headers are the only headers that exist,
and therefore there is no possibility of header collision after merging
(note: while per-recipient headers do not make sense in compact serialization,
this library does not prevent you from setting them -- they are all just
merged into the protected headers).
In future versions, the new behavior will be the default. New users are
encouraged to set this option to `false` now to avoid future issues.

View File

@@ -147,6 +147,7 @@ type identFS struct{}
type identKey struct{}
type identKeyProvider struct{}
type identKeyUsed struct{}
type identLegacyHeaderMerging struct{}
type identMaxDecompressBufferSize struct{}
type identMaxPBES2Count struct{}
type identMergeProtectedHeaders struct{}
@@ -193,6 +194,10 @@ func (identKeyUsed) String() string {
return "WithKeyUsed"
}
func (identLegacyHeaderMerging) String() string {
return "WithLegacyHeaderMerging"
}
func (identMaxDecompressBufferSize) String() string {
return "WithMaxDecompressBufferSize"
}
@@ -292,6 +297,43 @@ func WithKeyUsed(v any) DecryptOption {
return &decryptOption{option.New(identKeyUsed{}, v)}
}
// WithLegacyHeaderMerging specifies whether to perform legacy header merging
// when encrypting a JWE message in JSON serialization, when there is a single recipient.
// This behavior is enabled by default for backwards compatibility.
//
// When a JWE message is encrypted in JSON serialization, and there is only
// one recipient, this library automatically serializes the message in
// flattened JSON serialization format. In older versions of this library,
// the protected headers and the per-recipient headers were merged together
// before computing the AAD (Additional Authenticated Data), but the per-recipient
// headers were kept as-is in the `header` field of the recipient object.
//
// This behavior is not compliant with the JWE specification, which states that
// the headers must be disjoint.
//
// Passing this option with a value of `false` disables this legacy behavior,
// and while the per-recipient headers and protected headers are still merged
// for the purpose of computing AAD, the per-recipient headers are cleared
// after merging, so that the resulting JWE message is compliant with the
// specification.
//
// This option has no effect when there are multiple recipients, or when
// the serialization format is compact serialization. For multiple recipients
// (i.e. full JSON serialization), the protected headers and per-recipient
// headers are never merged, and it is the caller's responsibility to ensure
// that the headers are disjoint. In compact serialization, there are no per-recipient
// headers; in fact, the protected headers are the only headers that exist,
// and therefore there is no possibility of header collision after merging
// (note: while per-recipient headers do not make sense in compact serialization,
// this library does not prevent you from setting them -- they are all just
// merged into the protected headers).
//
// In future versions, the new behavior will be the default. New users are
// encouraged to set this option to `false` now to avoid future issues.
func WithLegacyHeaderMerging(v bool) EncryptOption {
return &encryptOption{option.New(identLegacyHeaderMerging{}, v)}
}
// WithMaxDecompressBufferSize specifies the maximum buffer size for used when
// decompressing the payload of a JWE message. If a compressed JWE payload
// exceeds this amount when decompressed, jwe.Decrypt will return an error.

View File

@@ -270,7 +270,7 @@ func (cs *cachedSet) cached() (Set, error) {
return cs.r.Resource(), nil
}
// Add is a no-op for `jwk.CachedSet`, as the `jwk.Set` should be treated read-only
// AddKey is a no-op for `jwk.CachedSet`, as the `jwk.Set` should be treated read-only
func (*cachedSet) AddKey(_ Key) error {
return fmt.Errorf(`(jwk.Cachedset).AddKey: jwk.CachedSet is immutable`)
}

View File

@@ -40,7 +40,7 @@ type CachedFetcher struct {
cache *Cache
}
// Creates a new `jwk.CachedFetcher` object.
// NewCachedFetcher creates a new `jwk.CachedFetcher` object.
func NewCachedFetcher(cache *Cache) *CachedFetcher {
return &CachedFetcher{cache}
}

View File

@@ -118,7 +118,7 @@ func NewPEMDecoder() PEMDecoder {
type pemDecoder struct{}
// DecodePEM decodes a key in PEM encoded ASN.1 DER format.
// Decode decodes a key in PEM encoded ASN.1 DER format.
// and returns a raw key.
func (pemDecoder) Decode(src []byte) (any, []byte, error) {
block, rest := pem.Decode(src)

View File

@@ -586,11 +586,14 @@ func AlgorithmsForKey(key any) ([]jwa.SignatureAlgorithm, error) {
return algs, nil
}
// Settings allows you to set global settings for this JWS operations.
//
// Currently, the only setting available is `jws.WithLegacySigners()`,
// which for various reason is now a no-op.
func Settings(options ...GlobalOption) {
for _, option := range options {
switch option.Ident() {
case identLegacySigners{}:
enableLegacySigners()
}
}
}

View File

@@ -26,7 +26,7 @@ func (e headerNotFoundError) Is(target error) bool {
}
}
// ErrHeaderdNotFound returns an error that can be passed to `errors.Is` to check if the error is
// ErrHeaderNotFound returns an error that can be passed to `errors.Is` to check if the error is
// the result of the field not being found
func ErrHeaderNotFound() error {
return headerNotFoundError{}

View File

@@ -2,11 +2,14 @@ package jws
import (
"fmt"
"sync"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jws/legacy"
)
var enableLegacySignersOnce = &sync.Once{}
func enableLegacySigners() {
for _, alg := range []jwa.SignatureAlgorithm{jwa.HS256(), jwa.HS384(), jwa.HS512()} {
if err := RegisterSigner(alg, func(alg jwa.SignatureAlgorithm) SignerFactory {
@@ -74,7 +77,7 @@ func legacySignerFor(alg jwa.SignatureAlgorithm) (Signer, error) {
muSigner.Lock()
s, ok := signers[alg]
if !ok {
v, err := NewSigner(alg)
v, err := newLegacySigner(alg)
if err != nil {
muSigner.Unlock()
return nil, fmt.Errorf(`failed to create payload signer: %w`, err)

View File

@@ -23,7 +23,7 @@ type Signer interface {
Algorithm() jwa.SignatureAlgorithm
}
// This is for legacy support only.
// Verifier is for legacy support only.
type Verifier interface {
// Verify checks whether the payload and signature are valid for
// the given key.

View File

@@ -38,7 +38,7 @@ type withKey struct {
public Headers
}
// This exists as an escape hatch to modify the header values after the fact
// Protected exists as an escape hatch to modify the header values after the fact
func (w *withKey) Protected(v Headers) Headers {
if w.protected == nil && v != nil {
w.protected = v
@@ -221,7 +221,7 @@ type withInsecureNoSignature struct {
protected Headers
}
// This exists as an escape hatch to modify the header values after the fact
// Protected exists as an escape hatch to modify the header values after the fact
func (w *withInsecureNoSignature) Protected(v Headers) Headers {
if w.protected == nil && v != nil {
w.protected = v

View File

@@ -227,8 +227,4 @@ options:
interface: GlobalOption
constant_value: true
comment: |
WithLegacySigners specifies whether the JWS package should use legacy
signers for signing JWS messages.
Usually there's no need to use this option, as the new signers and
verifiers are loaded by default.
WithLegacySigners is a no-op option that exists only for backwards compatibility.

View File

@@ -356,11 +356,7 @@ func WithKeyUsed(v any) VerifyOption {
return &verifyOption{option.New(identKeyUsed{}, v)}
}
// WithLegacySigners specifies whether the JWS package should use legacy
// signers for signing JWS messages.
//
// Usually there's no need to use this option, as the new signers and
// verifiers are loaded by default.
// WithLegacySigners is a no-op option that exists only for backwards compatibility.
func WithLegacySigners() GlobalOption {
return &globalOption{option.New(identLegacySigners{}, true)}
}

View File

@@ -2,6 +2,7 @@ package jws
import (
"fmt"
"strings"
"sync"
"github.com/lestrrat-go/jwx/v3/jwa"
@@ -33,6 +34,19 @@ func (fn SignerFactoryFn) Create() (Signer, error) {
return fn()
}
func init() {
// register the signers using jwsbb. These will be used by default.
for _, alg := range jwa.SignatureAlgorithms() {
if alg == jwa.NoSignature() {
continue
}
if err := RegisterSigner(alg, defaultSigner{alg: alg}); err != nil {
panic(fmt.Sprintf("RegisterSigner failed: %v", err))
}
}
}
// SignerFor returns a Signer2 for the given signature algorithm.
//
// Currently, this function will never fail. It will always return a
@@ -43,6 +57,9 @@ func (fn SignerFactoryFn) Create() (Signer, error) {
// 3. If no Signer2 or legacy Signer(Factory) is registered, it will return a
// default signer that uses jwsbb.Sign.
//
// 1 and 2 will take care of 99% of the cases. The only time 3 will happen is
// when you are using a custom algorithm that is not supported out of the box.
//
// jwsbb.Sign knows how to handle a static set of algorithms, so if the
// algorithm is not supported, it will return an error when you call
// `Sign` on the default signer.
@@ -80,6 +97,14 @@ var signerDB = make(map[jwa.SignatureAlgorithm]SignerFactory)
// Unlike the `UnregisterSigner` function, this function automatically
// calls `jwa.RegisterSignatureAlgorithm` to register the algorithm
// in this module's algorithm database.
//
// For backwards compatibility, this function also accepts
// `SignerFactory` implementations, but this usage is deprecated.
// You should use `Signer2` implementations instead.
//
// If you want to completely remove an algorithm, you must call
// `jwa.UnregisterSignatureAlgorithm` yourself after calling
// `UnregisterSigner`.
func RegisterSigner(alg jwa.SignatureAlgorithm, f any) error {
jwa.RegisterSignatureAlgorithm(alg)
switch s := f.(type) {
@@ -87,22 +112,10 @@ func RegisterSigner(alg jwa.SignatureAlgorithm, f any) error {
muSigner2DB.Lock()
signer2DB[alg] = s
muSigner2DB.Unlock()
// delete the other signer, if there was one
muSignerDB.Lock()
delete(signerDB, alg)
muSignerDB.Unlock()
case SignerFactory:
muSignerDB.Lock()
signerDB[alg] = s
muSignerDB.Unlock()
// Remove previous signer, if there was one
removeSigner(alg)
muSigner2DB.Lock()
delete(signer2DB, alg)
muSigner2DB.Unlock()
default:
return fmt.Errorf(`jws.RegisterSigner: unsupported type %T for algorithm %q`, f, alg)
}
@@ -132,11 +145,25 @@ func UnregisterSigner(alg jwa.SignatureAlgorithm) {
}
// NewSigner creates a signer that signs payloads using the given signature algorithm.
// This function is deprecated. You should use `SignerFor()` instead.
// This function is deprecated, and will either be removed to re-purposed using
// a different signature.
//
// This function only exists for backwards compatibility, but will not work
// unless you enable the legacy support mode by calling jws.Settings(jws.WithLegacySigners(true)).
// When you want to load a Signer object, you should use `SignerFor()` instead.
func NewSigner(alg jwa.SignatureAlgorithm) (Signer, error) {
s, err := newLegacySigner(alg)
if err == nil {
return s, nil
}
if strings.HasPrefix(err.Error(), `jws.NewSigner: unsupported signature algorithm`) {
// When newLegacySigner fails, automatically trigger to enable signers
enableLegacySignersOnce.Do(enableLegacySigners)
return newLegacySigner(alg)
}
return nil, err
}
func newLegacySigner(alg jwa.SignatureAlgorithm) (Signer, error) {
muSignerDB.RLock()
f, ok := signerDB[alg]
muSignerDB.RUnlock()

View File

@@ -66,7 +66,7 @@ func (o *TokenOptionSet) Enable(flag TokenOption) {
*o = TokenOptionSet(o.Value() | uint64(flag))
}
// Enable sets the appropriate value to disable the option in the
// Disable sets the appropriate value to disable the option in the
// option set
func (o *TokenOptionSet) Disable(flag TokenOption) {
*o = TokenOptionSet(o.Value() & ^uint64(flag))

View File

@@ -17,9 +17,9 @@ const _TokenOption_name = "FlattenAudienceMaxPerTokenOption"
var _TokenOption_index = [...]uint8{0, 15, 32}
func (i TokenOption) String() string {
i -= 1
if i >= TokenOption(len(_TokenOption_index)-1) {
return "TokenOption(" + strconv.FormatInt(int64(i+1), 10) + ")"
idx := int(i) - 1
if i < 1 || idx >= len(_TokenOption_index)-1 {
return "TokenOption(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _TokenOption_name[_TokenOption_index[i]:_TokenOption_index[i+1]]
return _TokenOption_name[_TokenOption_index[idx]:_TokenOption_index[idx+1]]
}

View File

@@ -6,10 +6,12 @@ import (
)
type safeType struct {
reflect.Type
cfg *frozenConfig
Type reflect.Type
cfg *frozenConfig
}
var _ Type = &safeType{}
func (type2 *safeType) New() interface{} {
return reflect.New(type2.Type).Interface()
}
@@ -18,6 +20,22 @@ func (type2 *safeType) UnsafeNew() unsafe.Pointer {
panic("does not support unsafe operation")
}
func (type2 *safeType) Kind() reflect.Kind {
return type2.Type.Kind()
}
func (type2 *safeType) Len() int {
return type2.Type.Len()
}
func (type2 *safeType) NumField() int {
return type2.Type.NumField()
}
func (type2 *safeType) String() string {
return type2.Type.String()
}
func (type2 *safeType) Elem() Type {
return type2.cfg.Type2(type2.Type.Elem())
}

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