diff --git a/.drone.star b/.drone.star index 810cd8d68137..988cff95a8b3 100644 --- a/.drone.star +++ b/.drone.star @@ -1,12 +1,10 @@ ATMOZ_SFTP = "atmoz/sftp" -DRONE_CLI_ALPINE = "drone/cli:alpine" INBUCKET_INBUCKET = "inbucket/inbucket" MINIO_MC_RELEASE_2020_VERSION = "minio/mc:RELEASE.2020-12-10T01-26-17Z" OC_CI_ALPINE = "owncloudci/alpine:latest" OC_CI_BAZEL_BUILDIFIER = "owncloudci/bazel-buildifier" OC_CI_CEPH = "owncloudci/ceph:tag-build-master-jewel-ubuntu-16.04" OC_CI_CORE_NODEJS = "owncloudci/core:nodejs14" -OC_CI_DRONE_CANCEL_PREVIOUS_BUILDS = "owncloudci/drone-cancel-previous-builds" OC_CI_DRONE_SKIP_PIPELINE = "owncloudci/drone-skip-pipeline" OC_CI_NODEJS = "owncloudci/nodejs:%s" OC_CI_ORACLE_XE = "owncloudci/oracle-xe:latest" @@ -26,13 +24,28 @@ POTTAVA_PROXY = "pottava/proxy" SELENIUM_STANDALONE_CHROME_DEBUG = "selenium/standalone-chrome-debug:3.141.59-oxygen" SELENIUM_STANDALONE_FIREFOX_DEBUG = "selenium/standalone-firefox-debug:3.8.1" SONARSOURCE_SONAR_SCANNER_CLI = "sonarsource/sonar-scanner-cli" -THEGEEKLAB_DRONE_GITHUB_COMMENT = "thegeeklab/drone-github.amrom.workers.devment:1" TOOLHIPPIE_CALENS = "toolhippie/calens:latest" WEBHIPPIE_REDIS = "webhippie/redis:latest" DEFAULT_PHP_VERSION = "7.4" DEFAULT_NODEJS_VERSION = "14" +# minio mc environment variables +MINIO_MC_ENV = { + "CACHE_BUCKET": { + "from_secret": "cache_s3_bucket", + }, + "MC_HOST": { + "from_secret": "cache_s3_server", + }, + "AWS_ACCESS_KEY_ID": { + "from_secret": "cache_s3_access_key", + }, + "AWS_SECRET_ACCESS_KEY": { + "from_secret": "cache_s3_secret_key", + }, +} + dir = { "base": "/drone", "server": "/drone/src", @@ -44,7 +57,7 @@ dir = { config = { "rocketchat": { "channel": "server", - "from_secret": "public_rocketchat", + "from_secret": "rocketchat_talk_webhook", }, "branches": [ "master", @@ -72,6 +85,7 @@ config = { "mariadb:10.6", "mariadb:10.7", "mariadb:10.8", + "mariadb:10.11", "mysql:5.5", "mysql:5.7", "mysql:8.0", @@ -91,6 +105,18 @@ config = { "oracle", ], }, + "ubuntu22": { + "phpVersions": [ + "7.4-ubuntu22.04", + ], + # These pipelines are run just to help avoid any obscure regression + # on Ubuntu 22.04. We do not need coverage for this. + "coverage": False, + "databases": [ + "sqlite", + "mariadb:10.6", + ], + }, "external-samba": { "phpVersions": [ DEFAULT_PHP_VERSION, @@ -281,6 +307,10 @@ config = { "testingRemoteSystem": False, }, "cliEncryption": { + "phpVersions": [ + DEFAULT_PHP_VERSION, + "7.4-ubuntu22.04", + ], "suites": [ "cliEncryption", ], @@ -459,6 +489,18 @@ config = { "runAllSuites": True, "numberOfParts": 8, }, + "apiUbuntu22": { + "phpVersions": [ + "7.4-ubuntu22.04", + ], + "suites": { + "apiUbuntu22": "apiUbuntu22", + }, + "useHttps": False, + "filterTags": "@smokeTest&&~@notifications-app-required&&~@local_storage&&~@files_external-app-required", + "runAllSuites": True, + "numberOfParts": 8, + }, "apiOnSqlite": { "suites": { "apiOnSqlite": "apiOnSqlite", @@ -513,7 +555,7 @@ def initialPipelines(ctx): return dependencies(ctx) + checkStarlark() def beforePipelines(ctx): - return codestyle(ctx) + changelog(ctx) + cancelPreviousBuilds() + phpstan(ctx) + phan(ctx) + return codestyle(ctx) + changelog(ctx) + phpstan(ctx) + phan(ctx) def coveragePipelines(ctx): # All unit test pipelines that have coverage or other test analysis reported @@ -795,31 +837,6 @@ def changelog(ctx): return pipelines -def cancelPreviousBuilds(): - return [{ - "kind": "pipeline", - "type": "docker", - "name": "cancel-previous-builds", - "clone": { - "disable": True, - }, - "steps": [{ - "name": "cancel-previous-builds", - "image": OC_CI_DRONE_CANCEL_PREVIOUS_BUILDS, - "settings": { - "DRONE_TOKEN": { - "from_secret": "drone_token", - }, - }, - }], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - ], - }, - }] - def phpstan(ctx): pipelines = [] @@ -1306,7 +1323,7 @@ def javascript(ctx, withCoverage): "image": PLUGINS_S3, "settings": { "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "bucket": "cache", "source": "tests/output/coverage/lcov.info", @@ -1349,6 +1366,7 @@ def phpTests(ctx, testType, withCoverage): "mariadb:10.6", "mariadb:10.7", "mariadb:10.8", + "mariadb:10.11", "mysql:5.5", "mysql:5.7", "mysql:8.0", @@ -1381,6 +1399,9 @@ def phpTests(ctx, testType, withCoverage): "mariadb:10.6", "mariadb:10.7", "mariadb:10.8", + "mariadb:10.9", + "mariadb:10.10", + "mariadb:10.11", "mysql:5.5", "mysql:5.7", "mysql:8.0", @@ -1446,18 +1467,15 @@ def phpTests(ctx, testType, withCoverage): else: command = "unknown tbd" - # Get the first 3 characters of the PHP version (7.4 or 8.0 etc) - # And use that for constructing the pipeline name - # That helps shorten pipeline names when using owncloud-ci images - # that have longer names like 7.4-ubuntu20.04 - phpMinorVersion = phpVersion[0:3] + # Shorten PHP docker tags that have longer names like 7.4-ubuntu22.04 + phpVersionString = phpVersion.replace("-ubuntu", "-u") for db in params["databases"]: for externalType in params["externalTypes"]: keyString = "-" + category if params["includeKeyInMatrixName"] else "" filesExternalType = externalType if externalType != "none" else "" externalNameString = "-" + externalType if externalType != "none" else "" - name = "%s%s-php%s-%s%s" % (testType, keyString, phpMinorVersion, getShortDbNameAndVersion(db), externalNameString) + name = "%s%s-php%s-%s%s" % (testType, keyString, phpVersionString, getShortDbNameAndVersion(db), externalNameString) maxLength = 50 nameLength = len(name) if nameLength > maxLength: @@ -1571,7 +1589,7 @@ def phpTests(ctx, testType, withCoverage): "image": PLUGINS_S3, "settings": { "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "bucket": "cache", "source": "tests/output/coverage/clover-%s.xml" % (name), @@ -1592,7 +1610,7 @@ def phpTests(ctx, testType, withCoverage): "image": PLUGINS_S3, "settings": { "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "bucket": "cache", "source": "tests/output/coverage/clover-%s-%s.xml" % (name, externalType), @@ -1662,7 +1680,6 @@ def acceptance(ctx): "skipExceptParts": [], "testAgainstCoreTarball": False, "coreTarball": "daily-master-qa", - "earlyFail": True, "selUserNeeded": False, "dbServices": [], } @@ -1703,9 +1720,6 @@ def acceptance(ctx): if params["skip"]: continue - if ("full-ci" in ctx.build.title.lower()): - params["earlyFail"] = False - if isAPI or isCLI: params["browsers"] = [""] @@ -1726,11 +1740,8 @@ def acceptance(ctx): for federatedServerVersion in params["federatedServerVersions"]: for browser in params["browsers"]: for phpVersion in params["phpVersions"]: - # Get the first 3 characters of the PHP version (7.4 or 8.0 etc) - # And use that for constructing the pipeline name - # That helps shorten pipeline names when using owncloud-ci images - # that have longer names like 7.4-ubuntu20.04 - phpMinorVersion = phpVersion[0:3] + # Shorten PHP docker tags that have longer names like 7.4-ubuntu22.04 + phpVersionString = phpVersion.replace("-ubuntu", "-u") for db in params["databases"]: for runPart in range(1, params["numberOfParts"] + 1): debugPartsEnabled = (len(params["skipExceptParts"]) != 0) @@ -1752,7 +1763,7 @@ def acceptance(ctx): keyString = "-" + category if params["includeKeyInMatrixName"] else "" partString = "" if params["numberOfParts"] == 1 else "-%d-%d" % (params["numberOfParts"], runPart) federatedServerVersionString = "-" + federatedServerVersion.replace("daily-", "").replace("-qa", "") if (federatedServerVersion != "") else "" - name = "%s%s%s%s%s-%s-php%s" % (alternateSuiteName, keyString, partString, federatedServerVersionString, browserString, getShortDbNameAndVersion(db), phpMinorVersion) + name = "%s%s%s%s%s-%s-php%s" % (alternateSuiteName, keyString, partString, federatedServerVersionString, browserString, getShortDbNameAndVersion(db), phpVersionString) maxLength = 50 nameLength = len(name) if nameLength > maxLength: @@ -1880,7 +1891,7 @@ def acceptance(ctx): "path": "%s/downloads" % dir["server"], }], }), - ] + githubComment(params["earlyFail"]) + stopBuild(params["earlyFail"]), + ], "services": dbServices + browserService(browser) + emailService(params["emailNeeded"]) + @@ -1961,14 +1972,11 @@ def sonarAnalysis(ctx, phpVersion = DEFAULT_PHP_VERSION): { "name": "sync-from-cache", "image": MINIO_MC_RELEASE_2020_VERSION, - "environment": { - "MC_HOST_cache": { - "from_secret": "cache_s3_connection_url", - }, - }, + "environment": MINIO_MC_ENV, "commands": [ "mkdir -p results", - "mc mirror cache/cache/%s/%s/coverage results/" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), + "mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY", + "mc mirror cache/$CACHE_BUCKET/%s/%s/coverage results/" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), ], }, { @@ -1995,13 +2003,10 @@ def sonarAnalysis(ctx, phpVersion = DEFAULT_PHP_VERSION): { "name": "purge-cache", "image": MINIO_MC_RELEASE_2020_VERSION, - "environment": { - "MC_HOST_cache": { - "from_secret": "cache_s3_connection_url", - }, - }, + "environment": MINIO_MC_ENV, "commands": [ - "mc rm --recursive --force cache/cache/%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), + "mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY", + "mc rm --recursive --force cache/$CACHE_BUCKET/%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), ], }, ], @@ -2057,60 +2062,6 @@ def notify(): return result -def stopBuild(earlyFail): - if (earlyFail): - return [{ - "name": "stop-build", - "image": DRONE_CLI_ALPINE, - "environment": { - "DRONE_SERVER": "https://drone.owncloud.com", - "DRONE_TOKEN": { - "from_secret": "drone_token", - }, - }, - "commands": [ - "drone build stop owncloud/core ${DRONE_BUILD_NUMBER}", - ], - "when": { - "status": [ - "failure", - ], - "event": [ - "pull_request", - ], - }, - }] - - else: - return [] - -def githubComment(earlyFail): - if (earlyFail): - return [{ - "name": "github.amrom.workers.devment", - "image": THEGEEKLAB_DRONE_GITHUB_COMMENT, - "pull": "if-not-exists", - "settings": { - "message": ":boom: Acceptance tests pipeline ${DRONE_STAGE_NAME} failed. The build has been cancelled.\\n\\n${DRONE_BUILD_LINK}/${DRONE_JOB_NUMBER}${DRONE_STAGE_NUMBER}", - "key": "pr-${DRONE_PULL_REQUEST}", - "update": "true", - "api_key": { - "from_secret": "github_token", - }, - }, - "when": { - "status": [ - "failure", - ], - "event": [ - "pull_request", - ], - }, - }] - - else: - return [] - def databaseService(db): dbName = getDbName(db) if (dbName == "mariadb") or (dbName == "mysql"): @@ -2355,7 +2306,7 @@ def owncloudService(phpVersion, name, pathOfServerUnderTest, ssl): }] def getShortDbNameAndVersion(db): - return "%s%s" % (getDbType(db), getDbVersion(db)) + return "%s%s" % (getDbShortName(db), getDbVersion(db)) def getDbName(db): return db.partition(":")[0] @@ -2403,6 +2354,19 @@ def getDbType(db): return dbName +def getDbShortName(db): + dbName = getDbName(db) + if dbName == "postgres": + return "pgsql" + + if dbName == "oracle": + return "oci" + + if dbName == "mariadb": + return "maria" + + return dbName + def cacheRestore(): return [{ "name": "cache-restore", @@ -2412,7 +2376,7 @@ def cacheRestore(): "from_secret": "cache_s3_access_key", }, "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "restore": True, "secret_key": { @@ -2455,7 +2419,7 @@ def cacheRebuildOnEventPush(): "from_secret": "cache_s3_access_key", }, "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "mount": [ ".cache", @@ -2485,7 +2449,7 @@ def cacheFlushOnEventPush(): "from_secret": "cache_s3_access_key", }, "endpoint": { - "from_secret": "cache_s3_endpoint", + "from_secret": "cache_s3_server", }, "flush": True, "flush_age": "14", diff --git a/CHANGELOG.html b/CHANGELOG.html index 0424d407591f..6a4c0b369fd6 100644 --- a/CHANGELOG.html +++ b/CHANGELOG.html @@ -2,29 +2,249 @@

Changelog for ownCloud Core [unreleased] (UNRELEASED)

The following sections list the changes in ownCloud core unreleased relevant to ownCloud admins and users.

- Full list of changes in unreleased + Full list of changes in unreleased

Summary

Details

+

Changelog for ownCloud Core [10.12.2] (2023-05-31)

+

The following sections list the changes in ownCloud core 10.12.2 relevant to ownCloud admins and users.

+

+ Full list of changes in 10.12.2 +

+

Summary

+ +

Details

+

Changelog for ownCloud Core [10.12.1] (2023-04-03)

The following sections list the changes in ownCloud core 10.12.1 relevant to ownCloud admins and users.

@@ -7407,7 +7627,7 @@

User management

External storage

Dav App

diff --git a/CHANGELOG.md b/CHANGELOG.md index a776d417da6b..ca2752477c6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,35 +3,277 @@ Changelog for ownCloud Core [unreleased] (UNRELEASED) The following sections list the changes in ownCloud core unreleased relevant to ownCloud admins and users. -[unreleased]: https://github.com/owncloud/core/compare/v10.12.1...master +[unreleased]: https://github.com/owncloud/core/compare/v10.12.2...master Summary ------- +* Bugfix - Align to new accounts.google.com authorization URI: [#40783](https://github.com/owncloud/core/pull/40783) +* Bugfix - Always return an int for the Symfony Command execute method: [#40793](https://github.com/owncloud/core/pull/40793) +* Bugfix - Exit with success when signing-key has been set: [#40794](https://github.com/owncloud/core/pull/40794) +* Bugfix - Fix query used to delete thumbnails: [#40800](https://github.com/owncloud/core/issues/40800) +* Bugfix - Always use json for federation post and get to exchange tokens: [#40815](https://github.com/owncloud/core/pull/40815) +* Bugfix - Rare undefined variable error when using a Google Drive mount: [#40822](https://github.com/owncloud/core/pull/40822) +* Bugfix - Explicitly set open mode in the checksum wrapper: [#40832](https://github.com/owncloud/core/pull/40832) +* Bugfix - Automatically disable online updater for enterprise: [#40841](https://github.com/owncloud/core/pull/40841) +* Bugfix - Verbose command output: [#40844](https://github.com/owncloud/core/pull/40844) +* Bugfix - Versions expire job does not error with federated shares: [#40847](https://github.com/owncloud/core/pull/40847) +* Bugfix - Request header can hold an empty string if not set: [#40856](https://github.com/owncloud/core/pull/40856) +* Bugfix - Skip share_folder for guest users: [#40864](https://github.com/owncloud/core/pull/40864) +* Change - Upgrade to Symfony 5: [#39630](https://github.com/owncloud/core/issues/39630) * Change - Update PHP dependencies: [#40724](https://github.com/owncloud/core/pull/40724) * Change - Fix name length check on federated shares: [#40726](https://github.com/owncloud/core/pull/40726) +* Change - Validate email and string user input in UserController: [#40769](https://github.com/owncloud/core/pull/40769) +* Change - Fix hiding Last Login column on Users page: [#40771](https://github.com/owncloud/core/pull/40771) +* Change - Fix name length check on system tag creation: [#40804](https://github.com/owncloud/core/pull/40804) +* Enhancement - Improve X-Robots-Tag header values check: [#40715](https://github.com/owncloud/core/pull/40715) +* Enhancement - Added occ command to remove obsolete storages: [#40779](https://github.com/owncloud/core/pull/40779) +* Enhancement - Add commands to handle the trusted servers from command line: [#40796](https://github.com/owncloud/core/pull/40796) +* Enhancement - Enforce 2-factor authentication: [#40830](https://github.com/owncloud/core/pull/40830) +* Enhancement - Improve the performance of the occ files:remove-storage command: [#40859](https://github.com/owncloud/core/pull/40859) Details ------- +* Bugfix - Align to new accounts.google.com authorization URI: [#40783](https://github.com/owncloud/core/pull/40783) + + Core 10.12.1 brought an update of the google/apiclient from version 2.12.6 to 2.13.1. + However, in version 2.13.0 the accounts.google.com authorization URI has been updated. This + change breaks old code that uses the "setApprovalPrompt('force')" instead of the newer + "setPrompt('consent')" method, as this endpoint does not support the legacy approval prompt + parameter. This has been now fixed. + + https://github.com/owncloud/core/issues/40777 + https://github.com/owncloud/core/pull/40783 + +* Bugfix - Always return an int for the Symfony Command execute method: [#40793](https://github.com/owncloud/core/pull/40793) + + Some occ commands could return an invalid exit status when executed. This has been corrected. + occ commands will now always return an integer exit status. Zero (0) is success, any other value + indicates a problem. + + https://github.com/owncloud/core/pull/40793 + +* Bugfix - Exit with success when signing-key has been set: [#40794](https://github.com/owncloud/core/pull/40794) + + The "occ security:sign-key:create" command exited with status 1 even when the signing key was + successfully created. This has been corrected. The command now exits with status zero (0) when + the command succeeded. + + For all occ commands, zero (0) is success, any other value indicates a problem. + + https://github.com/owncloud/core/pull/40794 + +* Bugfix - Fix query used to delete thumbnails: [#40800](https://github.com/owncloud/core/issues/40800) + + Fixed query that detects unused thumbnails to prevent unnecessary deletes and potential + recreations. + + https://github.com/owncloud/core/issues/40800 + https://github.com/owncloud/core/pull/40801 + +* Bugfix - Always use json for federation post and get to exchange tokens: [#40815](https://github.com/owncloud/core/pull/40815) + + After update of guzzle, it was no longer possible to request format of response to be json when + adding in query parameter. One of OCSAuthAPIController fed instances was receiving requests + without a hint that JSON needs to be used, and returned XML. On the other hand, + OCSAuthAPIController expects only JSON for exchange, and thus failed to parse the message. + Now the exchange is correctly done. + + WARNING: the patch/fix needs to be applied on all federated severs that are not yet "paired" and + have the issue with guzzle library. Otherwise pairing will not work. + + https://github.com/owncloud/enterprise/issues/5676 + https://github.com/owncloud/core/pull/40815 + +* Bugfix - Rare undefined variable error when using a Google Drive mount: [#40822](https://github.com/owncloud/core/pull/40822) + + There can be the rare case that deleting a file from a Google Drive mount can throw an undefined + variable error. Though the process completes without further issues, no errors should be + thrown. This fix initializes the variables for these cases properly making the error go away. + + https://github.com/owncloud/core/issues/40802 + https://github.com/owncloud/core/pull/40822 + +* Bugfix - Explicitly set open mode in the checksum wrapper: [#40832](https://github.com/owncloud/core/pull/40832) + + Uploading files to some external storages through the desktop client was causing issues due to + the checksum wrapper. We're using additional wrappers and the mode wasn't being detected + correctly in some cases. Using the right mode in the checksum wrapper was required in order to + decide whether we should discard the final checksum or not; in this case, the checksum was being + discarded, so it was causing a checksum mismatch. + + Now the open mode in the checksum wrapper is set explicitly. + + https://github.com/owncloud/core/pull/40832 + +* Bugfix - Automatically disable online updater for enterprise: [#40841](https://github.com/owncloud/core/pull/40841) + + Online updater is not recommended for Enterprise installations and is now automatically + disabled in such cases. + + https://github.com/owncloud/core/pull/40841 + +* Bugfix - Verbose command output: [#40844](https://github.com/owncloud/core/pull/40844) + + Verbose command output of the background:queue:execute is now displayed. + + https://github.com/owncloud/core/pull/40844 + +* Bugfix - Versions expire job does not error with federated shares: [#40847](https://github.com/owncloud/core/pull/40847) + + Versions expire job does not error with federated shares when versioning meta- data is + enabled. + + https://github.com/owncloud/core/pull/40847 + +* Bugfix - Request header can hold an empty string if not set: [#40856](https://github.com/owncloud/core/pull/40856) + + Due to Apache rewrite rules originally not existing headers can hold an empty string. + + https://github.com/owncloud/core/pull/40856 + +* Bugfix - Skip share_folder for guest users: [#40864](https://github.com/owncloud/core/pull/40864) + + In https://github.com/owncloud/core/pull/40378 we've fixed the case of (not) moving the + share target when the backend storage becomes temporary unavailable but we had the collateral + effect that guests did not see anymore their received shares as we were forcing the creation of + the target which failed for them as their storage is read-only. We now skip the share_folder + config.php option for guests and default to root. + + https://github.com/owncloud/core/pull/40864 + +* Change - Upgrade to Symfony 5: [#39630](https://github.com/owncloud/core/issues/39630) + + The Symfony PHP framework has been updated from major version 4 to 5. + + The following Symfony component versions are provided: - symfony/console (v5.4.24) - + symfony/event-dispatcher (v5.4.22) - symfony/process (v5.4.24) - symfony/routing + (v5.4.25) - symfony/string (v5.4.22) - symfony/translation (v5.4.24) + + https://github.com/owncloud/core/issues/39630 + https://github.com/owncloud/core/pull/40518 + https://github.com/owncloud/core/pull/40819 + https://github.com/owncloud/core/pull/40849 + * Change - Update PHP dependencies: [#40724](https://github.com/owncloud/core/pull/40724) - The following have been updated: - guzzlehttp/guzzle (7.5.0 to 7.5.1) - punic/punic (3.8.0 to - 3.8.1) + The following have been updated: - doctrine/deprecations (1.0.0 to 1.1.1) - + egulias/email-validator (3.2.5 to 3.2.6) - guzzlehttp/guzzle (7.5.0 to 7.7.0) - + owncloud/tarstreamer (2.0.0 to 2.1.0) - pear/pear-core-minimal (1.10.11 to 1.10.13) - + phpseclib/phpseclib (3.0.19 to 3.0.21) - punic/punic (3.8.0 to 3.8.1) - sabre/http (5.1.6 to + 5.1.7) - sabre/uri (2.3.2 to 2.3.3) - sabre/xml (2.2.5 to 2.2.6) The following have been updated in apps/files_external/3rdparty: - google/apiclient - (2.13.1 to 2.13.2) + (2.13.1 to 2.13.2) - firebase/php-jwt (v6.4.0 to v6.6.0) https://github.com/owncloud/core/pull/40724 https://github.com/owncloud/core/pull/40731 https://github.com/owncloud/core/pull/40742 + https://github.com/owncloud/core/pull/40753 + https://github.com/owncloud/core/pull/40789 + https://github.com/owncloud/core/pull/40806 + https://github.com/owncloud/core/pull/40819 + https://github.com/owncloud/core/pull/40825 + https://github.com/owncloud/core/pull/40833 + https://github.com/owncloud/core/pull/40838 + https://github.com/owncloud/core/pull/40839 + https://github.com/owncloud/core/pull/40849 + https://github.com/owncloud/core/pull/40853 + https://github.com/owncloud/core/pull/40854 + https://github.com/owncloud/core/pull/40867 * Change - Fix name length check on federated shares: [#40726](https://github.com/owncloud/core/pull/40726) - A federated share with a too long name results in inaccessible data. + A federated share with a too long name results in potentially inaccessible data. https://github.com/owncloud/core/pull/40726 +* Change - Validate email and string user input in UserController: [#40769](https://github.com/owncloud/core/pull/40769) + + User input is validated now in UserController + + https://github.com/owncloud/core/pull/40769 + +* Change - Fix hiding Last Login column on Users page: [#40771](https://github.com/owncloud/core/pull/40771) + + The Last Login column on the Users page is now correctly hidden if the setting is initially + unchecked. + + https://github.com/owncloud/core/pull/40771 + +* Change - Fix name length check on system tag creation: [#40804](https://github.com/owncloud/core/pull/40804) + + A system tag with a too long name results in potentially inaccessible data. + + https://github.com/owncloud/core/pull/40804 + +* Enhancement - Improve X-Robots-Tag header values check: [#40715](https://github.com/owncloud/core/pull/40715) + + Setup checks now allows other values other than "none" for X-Robots-Tag header. If "none" or + "noindex" and "nofollow" are missing, a security warning is raised. Previously a header value + with "noindex" and "nofollow" wasn't allowed even though it was valid. + + https://github.com/owncloud/core/pull/40715 + +* Enhancement - Added occ command to remove obsolete storages: [#40779](https://github.com/owncloud/core/pull/40779) + + Metadata coming from storages are stored in the DB. When a storage has been removed from + ownCloud, that metadata remains in the DB. + + The new occ command allows you to remove that metadata stored, reducing the amount of space used + by the DB as well as slightly improving the performance since there will be less entries. + + https://github.com/owncloud/core/pull/40779 + +* Enhancement - Add commands to handle the trusted servers from command line: [#40796](https://github.com/owncloud/core/pull/40796) + + New occ commands have been added to handle the trusted servers for federation from command + line. These commands will allow the admin to add list and remove trusted servers + + https://github.com/owncloud/core/pull/40796 + +* Enhancement - Enforce 2-factor authentication: [#40830](https://github.com/owncloud/core/pull/40830) + + 2-factor authentication can be enforced now. The feature requires at least an app + implementing the 2-factor, otherwise no enforcement will be done. If the 2-factor + authentication is enforced, all users will be required to use a 2-factor authentication app. + Some specific groups selected by the admin can be excluded to let those users bypass the + 2-factor authentication. + + https://github.com/owncloud/core/pull/40830 + +* Enhancement - Improve the performance of the occ files:remove-storage command: [#40859](https://github.com/owncloud/core/pull/40859) + + The "--show-candidates" option of the "occ files:remove-storage" command will take less + time + + https://github.com/owncloud/core/pull/40859 + +Changelog for ownCloud Core [10.12.2] (2023-05-31) +======================================= +The following sections list the changes in ownCloud core 10.12.2 relevant to +ownCloud admins and users. + +[10.12.2]: https://github.com/owncloud/core/compare/v10.12.1...v10.12.2 + +Summary +------- + +* Bugfix - Filter sensitive data in log for Session::loginInOwnCloud: [#40792](https://github.com/owncloud/core/pull/40792) +* Bugfix - Disallow permission tobe upgraded via federated sharing: [#40803](https://github.com/owncloud/core/pull/40803) + +Details +------- + +* Bugfix - Filter sensitive data in log for Session::loginInOwnCloud: [#40792](https://github.com/owncloud/core/pull/40792) + + https://github.com/owncloud/core/pull/40792 + +* Bugfix - Disallow permission tobe upgraded via federated sharing: [#40803](https://github.com/owncloud/core/pull/40803) + + https://github.com/owncloud/core/pull/40803 + Changelog for ownCloud Core [10.12.1] (2023-04-03) ======================================= The following sections list the changes in ownCloud core 10.12.1 relevant to @@ -7733,7 +7975,7 @@ Details #### External storage - "Local" storage type can now be disabled by sysadmin in config.php [#26653](https://github.com/owncloud/core/issues/26653) -- External storage backends must use [core external storage API](https://doc.owncloud.org/server/10.0/developer_manual/app/extstorage.html) to work without "files_external" [#18160](https://github.com/owncloud/core/issues/18160) +- External storage backends must use [core external storage API](https://doc.owncloud.com/server/next/developer_manual/app/advanced/extstorage.html) to work without "files_external" [#18160](https://github.com/owncloud/core/issues/18160) - FTP external storage moved to a separate app [files_external_ftp](https://github.com/owncloud/files_external_ftp) #### Dav App diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 119e93eaf12f..58422bece507 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -925,7 +925,7 @@ public function getCardUri($id) { $result->closeCursor(); if (!isset($uri['uri'])) { - throw new \InvalidArgumentException('Card does not exists: ' . $id); + throw new \InvalidArgumentException('Card does not exist: ' . $id); } return $uri['uri']; @@ -1062,7 +1062,7 @@ protected function getCardId($addressBookId, $uri) { $result->closeCursor(); if (!isset($cardIds['id'])) { - throw new \InvalidArgumentException('Card does not exists: ' . $uri); + throw new \InvalidArgumentException('Card does not exist: ' . $uri); } return (int)$cardIds['id']; diff --git a/apps/dav/lib/Command/CleanupChunks.php b/apps/dav/lib/Command/CleanupChunks.php index 4120b2ff413e..1ae72b87b6a3 100644 --- a/apps/dav/lib/Command/CleanupChunks.php +++ b/apps/dav/lib/Command/CleanupChunks.php @@ -65,7 +65,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $checkUploadExistsLocal = $input->getOption('local') === true; $d = $input->getArgument('minimum-age-in-days'); $d = \max(2, \min($d, 100)); diff --git a/apps/dav/lib/Command/CreateAddressBook.php b/apps/dav/lib/Command/CreateAddressBook.php index 1cac5ccc3dbf..a9bd3a83f72f 100644 --- a/apps/dav/lib/Command/CreateAddressBook.php +++ b/apps/dav/lib/Command/CreateAddressBook.php @@ -64,7 +64,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $input->getArgument('user'); if (!$this->userManager->userExists($user)) { throw new \InvalidArgumentException("User <$user> in unknown."); diff --git a/apps/dav/lib/Command/CreateCalendar.php b/apps/dav/lib/Command/CreateCalendar.php index db10bfd853c6..0becd3a3a3bf 100644 --- a/apps/dav/lib/Command/CreateCalendar.php +++ b/apps/dav/lib/Command/CreateCalendar.php @@ -70,7 +70,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $input->getArgument('user'); if (!$this->userManager->userExists($user)) { throw new \InvalidArgumentException("User <$user> in unknown."); @@ -82,7 +82,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { $groupPrincipalBackend = new GroupPrincipalBackend( $this->groupManager ); - $config = \OC::$server->getConfig(); $random = \OC::$server->getSecureRandom(); $name = $input->getArgument('name'); diff --git a/apps/dav/lib/Command/SyncBirthdayCalendar.php b/apps/dav/lib/Command/SyncBirthdayCalendar.php index 8e863d5e18cf..aac0c0f1013e 100644 --- a/apps/dav/lib/Command/SyncBirthdayCalendar.php +++ b/apps/dav/lib/Command/SyncBirthdayCalendar.php @@ -64,7 +64,7 @@ protected function configure() { * * @return int 0 if everything went fine, or an exit code */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $input->getArgument('user'); if ($user !== null) { if (!$this->userManager->userExists($user)) { diff --git a/apps/dav/lib/Command/SyncSystemAddressBook.php b/apps/dav/lib/Command/SyncSystemAddressBook.php index 6e51ae431041..8ebf40efbc61 100644 --- a/apps/dav/lib/Command/SyncSystemAddressBook.php +++ b/apps/dav/lib/Command/SyncSystemAddressBook.php @@ -50,7 +50,7 @@ protected function configure() { * * @return int 0 if everything went fine, or an exit code */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('Syncing users ...'); $progress = new ProgressBar($output); $progress->start(); diff --git a/apps/dav/lib/Connector/Sabre/BlockLegacyClientPlugin.php b/apps/dav/lib/Connector/Sabre/BlockLegacyClientPlugin.php index a2e12c2f5461..789d7aa42d67 100644 --- a/apps/dav/lib/Connector/Sabre/BlockLegacyClientPlugin.php +++ b/apps/dav/lib/Connector/Sabre/BlockLegacyClientPlugin.php @@ -66,7 +66,7 @@ public function beforeHandler(RequestInterface $request) { return; } - $minimumSupportedDesktopVersion = $this->config->getSystemValue('minimum.supported.desktop.version', '2.3.3'); + $minimumSupportedDesktopVersion = $this->config->getSystemValue('minimum.supported.desktop.version', '3.2.1'); // Match on the mirall version which is in scheme "Mozilla/5.0 (%1) mirall/%2" or // "mirall/%1" for older releases diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php index afafa4dcc14a..b6d9e83d3250 100644 --- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php @@ -133,7 +133,9 @@ private function getSharesForNodeIds($nodeIDs) { \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, - \OCP\Share::SHARE_TYPE_REMOTE + \OCP\Share::SHARE_TYPE_REMOTE, + \OCP\Share::SHARE_TYPE_REMOTE_GROUP + ]; // Query DB for share types for specified node IDs diff --git a/apps/dav/lib/SystemTag/SystemTagPlugin.php b/apps/dav/lib/SystemTag/SystemTagPlugin.php index 82c852d111ee..d47cb09205af 100644 --- a/apps/dav/lib/SystemTag/SystemTagPlugin.php +++ b/apps/dav/lib/SystemTag/SystemTagPlugin.php @@ -161,7 +161,7 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) * @throws Conflict if a tag with the same properties already exists * @throws UnsupportedMediaType if the content type is not supported */ - private function createTag($data, $contentType = 'application/json') { + private function createTag($data, $contentType = 'application/json'): ISystemTag { if (\explode(';', $contentType)[0] === 'application/json') { $data = \json_decode($data, true); } else { @@ -171,6 +171,9 @@ private function createTag($data, $contentType = 'application/json') { if (!isset($data['name'])) { throw new BadRequest('Missing "name" attribute'); } + if (\strlen($data['name']) > 64) { + throw new BadRequest('Tag name too long'); + } $tagName = $data['name']; $userVisible = true; diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php index 9fefcf047ba3..25f631de9f6f 100644 --- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php @@ -91,7 +91,8 @@ public function testGetProperties($shareTypes) { \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, - \OCP\Share::SHARE_TYPE_REMOTE + \OCP\Share::SHARE_TYPE_REMOTE, + \OCP\Share::SHARE_TYPE_REMOTE_GROUP ]; $this->shareManager->expects($this->any()) @@ -172,7 +173,8 @@ public function testPreloadThenGetProperties($shareTypes) { \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, - \OCP\Share::SHARE_TYPE_REMOTE + \OCP\Share::SHARE_TYPE_REMOTE, + \OCP\Share::SHARE_TYPE_REMOTE_GROUP ]; $this->shareManager->expects($this->any()) diff --git a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php index e39b24127d9c..b1acf989c3ef 100644 --- a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php +++ b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php @@ -31,6 +31,10 @@ use OCP\IUserSession; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\TagAlreadyExistsException; +use Sabre\DAV\Exception\BadRequest; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; +use OCA\DAV\SystemTag\SystemTagsByIdCollection; class SystemTagPluginTest extends \Test\TestCase { public const ID_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::ID_PROPERTYNAME; @@ -383,7 +387,7 @@ public function createTagInsufficientPermissionsProvider() { * @dataProvider createTagInsufficientPermissionsProvider */ public function testCreateNotAssignableTagAsRegularUser($userVisible, $userAssignable, $userEditable, $groups) { - $this->expectException(\Sabre\DAV\Exception\BadRequest::class); + $this->expectException(BadRequest::class); $this->expectExceptionMessage('Not sufficient permissions'); $this->user->expects($this->once()) @@ -442,6 +446,54 @@ public function testCreateNotAssignableTagAsRegularUser($userVisible, $userAssig $this->plugin->httpPost($request, $response); } + public function testPostTooLongTagName(): void { + $this->expectException(BadRequest::class); + $this->expectExceptionMessage('Tag name too long'); + + $requestData = [ + 'name' => 'ThisTagNameIsByFarTooLong.ThisTagNameIsByFarTooLong.ThisTagNameIsByFarTooLong', + 'userVisible' => true, + 'userAssignable' => true, + 'userEditable' => true + ]; + $requestData = \json_encode($requestData); + + $node = $this->getMockBuilder(SystemTagsByIdCollection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->tagManager->expects($this->never()) + ->method('createTag'); + $this->tagManager->expects($this->never()) + ->method('setTagGroups'); + + $this->tree + ->method('getNodeForPath') + ->with('/systemtags') + ->willReturn($node); + + $request = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $response = $this->getMockBuilder(ResponseInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->once()) + ->method('getPath') + ->willReturn('/systemtags'); + + $request->expects($this->once()) + ->method('getBodyAsString') + ->willReturn($requestData); + + $request->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->willReturn('application/json'); + + $this->plugin->httpPost($request, $response); + } + public function testCreateTagInByIdCollectionAsRegularUser() { $systemTag = new SystemTag(1, 'Test', true, false); diff --git a/apps/federatedfilesharing/l10n/en_GB.js b/apps/federatedfilesharing/l10n/en_GB.js index 3dca2ec1e3fc..824a7ca08962 100644 --- a/apps/federatedfilesharing/l10n/en_GB.js +++ b/apps/federatedfilesharing/l10n/en_GB.js @@ -2,7 +2,9 @@ OC.L10N.register( "federatedfilesharing", { "Federated sharing" : "Federated sharing", + "Add to" : "Add to", "Loading..." : "Loading...", + "Change server..." : "Change server...", "Invalid Federated Cloud ID" : "Invalid Federated Cloud ID", "Sharing %s failed, because this item is already shared with %s" : "Sharing %s failed, because this item is already shared with %s", "Not allowed to create a federated share with the same user" : "Not allowed to create a federated share with the same user", @@ -19,8 +21,10 @@ OC.L10N.register( "Share with me through my #ownCloud Federated Cloud ID" : "Share with me through my #ownCloud Federated Cloud ID", "Federated Cloud Sharing" : "Federated Cloud Sharing", "Open documentation" : "Open documentation", + "Periodically synchronize outdated federated shares for active users" : "Periodically synchronise outdated federated shares for active users", "Allow users on this server to send shares to other servers" : "Allow users on this server to send shares to other servers", "Allow users on this server to receive shares from other servers" : "Allow users on this server to receive shares from other servers", + "Automatically accept federated shares from trusted servers" : "Automatically accept federated shares from trusted servers", "Federated Cloud" : "Federated Cloud", "Your Federated Cloud ID:" : "Your Federated Cloud ID:", "Share it:" : "Share it:", diff --git a/apps/federatedfilesharing/l10n/en_GB.json b/apps/federatedfilesharing/l10n/en_GB.json index a9357dcdb692..0961adbcc963 100644 --- a/apps/federatedfilesharing/l10n/en_GB.json +++ b/apps/federatedfilesharing/l10n/en_GB.json @@ -1,6 +1,8 @@ { "translations": { "Federated sharing" : "Federated sharing", + "Add to" : "Add to", "Loading..." : "Loading...", + "Change server..." : "Change server...", "Invalid Federated Cloud ID" : "Invalid Federated Cloud ID", "Sharing %s failed, because this item is already shared with %s" : "Sharing %s failed, because this item is already shared with %s", "Not allowed to create a federated share with the same user" : "Not allowed to create a federated share with the same user", @@ -17,8 +19,10 @@ "Share with me through my #ownCloud Federated Cloud ID" : "Share with me through my #ownCloud Federated Cloud ID", "Federated Cloud Sharing" : "Federated Cloud Sharing", "Open documentation" : "Open documentation", + "Periodically synchronize outdated federated shares for active users" : "Periodically synchronise outdated federated shares for active users", "Allow users on this server to send shares to other servers" : "Allow users on this server to send shares to other servers", "Allow users on this server to receive shares from other servers" : "Allow users on this server to receive shares from other servers", + "Automatically accept federated shares from trusted servers" : "Automatically accept federated shares from trusted servers", "Federated Cloud" : "Federated Cloud", "Your Federated Cloud ID:" : "Your Federated Cloud ID:", "Share it:" : "Share it:", diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php index 287626b69303..180c4bc64aa4 100644 --- a/apps/federatedfilesharing/lib/AppInfo/Application.php +++ b/apps/federatedfilesharing/lib/AppInfo/Application.php @@ -140,7 +140,8 @@ function ($c) use ($server) { $server->getUserManager(), $c->query('AddressHandler'), $c->query('FederatedShareManager'), - $server->getLogger() + $server->getLogger(), + $server->getConfig() ); } ); @@ -148,16 +149,7 @@ function ($c) use ($server) { $container->registerService( 'NotificationManager', function ($c) { - return new NotificationManager( - $c->query('Permissions') - ); - } - ); - - $container->registerService( - 'Permissions', - function ($c) { - return new Permissions(); + return new NotificationManager(); } ); @@ -208,9 +200,7 @@ protected function initFederatedShareProvider() { \OC::$server->getMemCacheFactory(), \OC::$server->getHTTPClientService() ); - $notificationManager = new NotificationManager( - new Permissions() - ); + $notificationManager = new NotificationManager(); $notifications = new Notifications( $addressHandler, \OC::$server->getHTTPClientService(), diff --git a/apps/federatedfilesharing/lib/Command/PollIncomingShares.php b/apps/federatedfilesharing/lib/Command/PollIncomingShares.php index 07b45efb4f23..482375399559 100644 --- a/apps/federatedfilesharing/lib/Command/PollIncomingShares.php +++ b/apps/federatedfilesharing/lib/Command/PollIncomingShares.php @@ -79,9 +79,9 @@ protected function configure() { * @param InputInterface $input * @param OutputInterface $output * - * @return int|null|void + * @return int */ - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $output->writeln("WARNING: incoming-shares:poll has been deprecated and replaced by periodic external shares cronjob. Please check Federated Cloud Sharing settings and documentation."); if ($this->externalMountProvider === null) { $output->writeln("Polling is not possible when files_sharing app is disabled. Please enable it with 'occ app:enable files_sharing'"); @@ -134,6 +134,7 @@ public function execute(InputInterface $input, OutputInterface $output) { } } $cursor->closeCursor(); + return 0; } /** diff --git a/apps/federatedfilesharing/lib/Controller/OcmController.php b/apps/federatedfilesharing/lib/Controller/OcmController.php index d739d268e633..74e1d8559840 100644 --- a/apps/federatedfilesharing/lib/Controller/OcmController.php +++ b/apps/federatedfilesharing/lib/Controller/OcmController.php @@ -32,10 +32,12 @@ use OCA\FederatedFileSharing\Ocm\Exception\OcmException; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\IConfig; use OCP\ILogger; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserManager; +use OCP\Share\Exceptions\ShareNotFound; /** * Class OcmController @@ -75,6 +77,9 @@ class OcmController extends Controller { */ protected $logger; + /** @var IConfig */ + private $config; + /** * OcmController constructor. * @@ -86,6 +91,7 @@ class OcmController extends Controller { * @param AddressHandler $addressHandler * @param FedShareManager $fedShareManager * @param ILogger $logger + * @param IConfig $config */ public function __construct( $appName, @@ -95,7 +101,8 @@ public function __construct( IUserManager $userManager, AddressHandler $addressHandler, FedShareManager $fedShareManager, - ILogger $logger + ILogger $logger, + IConfig $config ) { parent::__construct($appName, $request); @@ -105,6 +112,7 @@ public function __construct( $this->addressHandler = $addressHandler; $this->fedShareManager = $fedShareManager; $this->logger = $logger; + $this->config = $config; } /** @@ -177,6 +185,24 @@ public function createShare( $resourceType, $protocol ) { + // Allow other apps to overwrite the behaviour of this endpoint + $controllerClass = $this->config->getSystemValue('sharing.ocmController'); + if (($controllerClass !== '') && ($controllerClass !== null)) { + $controller = \OC::$server->query($controllerClass); + return $controller->createShare( + $shareWith, + $name, + $description, + $providerId, + $owner, + $ownerDisplayName, + $sender, + $senderDisplayName, + $shareType, + $resourceType, + $protocol + ); + } try { $this->ocmMiddleware->assertIncomingSharingEnabled(); $this->ocmMiddleware->assertNotNull( @@ -284,6 +310,17 @@ public function processNotification( $providerId, $notification ) { + // Allow other apps to overwrite the behaviour of this endpoint + $controllerClass = $this->config->getSystemValue('sharing.ocmController'); + if (($controllerClass !== '') && ($controllerClass !== null)) { + $controller = \OC::$server->query($controllerClass); + return $controller->processNotification( + $notificationType, + $resourceType, + $providerId, + $notification + ); + } try { if (!\is_array($notification)) { throw new BadRequestException( diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php index ba144106c755..a67094929978 100644 --- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php +++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php @@ -110,6 +110,11 @@ public function createShare() { 'sharedByFederatedId', null ); + + if (\strlen($token) > 128) { + throw new BadRequestException('Token too long'); + } + $ownerFederatedId = $this->request->getParam('ownerFederatedId', null); $this->ocmMiddleware->assertNotNull( [ diff --git a/apps/federatedfilesharing/lib/FedShareManager.php b/apps/federatedfilesharing/lib/FedShareManager.php index a60d323194f2..0e99a11fbb59 100644 --- a/apps/federatedfilesharing/lib/FedShareManager.php +++ b/apps/federatedfilesharing/lib/FedShareManager.php @@ -69,11 +69,6 @@ class FedShareManager { */ private $addressHandler; - /** - * @var Permissions - */ - private $permissions; - /** * @var EventDispatcherInterface */ @@ -88,7 +83,6 @@ class FedShareManager { * @param ActivityManager $activityManager * @param NotificationManager $notificationManager * @param AddressHandler $addressHandler - * @param Permissions $permissions * @param EventDispatcherInterface $eventDispatcher */ public function __construct( @@ -98,7 +92,6 @@ public function __construct( ActivityManager $activityManager, NotificationManager $notificationManager, AddressHandler $addressHandler, - Permissions $permissions, EventDispatcherInterface $eventDispatcher ) { $this->federatedShareProvider = $federatedShareProvider; @@ -107,7 +100,6 @@ public function __construct( $this->activityManager = $activityManager; $this->notificationManager = $notificationManager; $this->addressHandler = $addressHandler; - $this->permissions = $permissions; $this->eventDispatcher = $eventDispatcher; } @@ -316,7 +308,7 @@ public function undoReshare(IShare $share) { * @return void */ public function updateOcmPermissions(IShare $share, $ocmPermissions) { - $permissions = $this->permissions->toOcPermissions($ocmPermissions); + $permissions = Permissions::toOcPermissions($ocmPermissions); $this->updatePermissions($share, $permissions); } @@ -328,8 +320,9 @@ public function updateOcmPermissions(IShare $share, $ocmPermissions) { * * @return void */ - public function updatePermissions(IShare $share, $permissions) { - if ($share->getPermissions() !== $permissions) { + public function updatePermissions(IShare $share, int $permissions): void { + # permissions can only be reduced but not upgraded + if (!Permissions::isNewPermissionHigher($share->getPermissions(), $permissions)) { $share->setPermissions($permissions); $this->federatedShareProvider->update($share); } diff --git a/apps/federatedfilesharing/lib/Ocm/NotificationManager.php b/apps/federatedfilesharing/lib/Ocm/NotificationManager.php index 9f810798ffbd..5577c9eb09aa 100644 --- a/apps/federatedfilesharing/lib/Ocm/NotificationManager.php +++ b/apps/federatedfilesharing/lib/Ocm/NotificationManager.php @@ -29,20 +29,6 @@ * @package OCA\FederatedFileSharing\Ocm */ class NotificationManager { - /** - * @var Permissions - */ - protected $permissions; - - /** - * NotificationManager constructor. - * - * @param Permissions $permissions - */ - public function __construct(Permissions $permissions) { - $this->permissions = $permissions; - } - /** * @param string $type * @@ -87,7 +73,7 @@ public function convertToOcmFileNotification($remoteId, $token, $action, $data = $notification->addNotificationData('message', $messages[$action]); if ($action === 'permissions') { - $ocmPermissions = $this->permissions->toOcmPermissions($data['permissions']); + $ocmPermissions = Permissions::toOcmPermissions($data['permissions']); $notification->addNotificationData('permission', $ocmPermissions); } diff --git a/apps/federatedfilesharing/lib/Ocm/Permissions.php b/apps/federatedfilesharing/lib/Ocm/Permissions.php index f75118d79c27..33643931c737 100644 --- a/apps/federatedfilesharing/lib/Ocm/Permissions.php +++ b/apps/federatedfilesharing/lib/Ocm/Permissions.php @@ -40,11 +40,11 @@ class Permissions { * * @return array */ - public function toOcmPermissions($ocPermissions) { + public static function toOcmPermissions(int $ocPermissions): array { $ocPermissions = (int) $ocPermissions; $ocmPermissions = []; if ($ocPermissions & Constants::PERMISSION_READ) { - $ocmPermissions[] = self::OCM_PERMISSION_READ . ''; + $ocmPermissions[] = self::OCM_PERMISSION_READ; } if (($ocPermissions & Constants::PERMISSION_CREATE) || ($ocPermissions & Constants::PERMISSION_UPDATE) @@ -62,7 +62,7 @@ public function toOcmPermissions($ocPermissions) { * * @return int */ - public function toOcPermissions($ocmPermissions) { + public static function toOcPermissions(array $ocmPermissions): int { $permissionMap = [ self::OCM_PERMISSION_READ => Constants::PERMISSION_READ, self::OCM_PERMISSION_WRITE => Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE, @@ -77,4 +77,8 @@ public function toOcPermissions($ocmPermissions) { return $ocPermissions; } + + public static function isNewPermissionHigher(int $existingPermission, int $newPermission): bool { + return ($existingPermission | $newPermission) !== $existingPermission; + } } diff --git a/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php b/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php index 2a953a2ddf1b..6532d544a783 100644 --- a/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php +++ b/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php @@ -33,6 +33,7 @@ use OCA\FederatedFileSharing\Tests\TestCase; use OCP\App\IAppManager; use OCP\AppFramework\Http; +use OCP\IConfig; use OCP\ILogger; use OCP\IRequest; use OCP\IURLGenerator; @@ -86,6 +87,11 @@ class OcmControllerTest extends TestCase { */ private $logger; + /** + * @var IConfig | \PHPUnit\Framework\MockObject\MockObject + */ + private $config; + /** * @var OcmController */ @@ -107,6 +113,7 @@ protected function setUp(): void { $this->addressHandler = $this->createMock(AddressHandler::class); $this->fedShareManager = $this->createMock(FedShareManager::class); $this->logger = $this->createMock(ILogger::class); + $this->config = $this->createMock(IConfig::class); $this->ocmController = new OcmController( 'federatedfilesharing', @@ -116,7 +123,8 @@ protected function setUp(): void { $this->userManager, $this->addressHandler, $this->fedShareManager, - $this->logger + $this->logger, + $this->config ); } diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php index 932a5c531631..fe9df1709d13 100644 --- a/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php +++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php @@ -456,6 +456,7 @@ public function testUpdatePermissions(): void { $this->ocmMiddleware->expects($this->once()) ->method('getValidShare') ->willReturn($share); + $this->ocmMiddleware->method('normalizePermissions')->willReturnArgument(0); $this->fedShareManager->expects($this->once()) ->method('isFederatedReShare') ->willReturn(true); diff --git a/apps/federatedfilesharing/tests/FedShareManagerTest.php b/apps/federatedfilesharing/tests/FedShareManagerTest.php index a46c8cc05847..8bd482900baf 100644 --- a/apps/federatedfilesharing/tests/FedShareManagerTest.php +++ b/apps/federatedfilesharing/tests/FedShareManagerTest.php @@ -64,9 +64,6 @@ class FedShareManagerTest extends TestCase { /** @var AddressHandler | \PHPUnit\Framework\MockObject\MockObject */ private $addressHandler; - /** @var Permissions | \PHPUnit\Framework\MockObject\MockObject */ - private $permissions; - /** @var EventDispatcherInterface | \PHPUnit\Framework\MockObject\MockObject */ private $eventDispatcher; @@ -87,8 +84,6 @@ protected function setUp(): void { $this->addressHandler = $this->getMockBuilder(AddressHandler::class) ->disableOriginalConstructor()->getMock(); - $this->permissions = $this->createMock(Permissions::class); - $this->eventDispatcher = $this->getMockBuilder(EventDispatcherInterface::class) ->getMock(); @@ -101,7 +96,6 @@ protected function setUp(): void { $this->activityManager, $this->notificationManager, $this->addressHandler, - $this->permissions, $this->eventDispatcher ] ) @@ -298,4 +292,31 @@ public function testIsFederatedReShare() { $isFederatedShared ); } + + public function providesPermissions(): \Generator { + $read = Permissions::toOcPermissions(['read']); + $readWrite = Permissions::toOcPermissions(['read', 'write']); + $readShare = Permissions::toOcPermissions(['read', 'share']); + $readWriteShare = Permissions::toOcPermissions(['read', 'write', 'share']); + + yield 'read -> write is not allowed' => [$read, $readWrite, false]; + yield 'write -> read is allowed' => [$readWrite, $read, true]; + yield 'read+share -> write is not allowed' => [$readShare, $readWrite, false]; + yield 'write+share -> read is allowed' => [$readWriteShare, $read, true]; + } + + /** + * @dataProvider providesPermissions + */ + public function testGrantingHigherPermission(int $currentPermissions, int $newPermissions, bool $allowed): void { + $share = $this->getMockBuilder(IShare::class) + ->disableOriginalConstructor()->getMock(); + $share->method('getPermissions')->willReturn($currentPermissions); + + $this->federatedShareProvider->expects($allowed ? $this->once() : $this->never()) + ->method('update') + ->with($share); + + $this->fedShareManager->updatePermissions($share, $newPermissions); + } } diff --git a/apps/federatedfilesharing/tests/NotificationsTest.php b/apps/federatedfilesharing/tests/NotificationsTest.php index 416b35f1093c..8e129b450bdf 100644 --- a/apps/federatedfilesharing/tests/NotificationsTest.php +++ b/apps/federatedfilesharing/tests/NotificationsTest.php @@ -65,9 +65,7 @@ public function setUp(): void { $this->config = $this->createMock(IConfig::class); $this->discoveryManager = $this->getMockBuilder(DiscoveryManager::class) ->disableOriginalConstructor()->getMock(); - $this->notificationManager = new NotificationManager( - $this->createMock(Permissions::class) - ); + $this->notificationManager = new NotificationManager(); $this->httpClientService = $this->createMock(IClientService::class); $this->addressHandler = $this->getMockBuilder(AddressHandler::class) ->disableOriginalConstructor()->getMock(); @@ -341,14 +339,14 @@ public function dataTryHttpPostToShareEndpointInException() { public function testDeclineEvent() { $dispatcher = \OC::$server->getEventDispatcher(); $event = $dispatcher->dispatch( - DeclineShare::class, new DeclineShare( [ 'remote_id' => '4354353', 'remote' => 'http://localhost', 'share_token' => 'ohno' ] - ) + ), + DeclineShare::class ); $this->assertInstanceOf(DeclineShare::class, $event); } diff --git a/apps/federatedfilesharing/tests/Ocm/PermissionsTest.php b/apps/federatedfilesharing/tests/Ocm/PermissionsTest.php index 107b2500c529..24934370e7c6 100644 --- a/apps/federatedfilesharing/tests/Ocm/PermissionsTest.php +++ b/apps/federatedfilesharing/tests/Ocm/PermissionsTest.php @@ -32,24 +32,14 @@ * @group DB */ class PermissionsTest extends TestCase { - /** - * @var Permissions - */ - private $permissions; - - protected function setUp(): void { - parent::setUp(); - $this->permissions = new Permissions(); - } - /** * @dataProvider dataTestToOcPermissions * * @param string[] $ocmPermissions * @param int $expectedOcPermissions */ - public function testToOcPermissions($ocmPermissions, $expectedOcPermissions) { - $ocPermissions = $this->permissions->toOcPermissions($ocmPermissions); + public function testToOcPermissions(array $ocmPermissions, int $expectedOcPermissions): void { + $ocPermissions = Permissions::toOcPermissions($ocmPermissions); $this->assertEquals($expectedOcPermissions, $ocPermissions); } @@ -91,8 +81,8 @@ public function dataTestToOcPermissions() { * @param int $ocPermissions * @param string[] $expectedOcmPermissions */ - public function testToOcmPermissions($ocPermissions, $expectedOcmPermissions) { - $ocmPermissions = $this->permissions->toOcmPermissions($ocPermissions); + public function testToOcmPermissions(int $ocPermissions, array $expectedOcmPermissions): void { + $ocmPermissions = Permissions::toOcmPermissions($ocPermissions); $this->assertEquals($expectedOcmPermissions, $ocmPermissions); } diff --git a/apps/federation/appinfo/info.xml b/apps/federation/appinfo/info.xml index 5dbdc03a26d3..6116f7c607d4 100644 --- a/apps/federation/appinfo/info.xml +++ b/apps/federation/appinfo/info.xml @@ -21,6 +21,9 @@ OCA\Federation\Command\SyncFederationAddressBooks + OCA\Federation\Command\TrustedServerAdd + OCA\Federation\Command\TrustedServerList + OCA\Federation\Command\TrustedServerRemove OCA\Federation\Panels\Admin diff --git a/apps/federation/lib/BackgroundJob/GetSharedSecret.php b/apps/federation/lib/BackgroundJob/GetSharedSecret.php index 9005dadf88a1..e8b8a9b40dea 100644 --- a/apps/federation/lib/BackgroundJob/GetSharedSecret.php +++ b/apps/federation/lib/BackgroundJob/GetSharedSecret.php @@ -64,7 +64,7 @@ class GetSharedSecret extends Job { /** @var bool */ protected $retainJob = false; - private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json'; + private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret'; /** * RequestSharedSecret constructor. @@ -143,11 +143,11 @@ protected function run($argument) { $result = $this->httpClient->get( $target . $this->endPoint, [ - 'query' => - [ - 'url' => $source, - 'token' => $token - ], + 'query' => [ + 'url' => $source, + 'token' => $token, + 'format' => 'json' + ], 'timeout' => 3, 'connect_timeout' => 3, ] diff --git a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php index 221225ecab3d..9682d6085de7 100644 --- a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php +++ b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php @@ -58,7 +58,7 @@ class RequestSharedSecret extends Job { /** @var TrustedServers */ private $trustedServers; - private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json'; + private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret'; /** @var ILogger */ private $logger; @@ -143,6 +143,7 @@ protected function run($argument) { 'form_params' => [ 'url' => $source, 'token' => $token, + 'format' => 'json' ], 'timeout' => 3, 'connect_timeout' => 3, diff --git a/apps/federation/lib/Command/SyncFederationAddressBooks.php b/apps/federation/lib/Command/SyncFederationAddressBooks.php index 36c7db931954..138f2d2ee682 100644 --- a/apps/federation/lib/Command/SyncFederationAddressBooks.php +++ b/apps/federation/lib/Command/SyncFederationAddressBooks.php @@ -51,7 +51,7 @@ protected function configure() { * @param OutputInterface $output * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $progress = new ProgressBar($output); $progress->start(); $this->syncService->syncThemAll(function ($url, $ex) use ($progress, $output) { diff --git a/apps/federation/lib/Command/TrustedServerAdd.php b/apps/federation/lib/Command/TrustedServerAdd.php new file mode 100644 index 000000000000..56ed63b085c9 --- /dev/null +++ b/apps/federation/lib/Command/TrustedServerAdd.php @@ -0,0 +1,75 @@ + + * + */ +namespace OCA\Federation\Command; + +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class TrustedServerAdd extends Command { + public const ERROR_ALREADY_TRUSTED = 1; + public const ERROR_NO_OWNCLOUD_FOUND = 2; + + /** @var TrustedServers */ + private $trustedServers; + + /** + * @param TrustedServers $trustedServers + */ + public function __construct(TrustedServers $trustedServers) { + parent::__construct(); + $this->trustedServers = $trustedServers; + } + + protected function configure() { + $this + ->setName('federation:trusted-servers:add') + ->setDescription('Adds a new trusted server') + ->addArgument( + 'url', + InputArgument::REQUIRED, + 'The url pointing to the server, such as https://myserver:8888/server/owncloud' + ); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int { + $url = $input->getArgument('url'); + if ($this->trustedServers->isTrustedServer($url)) { + $output->writeln('The server is already in the list of trusted servers.'); + return self::ERROR_ALREADY_TRUSTED; + } + + if (!$this->trustedServers->isOwnCloudServer($url)) { + $output->writeln('No ownCloud server found'); + return self::ERROR_NO_OWNCLOUD_FOUND; + } + + $id = $this->trustedServers->addServer($url); + $output->writeln("Server added with id {$id}"); + + return 0; + } +} diff --git a/apps/federation/lib/Command/TrustedServerList.php b/apps/federation/lib/Command/TrustedServerList.php new file mode 100644 index 000000000000..232a6261dbd9 --- /dev/null +++ b/apps/federation/lib/Command/TrustedServerList.php @@ -0,0 +1,69 @@ + + * + */ +namespace OCA\Federation\Command; + +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class TrustedServerList extends Command { + /** @var TrustedServers */ + private $trustedServers; + + /** + * @param TrustedServers $trustedServers + */ + public function __construct(TrustedServers $trustedServers) { + parent::__construct(); + $this->trustedServers = $trustedServers; + } + + protected function configure() { + $this + ->setName('federation:trusted-servers:list') + ->setDescription('List the trusted servers'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int { + $servers = $this->trustedServers->getServers(); + + $statusMap = [ + TrustedServers::STATUS_OK => 'OK', + TrustedServers::STATUS_PENDING => 'Pending', + TrustedServers::STATUS_FAILURE => 'Failure', + TrustedServers::STATUS_ACCESS_REVOKED => 'Revoked', + ]; + + $table = new Table($output); + $table->setHeaders(['id', 'server', 'status']); + foreach ($servers as $server) { + $table->addRow([$server['id'], $server['url'], $statusMap[$server['status']] ?? 'Unknown']); + } + $table->render(); + return 0; + } +} diff --git a/apps/federation/lib/Command/TrustedServerRemove.php b/apps/federation/lib/Command/TrustedServerRemove.php new file mode 100644 index 000000000000..e122f2bda719 --- /dev/null +++ b/apps/federation/lib/Command/TrustedServerRemove.php @@ -0,0 +1,66 @@ + + * + */ +namespace OCA\Federation\Command; + +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class TrustedServerRemove extends Command { + /** @var TrustedServers */ + private $trustedServers; + + /** + * @param TrustedServers $trustedServers + */ + public function __construct(TrustedServers $trustedServers) { + parent::__construct(); + $this->trustedServers = $trustedServers; + } + + protected function configure() { + $this + ->setName('federation:trusted-servers:remove') + ->setDescription('Remove a trusted server') + ->addArgument( + 'id', + InputArgument::REQUIRED, + 'The id of the server. Check with occ federation:trusted-servers:list' + ); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int { + $id = (int)$input->getArgument('id'); + try { + $this->trustedServers->removeServer($id); + $output->writeln("Removed server with id {$id}"); + } catch (\Exception $e) { + $output->writeln("{$e->getMessage()}"); + return 1; + } + return 0; + } +} diff --git a/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php b/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php index 3d857316500d..57be9dd19ba8 100644 --- a/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php +++ b/apps/federation/tests/BackgroundJob/GetSharedSecretTest.php @@ -151,12 +151,13 @@ public function testRun($statusCode) { ->willReturn($source); $this->httpClient->expects($this->once())->method('get') ->with( - $target . '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json', + $target . '/ocs/v2.php/apps/federation/api/v1/shared-secret', [ 'query' => [ 'url' => $source, - 'token' => $token + 'token' => $token, + 'format' => 'json' ], 'timeout' => 3, 'connect_timeout' => 3, diff --git a/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php b/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php index e4d577bc1387..351842a2a677 100644 --- a/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php +++ b/apps/federation/tests/BackgroundJob/RequestSharedSecretTest.php @@ -137,12 +137,13 @@ public function testRun($statusCode) { ->willReturn($source); $this->httpClient->expects($this->once())->method('post') ->with( - $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json', + $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret', [ 'form_params' => [ 'url' => $source, - 'token' => $token + 'token' => $token, + 'format' => 'json' ], 'timeout' => 3, 'connect_timeout' => 3, diff --git a/apps/federation/tests/Command/TrustedServerAddTest.php b/apps/federation/tests/Command/TrustedServerAddTest.php new file mode 100644 index 000000000000..e656b99e09b4 --- /dev/null +++ b/apps/federation/tests/Command/TrustedServerAddTest.php @@ -0,0 +1,71 @@ + + * + */ + +namespace OCA\Federation\Tests\Command; + +use OCA\Federation\Command\TrustedServerAdd; +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +/** + * @group DB + */ +class TrustedServerAddTest extends TestCase { + /** @var TrustedServers */ + private $trustedServers; + + /** @var TrustedServerAdd */ + private $command; + + protected function setUp(): void { + $this->trustedServers = $this->createMock(TrustedServers::class); + + $this->command = new CommandTester(new TrustedServerAdd($this->trustedServers)); + } + + public function testExecuteAlreadyTrusted() { + $this->trustedServers->method('isTrustedServer')->willReturn(true); + + $this->command->execute(['url' => 'https://some.server/path/owncloud']); + $this->assertSame(TrustedServerAdd::ERROR_ALREADY_TRUSTED, $this->command->getStatusCode()); + } + + public function testExecuteNotFound() { + $this->trustedServers->method('isTrustedServer')->willReturn(false); + $this->trustedServers->method('isOwnCloudServer')->willReturn(false); + + $this->command->execute(['url' => 'https://some.server/path/owncloud']); + $this->assertSame(TrustedServerAdd::ERROR_NO_OWNCLOUD_FOUND, $this->command->getStatusCode()); + } + + public function testExecute() { + $server = 'https://some.server/path/owncloud'; + + $this->trustedServers->method('isTrustedServer')->willReturn(false); + $this->trustedServers->method('isOwnCloudServer')->willReturn(true); + $this->trustedServers->expects($this->once()) + ->method('addServer') + ->with($server) + ->willReturn(33); + + $this->command->execute(['url' => $server]); + $this->assertSame(0, $this->command->getStatusCode()); + } +} diff --git a/apps/federation/tests/Command/TrustedServerListTest.php b/apps/federation/tests/Command/TrustedServerListTest.php new file mode 100644 index 000000000000..231857958add --- /dev/null +++ b/apps/federation/tests/Command/TrustedServerListTest.php @@ -0,0 +1,56 @@ + + * + */ + +namespace OCA\Federation\Tests\Command; + +use OCA\Federation\Command\TrustedServerList; +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +/** + * @group DB + */ +class TrustedServerListTest extends TestCase { + /** @var TrustedServers */ + private $trustedServers; + + /** @var TrustedServerList */ + private $command; + + protected function setUp(): void { + $this->trustedServers = $this->createMock(TrustedServers::class); + + $this->command = new CommandTester(new TrustedServerList($this->trustedServers)); + } + + public function testExecute() { + $this->trustedServers->method('getServers') + ->willReturn([ + ['id' => 45, 'url' => 'https://my.server1', 'status' => 2], + ['id' => 55, 'url' => 'https://my.server22', 'status' => 1], + ]); + + $this->command->execute([]); + $output = $this->command->getDisplay(); + // expect the information of each server in the same row, no special formatting + $this->assertMatchesRegularExpression('/^.*45.*my\.server1.*Pending.*$/m', $output); + $this->assertMatchesRegularExpression('/^.*55.*my\.server22.*OK.*$/m', $output); + } +} diff --git a/apps/federation/tests/Command/TrustedServerRemoveTest.php b/apps/federation/tests/Command/TrustedServerRemoveTest.php new file mode 100644 index 000000000000..7a8a9898b7be --- /dev/null +++ b/apps/federation/tests/Command/TrustedServerRemoveTest.php @@ -0,0 +1,51 @@ + + * + */ + +namespace OCA\Federation\Tests\Command; + +use OCA\Federation\Command\TrustedServerRemove; +use OCA\Federation\TrustedServers; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +/** + * @group DB + */ +class TrustedServerRemoveTest extends TestCase { + /** @var TrustedServers */ + private $trustedServers; + + /** @var TrustedServerRemove */ + private $command; + + protected function setUp(): void { + $this->trustedServers = $this->createMock(TrustedServers::class); + + $this->command = new CommandTester(new TrustedServerRemove($this->trustedServers)); + } + + public function testExecute() { + $this->trustedServers->expects($this->once()) + ->method('removeServer') + ->with(12); + + $this->command->execute(['id' => 12]); + $this->assertSame(0, $this->command->getStatusCode()); + } +} diff --git a/apps/federation/tests/TrustedServersTest.php b/apps/federation/tests/TrustedServersTest.php index 4b7dd1fc3019..735b380124c1 100644 --- a/apps/federation/tests/TrustedServersTest.php +++ b/apps/federation/tests/TrustedServersTest.php @@ -74,6 +74,12 @@ public function setUp(): void { ->disableOriginalConstructor()->getMock(); $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface') ->disableOriginalConstructor()->getMock(); + $this->dispatcher->expects($this->any())->method('dispatch') + ->will( + $this->returnCallback(function ($object) { + return $object; + }) + ); $this->httpClientService = $this->createMock('OCP\Http\Client\IClientService'); $this->httpClient = $this->createMock('OCP\Http\Client\IClient'); $this->response = $this->createMock('OCP\Http\Client\IResponse'); diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml index ddda2e0ff843..36959983683e 100644 --- a/apps/files/appinfo/info.xml +++ b/apps/files/appinfo/info.xml @@ -29,6 +29,7 @@ OCA\Files\Command\CheckCache OCA\Files\Command\Scan OCA\Files\Command\DeleteOrphanedFiles + OCA\Files\Command\RemoveStorageCache OCA\Files\Command\TransferOwnership OCA\Files\Command\TroubleshootTransferOwnership OCA\Files\Command\VerifyChecksums diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js index b59f761f81ea..2728de27e078 100644 --- a/apps/files/l10n/en_GB.js +++ b/apps/files/l10n/en_GB.js @@ -32,6 +32,7 @@ OC.L10N.register( "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -40,7 +41,12 @@ OC.L10N.register( "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -68,7 +74,10 @@ OC.L10N.register( "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -79,6 +88,7 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -100,18 +110,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json index ddb33a3c76f7..eafd36e0f6dd 100644 --- a/apps/files/l10n/en_GB.json +++ b/apps/files/l10n/en_GB.json @@ -30,6 +30,7 @@ "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -38,7 +39,12 @@ "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -66,7 +72,10 @@ "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -77,6 +86,7 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -98,18 +108,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/apps/files/l10n/es_AR.js b/apps/files/l10n/es_AR.js index 8816d4343a4b..00bb6516ea80 100644 --- a/apps/files/l10n/es_AR.js +++ b/apps/files/l10n/es_AR.js @@ -57,6 +57,7 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/apps/files/l10n/es_AR.json b/apps/files/l10n/es_AR.json index 32234ffe7b30..bf2225b0796f 100644 --- a/apps/files/l10n/es_AR.json +++ b/apps/files/l10n/es_AR.json @@ -55,6 +55,7 @@ "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/apps/files/l10n/he.js b/apps/files/l10n/he.js index 7fa7a9daf71f..d67f5270639d 100644 --- a/apps/files/l10n/he.js +++ b/apps/files/l10n/he.js @@ -41,6 +41,10 @@ OC.L10N.register( "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -105,18 +109,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/apps/files/l10n/he.json b/apps/files/l10n/he.json index a86a58598d91..8c8d331e7135 100644 --- a/apps/files/l10n/he.json +++ b/apps/files/l10n/he.json @@ -39,6 +39,10 @@ "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -103,18 +107,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/apps/files/l10n/zh-Hans.js b/apps/files/l10n/zh-Hans.js new file mode 100644 index 000000000000..14da401f67fb --- /dev/null +++ b/apps/files/l10n/zh-Hans.js @@ -0,0 +1,6 @@ +OC.L10N.register( + "files", + { + "Close" : "关闭" +}, +"nplurals=1; plural=0;"); diff --git a/apps/files/l10n/zh-Hans.json b/apps/files/l10n/zh-Hans.json new file mode 100644 index 000000000000..2b2dddd2ce0b --- /dev/null +++ b/apps/files/l10n/zh-Hans.json @@ -0,0 +1,4 @@ +{ "translations": { + "Close" : "关闭" +},"pluralForm" :"nplurals=1; plural=0;" +} \ No newline at end of file diff --git a/apps/files/lib/Command/CheckCache.php b/apps/files/lib/Command/CheckCache.php index dd6ccb40ebfb..e744407419cc 100644 --- a/apps/files/lib/Command/CheckCache.php +++ b/apps/files/lib/Command/CheckCache.php @@ -64,7 +64,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); $userFolder = $this->rootFolder->getUserFolder($uid); // might throw a NoUserException diff --git a/apps/files/lib/Command/DeleteOrphanedFiles.php b/apps/files/lib/Command/DeleteOrphanedFiles.php index 0faadd27a502..39e784486606 100644 --- a/apps/files/lib/Command/DeleteOrphanedFiles.php +++ b/apps/files/lib/Command/DeleteOrphanedFiles.php @@ -49,7 +49,7 @@ protected function configure() { ->setDescription('Deletes orphaned file cache entries.'); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $deletedEntries = 0; $query = $this->connection->getQueryBuilder(); diff --git a/apps/files/lib/Command/RemoveStorageCache.php b/apps/files/lib/Command/RemoveStorageCache.php new file mode 100644 index 000000000000..174eea439d6d --- /dev/null +++ b/apps/files/lib/Command/RemoveStorageCache.php @@ -0,0 +1,193 @@ + + * + */ + +namespace OCA\Files\Command; + +use OCP\IDBConnection; +use OCP\DB\QueryBuilder\IQueryBuilder; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Remove the target storage from the oc_storages tables, and remove the + * related files from the oc_filecache table. + */ +class RemoveStorageCache extends Command { + private const DEFAULT_CHUNK_SIZE = 1000; + + /** @var IDBConnection */ + private $connection; + + public function __construct(IDBConnection $connection) { + parent::__construct(); + $this->connection = $connection; + } + + protected function configure() { + $this + ->setName('files:remove-storage') + ->setDescription('Remove a storage from the storages table and related files from the filecache table.') + ->addArgument( + 'storage-id', + InputArgument::OPTIONAL, + 'The numeric ID of the storage' + )->addOption( + 'chunk-size', + null, + InputOption::VALUE_REQUIRED, + 'The number of rows that will be deleted at the same time.', + self::DEFAULT_CHUNK_SIZE + )->addOption( + 'show-candidates', + null, + InputOption::VALUE_NONE, + 'Show possible candidates for obsolete storages. This query can take a while.' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($input->getOption('show-candidates')) { + $this->showCandidates($output); + return 0; + } + + $storage_id = \intval($input->getArgument('storage-id')); + if ($storage_id <= 0) { + $output->writeln('A valid storage ID is required'); + return 1; + } + + $chunk_size = \intval($input->getOption('chunk-size')); + if ($chunk_size <= 0) { + $chunk_size = self::DEFAULT_CHUNK_SIZE; + } + + $this->removeStorage($storage_id); + $nfiles = $this->countCachedFiles($storage_id); + + if ($nfiles <= 0) { + $output->writeln('No files found for the target storage'); + return 0; + } + + $bar = new ProgressBar($output); + $bar->start($nfiles); + while (($maxId = $this->getMaxFileidInRange($storage_id, $chunk_size)) > 0) { + $ndeleted = $this->removeCachedFiles($storage_id, $maxId); + $bar->advance($ndeleted); + } + $bar->finish(); + return 0; + } + + /** + * Remove the storage_id from the oc_storages table. + * @return int the number of rows deleted from the table + */ + private function removeStorage(int $storage_id) { + $qb = $this->connection->getQueryBuilder(); + $result = $qb->delete('storages') + ->where($qb->expr()->eq('numeric_id', $qb->createNamedParameter($storage_id, IQueryBuilder::PARAM_INT))) + ->execute(); + return (int)$result; + } + + /** + * Count the number of rows for the storage_id + * @return int the number of rows for the target storage + */ + private function countCachedFiles(int $storage_id) { + $qb = $this->connection->getQueryBuilder(); + $result = $qb->select($qb->createFunction('count(*) as `count`')) + ->from('filecache') + ->where($qb->expr()->eq('storage', $qb->createNamedParameter($storage_id, IQueryBuilder::PARAM_INT))) + ->execute(); + + $row = $result->fetch(); + $result->closeCursor(); + + return (int)$row['count']; + } + + /** + * Get the maximum fileid found in the first results of the storage_id + * If there is no file in the storage, 0 will be returned. + * The rows can be deleted by filtering by the storage_id and with + * the fileid lower or equal to the returned fileid + * @return int the maximum fileid found + */ + private function getMaxFileidInRange(int $storage_id, $maxResults) { + $qb = $this->connection->getQueryBuilder(); + $result = $qb->select('fileid') + ->from('filecache') + ->where($qb->expr()->eq('storage', $qb->createNamedParameter($storage_id, IQueryBuilder::PARAM_INT))) + ->orderBy('fileid', 'ASC') + ->setMaxResults($maxResults) + ->execute(); + + $maxId = 0; + while (($row = $result->fetch()) !== false) { + if ($maxId < (int)$row['fileid']) { + $maxId = (int)$row['fileid']; + } + } + + $result->closeCursor(); + return $maxId; + } + + /** + * Remove the files in the oc_filecache table with the target storage_id and + * with fileid lower or equal to the $max + * @return int the number of removed rows + */ + private function removeCachedFiles(int $storage_id, int $max) { + $qb = $this->connection->getQueryBuilder(); + $result = $qb->delete('filecache') + ->where($qb->expr()->eq('storage', $qb->createNamedParameter($storage_id, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->lte('fileid', $qb->createNamedParameter($max))) + ->execute(); + + return (int)$result; + } + + private function showCandidates(OutputInterface $output) { + $qb = $this->connection->getQueryBuilder(); + $result = $qb->select(['f.storage', 's.id', $qb->createFunction('count(f.`storage`) as `count`')]) + ->from('storages', 's') + ->leftJoin('s', 'mounts', 'm', $qb->expr()->eq('s.numeric_id', 'm.storage_id')) + ->rightJoin('s', 'filecache', 'f', $qb->expr()->eq('s.numeric_id', 'f.storage')) + ->where($qb->expr()->isNull('m.mount_point')) + ->groupBy('f.storage', 's.id') + ->execute(); + + $table = new Table($output); + $table->setHeaders(['storage-id', 'name', 'file_count']); + while (($row = $result->fetch()) !== false) { + $table->addRow([$row['storage'], $row['id'] ?? 'NULL', $row['count']]); + } + $table->render(); + $result->closeCursor(); + } +} diff --git a/apps/files/lib/Command/Scan.php b/apps/files/lib/Command/Scan.php index a46f030a4630..e35e05ffbf8a 100644 --- a/apps/files/lib/Command/Scan.php +++ b/apps/files/lib/Command/Scan.php @@ -221,7 +221,7 @@ protected function scanFiles($user, $path, $verbose, OutputInterface $output, $b $scanner->listen('\OC\Files\Utils\Scanner', 'StorageNotAvailable', function (StorageNotAvailableException $e) use ($output) { $output->writeln("Error while scanning, storage not available (" . $e->getMessage() . ")"); }); - # count only + # count only } else { $scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function () { $this->filesCounter += 1; @@ -279,7 +279,7 @@ protected function getAllUsersFromGroup($group) { } } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $inputPath = $input->getOption('path'); $groups = $input->getOption('groups') ? \explode(',', $input->getOption('groups')) : []; $groups = \array_unique(\array_merge($groups, $input->getOption('group'))); diff --git a/apps/files/lib/Command/TransferOwnership.php b/apps/files/lib/Command/TransferOwnership.php index c1d3d89e1e67..a9ff6c54a9ad 100644 --- a/apps/files/lib/Command/TransferOwnership.php +++ b/apps/files/lib/Command/TransferOwnership.php @@ -139,7 +139,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $sourceUserObject = $this->userManager->get($input->getArgument('source-user')); $destinationUserObject = $this->userManager->get($input->getArgument('destination-user')); if ($sourceUserObject === null) { diff --git a/apps/files/lib/Command/TroubleshootTransferOwnership.php b/apps/files/lib/Command/TroubleshootTransferOwnership.php index 72bc227578bd..94fb011f945e 100644 --- a/apps/files/lib/Command/TroubleshootTransferOwnership.php +++ b/apps/files/lib/Command/TroubleshootTransferOwnership.php @@ -80,7 +80,7 @@ protected function configure() { ); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $type = $input->getArgument('type'); $fix = $input->getOption('fix'); $scopeUid = $input->getOption('uid'); diff --git a/apps/files/lib/Command/VerifyChecksums.php b/apps/files/lib/Command/VerifyChecksums.php index 476b43926006..c2d9a7d9c161 100644 --- a/apps/files/lib/Command/VerifyChecksums.php +++ b/apps/files/lib/Command/VerifyChecksums.php @@ -88,7 +88,7 @@ protected function configure() { * @throws \OCP\Files\InvalidPathException * @throws \OCP\Files\StorageNotAvailableException */ - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $pathOption = $input->getOption('path'); $userName = $input->getOption('user'); diff --git a/apps/files/tests/Controller/ViewControllerTest.php b/apps/files/tests/Controller/ViewControllerTest.php index 48b2c84c1c9c..49ef6152c969 100644 --- a/apps/files/tests/Controller/ViewControllerTest.php +++ b/apps/files/tests/Controller/ViewControllerTest.php @@ -75,6 +75,12 @@ public function setUp(): void { $this->l10n = $this->createMock('\OCP\IL10N'); $this->config = $this->createMock('\OCP\IConfig'); $this->eventDispatcher = $this->createMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->eventDispatcher->expects($this->any())->method('dispatch') + ->will( + $this->returnCallback(function ($object) { + return $object; + }) + ); $this->userSession = $this->createMock('\OCP\IUserSession'); $this->appManager = $this->createMock('\OCP\App\IAppManager'); $this->user = $this->createMock('\OCP\IUser'); diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json index 5f350b5d59bc..91861897c106 100644 --- a/apps/files_external/3rdparty/composer.json +++ b/apps/files_external/3rdparty/composer.json @@ -11,9 +11,9 @@ } }, "replace": { - "guzzlehttp/guzzle": "^7.5", - "guzzlehttp/psr7": "^2.4", - "phpseclib/phpseclib": ">=3.0.17" + "guzzlehttp/guzzle": "^7.7", + "guzzlehttp/psr7": "^2.5", + "phpseclib/phpseclib": ">=3.0.20" }, "require": { "php": ">=7.4", diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock index 56c1979d60a9..226ddca40116 100644 --- a/apps/files_external/3rdparty/composer.lock +++ b/apps/files_external/3rdparty/composer.lock @@ -4,29 +4,29 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2c6a4ccb775cc7cf7dba22909eebff7", + "content-hash": "1c6fa935ea0a92cf47f5cbdb7140ffa7", "packages": [ { "name": "firebase/php-jwt", - "version": "v6.4.0", + "version": "v6.6.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224" + "reference": "5a9cf79b4a2eb347230384648cc7b0d68cd97faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/4dd1e007f22a927ac77da5a3fbb067b42d3bc224", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5a9cf79b4a2eb347230384648cc7b0d68cd97faa", + "reference": "5a9cf79b4a2eb347230384648cc7b0d68cd97faa", "shasum": "" }, "require": { - "php": "^7.1||^8.0" + "php": "^7.4||^8.0" }, "require-dev": { "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "psr/cache": "^1.0||^2.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" @@ -65,9 +65,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.4.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.6.0" }, - "time": "2023-02-09T21:01:23+00:00" + "time": "2023-06-13T17:11:06+00:00" }, { "name": "google/apiclient", @@ -595,21 +595,22 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "599b9d6746e56b67b187afed175dd02fb1a288fa" + "reference": "601b276d21df95e49f1802c7432b788cfaac15a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/599b9d6746e56b67b187afed175dd02fb1a288fa", - "reference": "599b9d6746e56b67b187afed175dd02fb1a288fa", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/601b276d21df95e49f1802c7432b788cfaac15a8", + "reference": "601b276d21df95e49f1802c7432b788cfaac15a8", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", - "admidio/admidio": "<4.1.9", + "admidio/admidio": "<4.2.8", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "aheinze/cockpit": "<=2.2.1", "akaunting/akaunting": "<2.1.13", - "alextselegidis/easyappointments": "<=1.4.3", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<1.5", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", @@ -617,17 +618,27 @@ "amphp/http-client": ">=4,<4.4", "anchorcms/anchor-cms": "<=0.12.7", "andreapollastri/cipi": "<=3.1.15", - "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", - "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<=1.0.1|>=2,<=2.2.4", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6|>=2.6,<2.7.10|>=3,<3.0.12|>=3.1,<3.1.3", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", "area17/twill": "<1.2.5|>=2,<2.5.3", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "automad/automad": "<1.8", "awesome-support/awesome-support": "<=6.0.7", "aws/aws-sdk-php": ">=3,<3.2.1", + "azuracast/azuracast": "<0.18.3", + "backdrop/backdrop": "<1.24.2", + "badaso/core": "<2.7", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", "barryvdh/laravel-translation-manager": "<0.6.2", - "baserproject/basercms": "<4.5.4", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<4.7.5", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bigfork/silverstripe-form-capture": ">=3,<=3.1", "billz/raspap-webgui": "<=2.6.6", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", "bmarshall511/wordpress_zero_spam": "<5.2.13", @@ -642,34 +653,39 @@ "bugsnag/bugsnag-laravel": ">=2,<2.0.2", "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.6", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|= 1.3.7|>=4.1,<4.1.4", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", "catfan/medoo": "<1.7.5", - "centreon/centreon": "<21.4.16|>=21.10,<21.10.8|>=22,<22.4.1", + "centreon/centreon": "<22.10-beta.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "cockpit-hq/cockpit": "<2.4.1", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", - "codeigniter4/framework": "<4.2.7", - "codeigniter4/shield": "= 1.0.0-beta", + "codeigniter4/framework": "<4.3.5", + "codeigniter4/shield": "<1-beta.4|= 1.0.0-beta", "codiad/codiad": "<=2.8.4", "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", - "concrete5/concrete5": "<9", + "concrete5/concrete5": "<9.2|>= 9.0.0RC1, < 9.1.3", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/core-bundle": "<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", "contao/managed-edition": "<=1.5", - "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1", + "craftcms/cms": ">= 4.0.0-RC1, < 4.4.12|>= 4.0.0-RC1, <= 4.4.5|>= 4.0.0-RC1, <= 4.4.6|<=3.8.5|>=4,<4.4.6|>= 4.0.0-RC1, < 4.4.6|>= 4.0.0-RC1, < 4.3.7|>= 4.0.0-RC1, < 4.2.1", "croogo/croogo": "<3.0.7", "cuyz/valinor": "<0.12", "czproject/git-php": "<4.0.3", "darylldoyle/safe-svg": "<1.9.10", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3-beta", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", "directmailteam/direct-mail": "<5.2.4", "doctrine/annotations": ">=1,<1.2.7", @@ -681,15 +697,16 @@ "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2", - "dompdf/dompdf": "<2.0.1", - "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "dolibarr/dolibarr": "<17.0.1|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.2|= 2.0.2", + "drupal/core": ">=7,<7.96|>=8,<9.4.14|>=9.5,<9.5.8|>=10,<10.0.8", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", "elefant/cms": "<1.3.13", "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "encore/laravel-admin": "<=1.8.19", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.15", "erusev/parsedown": "<1.7.2", @@ -701,25 +718,29 @@ "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.27", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.19", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<1.2.5.1|>=1.3,<1.3.26", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", - "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.7.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.29", + "ezsystems/ezpublish-kernel": "<6.13.8.2|>=7,<7.5.30", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", - "ezsystems/repository-forms": ">=2.3,<2.3.2.1", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<4.1.1", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", "facturascripts/facturascripts": "<=2022.8", "feehi/cms": "<=2.1.1", - "feehi/feehicms": "<=2.0.1.1", + "feehi/feehicms": "<=2.1.1", "fenom/fenom": "<=2.12.1", "filegator/filegator": "<7.8", - "firebase/php-jwt": "<2", - "flarum/core": ">=1,<=1.0.1", + "firebase/php-jwt": "<6", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.7", + "flarum/mentions": "<1.6.3", "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", "flarum/tags": "<=0.1-beta.13", "fluidtypo3/vhs": "<5.1.1", @@ -728,14 +749,16 @@ "fooman/tcpdf": "<6.2.22", "forkcms/forkcms": "<5.11.1", "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<10.1", + "francoisjacquet/rosariosis": "<11", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "froala/wysiwyg-editor": "<3.2.7", - "froxlor/froxlor": "<0.10.38", + "froxlor/froxlor": "<2.1", "fuel/core": "<1.8.1", + "funadmin/funadmin": "<=3.2", "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", "getgrav/grav": "<1.7.34", @@ -746,18 +769,24 @@ "globalpayments/php-sdk": "<2", "google/protobuf": "<3.15", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", - "gree/jose": "<=2.2", + "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<5.6.5", + "grumpydictator/firefly-iii": "<6", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", - "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "harvesthq/chosen": "<1.8.7", "helloxz/imgurl": "= 2.31|<=2.31", "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", "hjue/justwriting": "<=1", "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", "hyn/multi-tenant": ">=5.6,<5.7.2", - "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", "ibexa/post-install": "<=1.0.4", + "ibexa/user": ">=4,<4.4.3", "icecoder/icecoder": "<=8.1", "idno/known": "<=1.3.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", @@ -766,40 +795,47 @@ "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "impresscms/impresscms": "<=1.4.3", - "in2code/femanager": "<5.5.1|>=6,<6.3.1", + "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", "in2code/lux": "<17.6.1|>=18,<24.0.2", + "innologi/typo3-appointments": "<2.0.6", "intelliants/subrion": "<=4.2.1", "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", "jackalope/jackalope-doctrine-dbal": "<1.7.4", "james-heinrich/getid3": "<1.9.21", + "jasig/phpcas": "<1.3.3", "joomla/archive": "<1.1.12|>=2,<2.0.1", "joomla/filesystem": "<1.6.2|>=2,<2.0.1", "joomla/filter": "<1.4.4|>=2,<2.0.1", "joomla/input": ">=2,<2.0.2", "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", + "kimai/kimai": "<1.1", "kitodo/presentation": "<3.1.2", "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<1.4.2", "krayin/laravel-crm": "<1.2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-diactoros": "<2.18.1|>=2.24,<2.24.2|>=2.25,<2.25.2|= 2.23.0|= 2.22.0|= 2.21.0|= 2.20.0|= 2.19.0", "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", "laravel/fortify": "<1.11.1", "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", "latte/latte": "<2.10.8", - "lavalite/cms": "<=5.8", + "lavalite/cms": "<=9", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", "league/flysystem": "<1.1.4|>=2,<2.1.1", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "librenms/librenms": "<=22.8", + "librenms/librenms": "<22.10", + "liftkit/database": "<2.13.2", "limesurvey/limesurvey": "<3.27.19", "livehelperchat/livehelperchat": "<=3.91", "livewire/livewire": ">2.2.4,<2.2.6", @@ -810,21 +846,26 @@ "magento/magento1ce": "<1.9.4.3", "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "maikuolan/phpmussel": ">=1,<1.6", + "mantisbt/mantisbt": "<=2.25.5", "marcwillmann/turn": "<0.3.3", "matyhtf/framework": "<3.0.6", "mautic/core": "<4.3|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "mediawiki/matomo": "<2.4.3", "melisplatform/melis-asset-manager": "<5.0.1", "melisplatform/melis-cms": "<5.0.1", "melisplatform/melis-front": "<5.0.1", "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", - "microweber/microweber": "<=1.3.1", + "mgallegos/laravel-jqgrid": "<=1.3", + "microweber/microweber": "<=1.3.4", "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", "modx/revolution": "<= 2.8.3-pl|<2.8", "mojo42/jirafeau": "<4.4", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.0.1", + "moodle/moodle": "<4.2-rc.2|= 3.11", "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", "neoan3-apps/template": "<1.1.1", @@ -836,10 +877,11 @@ "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nilsteampassnet/teampass": "<=2.1.27.36", + "nilsteampassnet/teampass": "<3.0.9", "notrinos/notrinos-erp": "<=0.7", "noumo/easyii": "<=0.9", "nukeviet/nukeviet": "<4.5.2", + "nyholm/psr7": "<1.6.1", "nystudio107/craft-seomatic": "<3.4.12", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": "<1.1.2", @@ -850,9 +892,9 @@ "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "open-web-analytics/open-web-analytics": "<1.7.4", - "opencart/opencart": "<=3.0.3.2", + "opencart/opencart": "<=3.0.3.7", "openid/php-openid": "<2.3", - "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", + "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", "orchid/platform": ">=9,<9.4.4", "oro/commerce": ">=4.1,<5.0.6", "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", @@ -869,45 +911,56 @@ "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", "phanan/koel": "<5.1.4", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": ">=3.2,<3.2.10|>=3.3,<3.3.1", "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<5.1.3", + "phpmyadmin/phpmyadmin": "<5.2.1", "phpmyfaq/phpmyfaq": "<=3.1.7", "phpoffice/phpexcel": "<1.8", "phpoffice/phpspreadsheet": "<1.16", - "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.19", "phpservermon/phpservermon": "<=3.5.2", + "phpsysinfo/phpsysinfo": "<3.2.5", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pimcore/customer-management-framework-bundle": "<3.3.10", "pimcore/data-hub": "<1.2.4", - "pimcore/pimcore": "<=10.5.6", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<10.5.23", + "pixelfed/pixelfed": "<=0.11.4", "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<4.7.2|>= 4.0.0-BETA5, < 4.4.2", + "pocketmine/pocketmine-mp": "<4.20.5|>=4.21,<4.21.1|< 4.18.0-ALPHA2|>= 4.0.0-BETA5, < 4.4.2", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": ">=1.6.0.10,<1.7.8.7", + "prestashop/prestashop": "<8.0.4", "prestashop/productcomments": "<5.0.2", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", "prestashop/ps_linklist": "<3.1", "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", "pterodactyl/panel": "<1.7", "ptrofimov/beanstalk_console": "<1.7.14", "pusher/pusher-php-server": "<2.2.1", "pwweb/laravel-core": "<=0.3.6-beta", + "pyrocms/pyrocms": "<=3.9.1", "rainlab/debugbar-plugin": "<3.1", "rankmath/seo-by-rank-math": "<=1.0.95", - "react/http": ">=0.7,<1.7", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", "remdex/livehelperchat": "<3.99", "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", + "roots/soil": "<4.1", "rudloff/alltube": "<3.0.3", "s-cart/core": "<6.9", "s-cart/s-cart": "<6.9", @@ -916,37 +969,43 @@ "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.4.9", - "shopware/platform": "<=6.4.9", + "shopware/core": "<=6.4.20", + "shopware/platform": "<=6.4.20", "shopware/production": "<=6.3.5.2", "shopware/shopware": "<=5.7.14", "shopware/storefront": "<=6.4.8.1", "shopxo/shopxo": "<2.2.6", "showdoc/showdoc": "<2.10.4", - "silverstripe/admin": ">=1,<1.8.1", - "silverstripe/assets": ">=1,<1.10.1", - "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "silverstripe/admin": "<1.12.7", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.10.9", - "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/framework": "<4.12.5", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1", "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", - "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/subsites": ">=2,<2.6.1", "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", "silverstripe/userforms": "<3", + "silverstripe/versioned-admin": ">=1,<1.11.1", "simple-updates/phpwhois": "<=1", "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", "simplesamlphp/simplesamlphp": "<1.18.6", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.47|>=4,<4.2.1", - "snipe/snipe-it": "<6.0.11|>= 6.0.0-RC-1, <= 6.0.0-RC-5", + "smarty/smarty": "<3.1.48|>=4,<4.3.1", + "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", + "spatie/browsershot": "<3.57.4", "spipu/html2pdf": "<5.2.4", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", @@ -955,7 +1014,10 @@ "stormpath/sdk": ">=0,<9.9.99", "studio-42/elfinder": "<2.1.59", "subrion/cms": "<=4.2.1", + "sukohi/surpass": "<1", "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "sumocoders/framework-user-bundle": "<1.4", + "swag/paypal": "<5.4.4", "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", @@ -965,15 +1027,16 @@ "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", "symbiote/silverstripe-versionedfiles": "<=2.0.3", - "symfont/process": ">=0,<4", + "symfont/process": ">=0", "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", "symfony/mime": ">=4.3,<4.3.8", @@ -983,13 +1046,13 @@ "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", - "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", + "symfony/symfony": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", @@ -998,27 +1061,31 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tastyigniter/tastyigniter": "<3.3", + "tcg/voyager": "<=1.4", "tecnickcom/tcpdf": "<6.2.22", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<=5.1.7", - "thorsten/phpmyfaq": "<=3.1.7", - "tinymce/tinymce": "<5.10", + "thorsten/phpmyfaq": "<3.2-beta", + "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", + "tinymighty/wiki-seo": "<1.2.2", "titon/framework": ">=0,<9.9.99", - "topthink/framework": "<=6.0.13", - "topthink/think": "<=6.0.9", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<6.0.14", + "topthink/think": "<=6.1.1", "topthink/thinkphp": "<=3.2.3", - "tribalsystems/zenario": "<9.2.55826", + "tribalsystems/zenario": "<=9.3.57595", "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms": "<2.0.5|>=3,<3.0.3|>=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.58|>=8,<8.7.48|>=9,<9.5.37|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms-core": "<8.7.51|>=9,<9.5.40|>=10,<10.4.36|>=11,<11.5.23|>=12,<12.2", "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "typo3/html-sanitizer": ">=1,<1.0.7|>=2,<2.0.16", + "typo3/html-sanitizer": ">=1,<1.5|>=2,<2.1.1", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", @@ -1027,33 +1094,42 @@ "unisharp/laravel-filemanager": "<=2.5.1", "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", "vanilla/safecurl": "<0.9.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vova07/yii2-fileapi-widget": "<0.1.9", "vrana/adminer": "<4.8.1", "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.5.4", "wanglelecc/laracms": "<=1.0.3", "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", "webcoast/deferred-image-processing": "<1.0.2", + "webpa/webpa": "<3.1.2", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", - "wintercms/winter": "<1.0.475|>=1.1,<1.1.9", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", "woocommerce/woocommerce": "<6.6", "wp-cli/wp-cli": "<2.5", "wp-graphql/wp-graphql": "<0.3.5", "wpanel/wpanel4-cms": "<=4.3.1", - "wwbn/avideo": "<=11.6", + "wpcloud/wp-stateless": "<3.2", + "wwbn/avideo": "<=12.4", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", "yeswiki/yeswiki": "<4.1", "yetiforce/yetiforce-crm": "<=6.4", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", - "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii": "<1.1.27", "yiisoft/yii2": "<2.0.38", "yiisoft/yii2-bootstrap": "<2.0.4", "yiisoft/yii2-dev": "<2.0.43", "yiisoft/yii2-elasticsearch": "<2.0.5", - "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-gii": "<=2.2.4", "yiisoft/yii2-jui": "<2.0.4", "yiisoft/yii2-redis": "<2.0.8", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", "yoast-seo-for-typo3/yoast_seo": "<7.2.3", "yourls/yourls": "<=1.8.2", "zendesk/zendesk_api_client_php": "<2.2.11", @@ -1103,6 +1179,9 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], "support": { "issues": "https://github.com/Roave/SecurityAdvisories/issues", "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" @@ -1117,7 +1196,7 @@ "type": "tidelift" } ], - "time": "2022-10-24T19:11:20+00:00" + "time": "2023-06-14T05:04:21+00:00" } ], "aliases": [], diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json index dfdaa5dc960a..ee919f78780b 100644 --- a/apps/files_external/3rdparty/composer/installed.json +++ b/apps/files_external/3rdparty/composer/installed.json @@ -2,26 +2,26 @@ "packages": [ { "name": "firebase/php-jwt", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.6.0", + "version_normalized": "6.6.0.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224" + "reference": "5a9cf79b4a2eb347230384648cc7b0d68cd97faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/4dd1e007f22a927ac77da5a3fbb067b42d3bc224", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5a9cf79b4a2eb347230384648cc7b0d68cd97faa", + "reference": "5a9cf79b4a2eb347230384648cc7b0d68cd97faa", "shasum": "" }, "require": { - "php": "^7.1||^8.0" + "php": "^7.4||^8.0" }, "require-dev": { "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "psr/cache": "^1.0||^2.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" @@ -30,7 +30,7 @@ "ext-sodium": "Support EdDSA (Ed25519) signatures", "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" }, - "time": "2023-02-09T21:01:23+00:00", + "time": "2023-06-13T17:11:06+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -62,7 +62,7 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.4.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.6.0" }, "install-path": "../firebase/php-jwt" }, @@ -615,21 +615,22 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "599b9d6746e56b67b187afed175dd02fb1a288fa" + "reference": "601b276d21df95e49f1802c7432b788cfaac15a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/599b9d6746e56b67b187afed175dd02fb1a288fa", - "reference": "599b9d6746e56b67b187afed175dd02fb1a288fa", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/601b276d21df95e49f1802c7432b788cfaac15a8", + "reference": "601b276d21df95e49f1802c7432b788cfaac15a8", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", - "admidio/admidio": "<4.1.9", + "admidio/admidio": "<4.2.8", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "aheinze/cockpit": "<=2.2.1", "akaunting/akaunting": "<2.1.13", - "alextselegidis/easyappointments": "<=1.4.3", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<1.5", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", @@ -637,17 +638,27 @@ "amphp/http-client": ">=4,<4.4", "anchorcms/anchor-cms": "<=0.12.7", "andreapollastri/cipi": "<=3.1.15", - "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", - "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<=1.0.1|>=2,<=2.2.4", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6|>=2.6,<2.7.10|>=3,<3.0.12|>=3.1,<3.1.3", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", "area17/twill": "<1.2.5|>=2,<2.5.3", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "automad/automad": "<1.8", "awesome-support/awesome-support": "<=6.0.7", "aws/aws-sdk-php": ">=3,<3.2.1", + "azuracast/azuracast": "<0.18.3", + "backdrop/backdrop": "<1.24.2", + "badaso/core": "<2.7", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", "barryvdh/laravel-translation-manager": "<0.6.2", - "baserproject/basercms": "<4.5.4", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<4.7.5", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bigfork/silverstripe-form-capture": ">=3,<=3.1", "billz/raspap-webgui": "<=2.6.6", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", "bmarshall511/wordpress_zero_spam": "<5.2.13", @@ -662,34 +673,39 @@ "bugsnag/bugsnag-laravel": ">=2,<2.0.2", "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.6", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|= 1.3.7|>=4.1,<4.1.4", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", "catfan/medoo": "<1.7.5", - "centreon/centreon": "<21.4.16|>=21.10,<21.10.8|>=22,<22.4.1", + "centreon/centreon": "<22.10-beta.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "cockpit-hq/cockpit": "<2.4.1", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", - "codeigniter4/framework": "<4.2.7", - "codeigniter4/shield": "= 1.0.0-beta", + "codeigniter4/framework": "<4.3.5", + "codeigniter4/shield": "<1-beta.4|= 1.0.0-beta", "codiad/codiad": "<=2.8.4", "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", - "concrete5/concrete5": "<9", + "concrete5/concrete5": "<9.2|>= 9.0.0RC1, < 9.1.3", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/core-bundle": "<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", "contao/managed-edition": "<=1.5", - "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1", + "craftcms/cms": ">= 4.0.0-RC1, < 4.4.12|>= 4.0.0-RC1, <= 4.4.5|>= 4.0.0-RC1, <= 4.4.6|<=3.8.5|>=4,<4.4.6|>= 4.0.0-RC1, < 4.4.6|>= 4.0.0-RC1, < 4.3.7|>= 4.0.0-RC1, < 4.2.1", "croogo/croogo": "<3.0.7", "cuyz/valinor": "<0.12", "czproject/git-php": "<4.0.3", "darylldoyle/safe-svg": "<1.9.10", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3-beta", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", "directmailteam/direct-mail": "<5.2.4", "doctrine/annotations": ">=1,<1.2.7", @@ -701,15 +717,16 @@ "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2", - "dompdf/dompdf": "<2.0.1", - "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "dolibarr/dolibarr": "<17.0.1|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.2|= 2.0.2", + "drupal/core": ">=7,<7.96|>=8,<9.4.14|>=9.5,<9.5.8|>=10,<10.0.8", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", "elefant/cms": "<1.3.13", "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "encore/laravel-admin": "<=1.8.19", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.15", "erusev/parsedown": "<1.7.2", @@ -721,25 +738,29 @@ "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.27", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.19", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<1.2.5.1|>=1.3,<1.3.26", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", - "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.7.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.29", + "ezsystems/ezpublish-kernel": "<6.13.8.2|>=7,<7.5.30", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", - "ezsystems/repository-forms": ">=2.3,<2.3.2.1", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<4.1.1", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", "facturascripts/facturascripts": "<=2022.8", "feehi/cms": "<=2.1.1", - "feehi/feehicms": "<=2.0.1.1", + "feehi/feehicms": "<=2.1.1", "fenom/fenom": "<=2.12.1", "filegator/filegator": "<7.8", - "firebase/php-jwt": "<2", - "flarum/core": ">=1,<=1.0.1", + "firebase/php-jwt": "<6", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.7", + "flarum/mentions": "<1.6.3", "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", "flarum/tags": "<=0.1-beta.13", "fluidtypo3/vhs": "<5.1.1", @@ -748,14 +769,16 @@ "fooman/tcpdf": "<6.2.22", "forkcms/forkcms": "<5.11.1", "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<10.1", + "francoisjacquet/rosariosis": "<11", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "froala/wysiwyg-editor": "<3.2.7", - "froxlor/froxlor": "<0.10.38", + "froxlor/froxlor": "<2.1", "fuel/core": "<1.8.1", + "funadmin/funadmin": "<=3.2", "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", "getgrav/grav": "<1.7.34", @@ -766,18 +789,24 @@ "globalpayments/php-sdk": "<2", "google/protobuf": "<3.15", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", - "gree/jose": "<=2.2", + "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<5.6.5", + "grumpydictator/firefly-iii": "<6", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", - "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "harvesthq/chosen": "<1.8.7", "helloxz/imgurl": "= 2.31|<=2.31", "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", "hjue/justwriting": "<=1", "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", "hyn/multi-tenant": ">=5.6,<5.7.2", - "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", "ibexa/post-install": "<=1.0.4", + "ibexa/user": ">=4,<4.4.3", "icecoder/icecoder": "<=8.1", "idno/known": "<=1.3.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", @@ -786,40 +815,47 @@ "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "impresscms/impresscms": "<=1.4.3", - "in2code/femanager": "<5.5.1|>=6,<6.3.1", + "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", "in2code/lux": "<17.6.1|>=18,<24.0.2", + "innologi/typo3-appointments": "<2.0.6", "intelliants/subrion": "<=4.2.1", "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", "jackalope/jackalope-doctrine-dbal": "<1.7.4", "james-heinrich/getid3": "<1.9.21", + "jasig/phpcas": "<1.3.3", "joomla/archive": "<1.1.12|>=2,<2.0.1", "joomla/filesystem": "<1.6.2|>=2,<2.0.1", "joomla/filter": "<1.4.4|>=2,<2.0.1", "joomla/input": ">=2,<2.0.2", "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", + "kimai/kimai": "<1.1", "kitodo/presentation": "<3.1.2", "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<1.4.2", "krayin/laravel-crm": "<1.2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-diactoros": "<2.18.1|>=2.24,<2.24.2|>=2.25,<2.25.2|= 2.23.0|= 2.22.0|= 2.21.0|= 2.20.0|= 2.19.0", "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", "laravel/fortify": "<1.11.1", "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", "latte/latte": "<2.10.8", - "lavalite/cms": "<=5.8", + "lavalite/cms": "<=9", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", "league/flysystem": "<1.1.4|>=2,<2.1.1", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "librenms/librenms": "<=22.8", + "librenms/librenms": "<22.10", + "liftkit/database": "<2.13.2", "limesurvey/limesurvey": "<3.27.19", "livehelperchat/livehelperchat": "<=3.91", "livewire/livewire": ">2.2.4,<2.2.6", @@ -830,21 +866,26 @@ "magento/magento1ce": "<1.9.4.3", "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "maikuolan/phpmussel": ">=1,<1.6", + "mantisbt/mantisbt": "<=2.25.5", "marcwillmann/turn": "<0.3.3", "matyhtf/framework": "<3.0.6", "mautic/core": "<4.3|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "mediawiki/matomo": "<2.4.3", "melisplatform/melis-asset-manager": "<5.0.1", "melisplatform/melis-cms": "<5.0.1", "melisplatform/melis-front": "<5.0.1", "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", - "microweber/microweber": "<=1.3.1", + "mgallegos/laravel-jqgrid": "<=1.3", + "microweber/microweber": "<=1.3.4", "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", "modx/revolution": "<= 2.8.3-pl|<2.8", "mojo42/jirafeau": "<4.4", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.0.1", + "moodle/moodle": "<4.2-rc.2|= 3.11", "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", "neoan3-apps/template": "<1.1.1", @@ -856,10 +897,11 @@ "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nilsteampassnet/teampass": "<=2.1.27.36", + "nilsteampassnet/teampass": "<3.0.9", "notrinos/notrinos-erp": "<=0.7", "noumo/easyii": "<=0.9", "nukeviet/nukeviet": "<4.5.2", + "nyholm/psr7": "<1.6.1", "nystudio107/craft-seomatic": "<3.4.12", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": "<1.1.2", @@ -870,9 +912,9 @@ "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "open-web-analytics/open-web-analytics": "<1.7.4", - "opencart/opencart": "<=3.0.3.2", + "opencart/opencart": "<=3.0.3.7", "openid/php-openid": "<2.3", - "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", + "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", "orchid/platform": ">=9,<9.4.4", "oro/commerce": ">=4.1,<5.0.6", "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", @@ -889,45 +931,56 @@ "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", "phanan/koel": "<5.1.4", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": ">=3.2,<3.2.10|>=3.3,<3.3.1", "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<5.1.3", + "phpmyadmin/phpmyadmin": "<5.2.1", "phpmyfaq/phpmyfaq": "<=3.1.7", "phpoffice/phpexcel": "<1.8", "phpoffice/phpspreadsheet": "<1.16", - "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.19", "phpservermon/phpservermon": "<=3.5.2", + "phpsysinfo/phpsysinfo": "<3.2.5", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pimcore/customer-management-framework-bundle": "<3.3.10", "pimcore/data-hub": "<1.2.4", - "pimcore/pimcore": "<=10.5.6", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<10.5.23", + "pixelfed/pixelfed": "<=0.11.4", "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<4.7.2|>= 4.0.0-BETA5, < 4.4.2", + "pocketmine/pocketmine-mp": "<4.20.5|>=4.21,<4.21.1|< 4.18.0-ALPHA2|>= 4.0.0-BETA5, < 4.4.2", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": ">=1.6.0.10,<1.7.8.7", + "prestashop/prestashop": "<8.0.4", "prestashop/productcomments": "<5.0.2", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", "prestashop/ps_linklist": "<3.1", "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", "pterodactyl/panel": "<1.7", "ptrofimov/beanstalk_console": "<1.7.14", "pusher/pusher-php-server": "<2.2.1", "pwweb/laravel-core": "<=0.3.6-beta", + "pyrocms/pyrocms": "<=3.9.1", "rainlab/debugbar-plugin": "<3.1", "rankmath/seo-by-rank-math": "<=1.0.95", - "react/http": ">=0.7,<1.7", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", "remdex/livehelperchat": "<3.99", "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", + "roots/soil": "<4.1", "rudloff/alltube": "<3.0.3", "s-cart/core": "<6.9", "s-cart/s-cart": "<6.9", @@ -936,37 +989,43 @@ "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.4.9", - "shopware/platform": "<=6.4.9", + "shopware/core": "<=6.4.20", + "shopware/platform": "<=6.4.20", "shopware/production": "<=6.3.5.2", "shopware/shopware": "<=5.7.14", "shopware/storefront": "<=6.4.8.1", "shopxo/shopxo": "<2.2.6", "showdoc/showdoc": "<2.10.4", - "silverstripe/admin": ">=1,<1.8.1", - "silverstripe/assets": ">=1,<1.10.1", - "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "silverstripe/admin": "<1.12.7", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.10.9", - "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/framework": "<4.12.5", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1", "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", - "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/subsites": ">=2,<2.6.1", "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", "silverstripe/userforms": "<3", + "silverstripe/versioned-admin": ">=1,<1.11.1", "simple-updates/phpwhois": "<=1", "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", "simplesamlphp/simplesamlphp": "<1.18.6", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.47|>=4,<4.2.1", - "snipe/snipe-it": "<6.0.11|>= 6.0.0-RC-1, <= 6.0.0-RC-5", + "smarty/smarty": "<3.1.48|>=4,<4.3.1", + "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", + "spatie/browsershot": "<3.57.4", "spipu/html2pdf": "<5.2.4", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", @@ -975,7 +1034,10 @@ "stormpath/sdk": ">=0,<9.9.99", "studio-42/elfinder": "<2.1.59", "subrion/cms": "<=4.2.1", + "sukohi/surpass": "<1", "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "sumocoders/framework-user-bundle": "<1.4", + "swag/paypal": "<5.4.4", "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", @@ -985,15 +1047,16 @@ "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", "symbiote/silverstripe-versionedfiles": "<=2.0.3", - "symfont/process": ">=0,<4", + "symfont/process": ">=0", "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", "symfony/mime": ">=4.3,<4.3.8", @@ -1003,13 +1066,13 @@ "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", - "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", + "symfony/symfony": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", @@ -1018,27 +1081,31 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tastyigniter/tastyigniter": "<3.3", + "tcg/voyager": "<=1.4", "tecnickcom/tcpdf": "<6.2.22", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<=5.1.7", - "thorsten/phpmyfaq": "<=3.1.7", - "tinymce/tinymce": "<5.10", + "thorsten/phpmyfaq": "<3.2-beta", + "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", + "tinymighty/wiki-seo": "<1.2.2", "titon/framework": ">=0,<9.9.99", - "topthink/framework": "<=6.0.13", - "topthink/think": "<=6.0.9", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<6.0.14", + "topthink/think": "<=6.1.1", "topthink/thinkphp": "<=3.2.3", - "tribalsystems/zenario": "<9.2.55826", + "tribalsystems/zenario": "<=9.3.57595", "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms": "<2.0.5|>=3,<3.0.3|>=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.58|>=8,<8.7.48|>=9,<9.5.37|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms-core": "<8.7.51|>=9,<9.5.40|>=10,<10.4.36|>=11,<11.5.23|>=12,<12.2", "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "typo3/html-sanitizer": ">=1,<1.0.7|>=2,<2.0.16", + "typo3/html-sanitizer": ">=1,<1.5|>=2,<2.1.1", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", @@ -1047,33 +1114,42 @@ "unisharp/laravel-filemanager": "<=2.5.1", "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", "vanilla/safecurl": "<0.9.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vova07/yii2-fileapi-widget": "<0.1.9", "vrana/adminer": "<4.8.1", "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.5.4", "wanglelecc/laracms": "<=1.0.3", "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", "webcoast/deferred-image-processing": "<1.0.2", + "webpa/webpa": "<3.1.2", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", - "wintercms/winter": "<1.0.475|>=1.1,<1.1.9", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", "woocommerce/woocommerce": "<6.6", "wp-cli/wp-cli": "<2.5", "wp-graphql/wp-graphql": "<0.3.5", "wpanel/wpanel4-cms": "<=4.3.1", - "wwbn/avideo": "<=11.6", + "wpcloud/wp-stateless": "<3.2", + "wwbn/avideo": "<=12.4", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", "yeswiki/yeswiki": "<4.1", "yetiforce/yetiforce-crm": "<=6.4", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", - "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii": "<1.1.27", "yiisoft/yii2": "<2.0.38", "yiisoft/yii2-bootstrap": "<2.0.4", "yiisoft/yii2-dev": "<2.0.43", "yiisoft/yii2-elasticsearch": "<2.0.5", - "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-gii": "<=2.2.4", "yiisoft/yii2-jui": "<2.0.4", "yiisoft/yii2-redis": "<2.0.8", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", "yoast-seo-for-typo3/yoast_seo": "<7.2.3", "yourls/yourls": "<=1.8.2", "zendesk/zendesk_api_client_php": "<2.2.11", @@ -1104,7 +1180,7 @@ "zfr/zfr-oauth2-server-module": "<0.1.2", "zoujingli/thinkadmin": "<6.0.22" }, - "time": "2022-10-24T19:11:20+00:00", + "time": "2023-06-14T05:04:21+00:00", "default-branch": true, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", @@ -1124,6 +1200,9 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], "support": { "issues": "https://github.com/Roave/SecurityAdvisories/issues", "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" diff --git a/apps/files_external/3rdparty/composer/installed.php b/apps/files_external/3rdparty/composer/installed.php index 452835427318..6a4dba03b073 100644 --- a/apps/files_external/3rdparty/composer/installed.php +++ b/apps/files_external/3rdparty/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'files_external/3rdparty', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '44f75de85efe39512ea88955621ebfca9b7963c9', + 'reference' => 'b963992e7b4866eac52efcc536a9d4111c67cdaa', 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), @@ -13,16 +13,16 @@ 'files_external/3rdparty' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '44f75de85efe39512ea88955621ebfca9b7963c9', + 'reference' => 'b963992e7b4866eac52efcc536a9d4111c67cdaa', 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), 'dev_requirement' => false, ), 'firebase/php-jwt' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '4dd1e007f22a927ac77da5a3fbb067b42d3bc224', + 'pretty_version' => 'v6.6.0', + 'version' => '6.6.0.0', + 'reference' => '5a9cf79b4a2eb347230384648cc7b0d68cd97faa', 'type' => 'library', 'install_path' => __DIR__ . '/../firebase/php-jwt', 'aliases' => array(), @@ -58,13 +58,13 @@ 'guzzlehttp/guzzle' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '^7.5', + 0 => '^7.7', ), ), 'guzzlehttp/psr7' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '^2.4', + 0 => '^2.5', ), ), 'icewind/smb' => array( @@ -97,7 +97,7 @@ 'phpseclib/phpseclib' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '>=3.0.17', + 0 => '>=3.0.20', ), ), 'psr/cache' => array( @@ -136,7 +136,7 @@ 'roave/security-advisories' => array( 'pretty_version' => 'dev-latest', 'version' => 'dev-latest', - 'reference' => '599b9d6746e56b67b187afed175dd02fb1a288fa', + 'reference' => '601b276d21df95e49f1802c7432b788cfaac15a8', 'type' => 'metapackage', 'install_path' => NULL, 'aliases' => array( diff --git a/apps/files_external/3rdparty/firebase/php-jwt/CHANGELOG.md b/apps/files_external/3rdparty/firebase/php-jwt/CHANGELOG.md index 9242bd30d533..c74fd13194e3 100644 --- a/apps/files_external/3rdparty/firebase/php-jwt/CHANGELOG.md +++ b/apps/files_external/3rdparty/firebase/php-jwt/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13) + + +### Features + +* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3)) + + +### Bug Fixes + +* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797)) + +## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12) + + +### Bug Fixes + +* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a)) + + +### Miscellaneous Chores + +* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495)) + ## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08) diff --git a/apps/files_external/3rdparty/firebase/php-jwt/README.md b/apps/files_external/3rdparty/firebase/php-jwt/README.md index ae2b389563a0..701de23a828f 100644 --- a/apps/files_external/3rdparty/firebase/php-jwt/README.md +++ b/apps/files_external/3rdparty/firebase/php-jwt/README.md @@ -45,9 +45,12 @@ $payload = [ */ $jwt = JWT::encode($payload, $key, 'HS256'); $decoded = JWT::decode($jwt, new Key($key, 'HS256')); - print_r($decoded); +// Pass a stdClass in as the third parameter to get the decoded header values +$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass()); +print_r($headers); + /* NOTE: This will now be an object instead of an associative array. To get an associative array, you will need to cast it as such: @@ -65,6 +68,40 @@ $decoded_array = (array) $decoded; JWT::$leeway = 60; // $leeway in seconds $decoded = JWT::decode($jwt, new Key($key, 'HS256')); ``` +Example encode/decode headers +------- +Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by +this library. This is because without verifying the JWT, the header values could have been tampered with. +Any value pulled from an unverified header should be treated as if it could be any string sent in from an +attacker. If this is something you still want to do in your application for whatever reason, it's possible to +decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT +header part: +```php +use Firebase\JWT\JWT; + +$key = 'example_key'; +$payload = [ + 'iss' => 'http://example.org', + 'aud' => 'http://example.com', + 'iat' => 1356999524, + 'nbf' => 1357000000 +]; + +$headers = [ + 'x-forwarded-for' => 'www.google.com' +]; + +// Encode headers in the JWT string +$jwt = JWT::encode($payload, $key, 'HS256', null, $headers); + +// Decode headers from the JWT string WITHOUT validation +// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified. +// These headers could be any value sent by an attacker. +list($headersB64, $payloadB64, $sig) = explode('.', $jwt); +$decoded = json_decode(base64_decode($headersB64), true); + +print_r($decoded); +``` Example with RS256 (openssl) ---------------------------- ```php @@ -73,28 +110,43 @@ use Firebase\JWT\Key; $privateKey = << 'example.org', + 'aud' => 'example.com', + 'iat' => 1356999524, + 'nbf' => 1357000000 +]; + +$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1'); +$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2'); +echo "Encode 1:\n" . print_r($jwt1, true) . "\n"; +echo "Encode 2:\n" . print_r($jwt2, true) . "\n"; + +$keys = [ + 'kid1' => new Key($publicKey1, 'RS256'), + 'kid2' => new Key($publicKey2, 'EdDSA'), +]; + +$decoded1 = JWT::decode($jwt1, $keys); +$decoded2 = JWT::decode($jwt2, $keys); + +echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n"; +echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n"; +``` + Using JWKs ---------- @@ -286,6 +376,8 @@ All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException` like this: ```php +use Firebase\JWT\JWT; +use UnexpectedValueException; try { $decoded = JWT::decode($payload, $keys); } catch (LogicException $e) { diff --git a/apps/files_external/3rdparty/firebase/php-jwt/composer.json b/apps/files_external/3rdparty/firebase/php-jwt/composer.json index c9aa3dbbc26a..e23dfe378d8f 100644 --- a/apps/files_external/3rdparty/firebase/php-jwt/composer.json +++ b/apps/files_external/3rdparty/firebase/php-jwt/composer.json @@ -20,7 +20,7 @@ ], "license": "BSD-3-Clause", "require": { - "php": "^7.1||^8.0" + "php": "^7.4||^8.0" }, "suggest": { "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present", @@ -33,8 +33,8 @@ }, "require-dev": { "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "psr/cache": "^1.0||^2.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" diff --git a/apps/files_external/3rdparty/firebase/php-jwt/src/JWT.php b/apps/files_external/3rdparty/firebase/php-jwt/src/JWT.php index 269e8caf0d3d..7ffb98521c15 100644 --- a/apps/files_external/3rdparty/firebase/php-jwt/src/JWT.php +++ b/apps/files_external/3rdparty/firebase/php-jwt/src/JWT.php @@ -69,11 +69,16 @@ class JWT * Decodes a JWT string into a PHP object. * * @param string $jwt The JWT - * @param Key|array $keyOrKeyArray The Key or associative array of key IDs (kid) to Key objects. - * If the algorithm used is asymmetric, this is the public key - * Each Key object contains an algorithm and matching key. - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' + * @param Key|ArrayAccess|array $keyOrKeyArray The Key or associative array of key IDs + * (kid) to Key objects. + * If the algorithm used is asymmetric, this is + * the public key. + * Each Key object contains an algorithm and + * matching key. + * Supported algorithms are 'ES384','ES256', + * 'HS256', 'HS384', 'HS512', 'RS256', 'RS384' + * and 'RS512'. + * @param stdClass $headers Optional. Populates stdClass with headers. * * @return stdClass The JWT's payload as a PHP object * @@ -90,7 +95,8 @@ class JWT */ public static function decode( string $jwt, - $keyOrKeyArray + $keyOrKeyArray, + stdClass &$headers = null ): stdClass { // Validate JWT $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp; @@ -107,6 +113,9 @@ public static function decode( if (null === ($header = static::jsonDecode($headerRaw))) { throw new UnexpectedValueException('Invalid header encoding'); } + if ($headers !== null) { + $headers = $header; + } $payloadRaw = static::urlsafeB64Decode($bodyb64); if (null === ($payload = static::jsonDecode($payloadRaw))) { throw new UnexpectedValueException('Invalid claims encoding'); @@ -152,7 +161,7 @@ public static function decode( // Check that this token has been created before 'now'. This prevents // using tokens that have been created for later use (and haven't // correctly used the nbf claim). - if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) { + if (!isset($payload->nbf) && isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) { throw new BeforeValidException( 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat) ); @@ -376,7 +385,7 @@ public static function jsonEncode(array $input): string } if ($errno = \json_last_error()) { self::handleJsonError($errno); - } elseif ($json === 'null' && $input !== null) { + } elseif ($json === 'null') { throw new DomainException('Null result with non-null input'); } if ($json === false) { @@ -435,7 +444,7 @@ private static function getKey( return $keyOrKeyArray; } - if (empty($kid)) { + if (empty($kid) && $kid !== '0') { throw new UnexpectedValueException('"kid" empty, unable to lookup correct key'); } diff --git a/apps/files_external/ajax/oauth2.php b/apps/files_external/ajax/oauth2.php index 4044bbdb1b56..22ffa1669d76 100644 --- a/apps/files_external/ajax/oauth2.php +++ b/apps/files_external/ajax/oauth2.php @@ -38,7 +38,7 @@ $client->setClientSecret((string)$_POST['client_secret']); $client->setRedirectUri((string)$_POST['redirect']); $client->setScopes(['https://www.googleapis.com/auth/drive']); - $client->setApprovalPrompt('force'); + $client->setPrompt('consent'); $client->setAccessType('offline'); if (isset($_POST['step'])) { $step = $_POST['step']; diff --git a/apps/files_external/l10n/en_GB.js b/apps/files_external/l10n/en_GB.js index beb6f53976d5..351ca1f064df 100644 --- a/apps/files_external/l10n/en_GB.js +++ b/apps/files_external/l10n/en_GB.js @@ -15,10 +15,16 @@ OC.L10N.register( "Error generating key pair" : "Error generating key pair", "All users. Type to select user or group." : "All users. Type to select user or group.", "(group)" : "(group)", + "All users" : "All users", "Compatibility with Mac NFD encoding (slow)" : "Compatibility with Mac NFD encoding (slow)", + "Sharing cannot be enabled due to the chosen authentication method" : "Sharing cannot be enabled due to the chosen authentication method", "Unknown auth backend \"{b}\"" : "Unknown auth backend \"{b}\"", "Please make sure that the app that provides this backend is installed and enabled" : "Please make sure that the app that provides this backend is installed and enabled", "Admin defined" : "Admin defined", + "An error occurred while adding the external storage, please check the logs or contact the administrator" : "An error occurred while adding the external storage, please check the logs or contact the administrator", + "External storage has been added successfully" : "External storage has been added successfully", + "An error occurred while adding the external storage please check the logs" : "An error occurred while adding the external storage please check the logs", + "An error occurred while loading external mount point: {name}" : "An error occurred while loading external mount point: {name}", "Saved" : "Saved", "Disabling external storage will unmount all storages for all users, are you sure ?" : "Disabling external storage will unmount all storages for all users, are you sure ?", "Disable external storage" : "Disable external storage", @@ -69,6 +75,7 @@ OC.L10N.register( "Remote subfolder" : "Remote subfolder", "Secure https://" : "Secure https://", "Google Drive" : "Google Drive", + "SubFolder" : "SubFolder", "Local" : "Local", "Location" : "Location", "ownCloud" : "ownCloud", @@ -76,8 +83,12 @@ OC.L10N.register( "Host" : "Host", "Root" : "Root", "SFTP with secret key login" : "SFTP with secret key login", + "SMB Personal (unique file IDs)" : "SMB Personal (unique file IDs)", "Share" : "Share", "Domain" : "Domain", + "SMB Collaborative (shared file IDs)" : "SMB Collaborative (shared file IDs)", + "Service Account" : "Service Account", + "Service Account Password" : "Service Account Password", "SMB / CIFS using OC login" : "SMB / CIFS using OC login", "Username as share" : "Username as share", "Note: " : "Note: ", diff --git a/apps/files_external/l10n/en_GB.json b/apps/files_external/l10n/en_GB.json index c439ba988bf7..75c9f4220519 100644 --- a/apps/files_external/l10n/en_GB.json +++ b/apps/files_external/l10n/en_GB.json @@ -13,10 +13,16 @@ "Error generating key pair" : "Error generating key pair", "All users. Type to select user or group." : "All users. Type to select user or group.", "(group)" : "(group)", + "All users" : "All users", "Compatibility with Mac NFD encoding (slow)" : "Compatibility with Mac NFD encoding (slow)", + "Sharing cannot be enabled due to the chosen authentication method" : "Sharing cannot be enabled due to the chosen authentication method", "Unknown auth backend \"{b}\"" : "Unknown auth backend \"{b}\"", "Please make sure that the app that provides this backend is installed and enabled" : "Please make sure that the app that provides this backend is installed and enabled", "Admin defined" : "Admin defined", + "An error occurred while adding the external storage, please check the logs or contact the administrator" : "An error occurred while adding the external storage, please check the logs or contact the administrator", + "External storage has been added successfully" : "External storage has been added successfully", + "An error occurred while adding the external storage please check the logs" : "An error occurred while adding the external storage please check the logs", + "An error occurred while loading external mount point: {name}" : "An error occurred while loading external mount point: {name}", "Saved" : "Saved", "Disabling external storage will unmount all storages for all users, are you sure ?" : "Disabling external storage will unmount all storages for all users, are you sure ?", "Disable external storage" : "Disable external storage", @@ -67,6 +73,7 @@ "Remote subfolder" : "Remote subfolder", "Secure https://" : "Secure https://", "Google Drive" : "Google Drive", + "SubFolder" : "SubFolder", "Local" : "Local", "Location" : "Location", "ownCloud" : "ownCloud", @@ -74,8 +81,12 @@ "Host" : "Host", "Root" : "Root", "SFTP with secret key login" : "SFTP with secret key login", + "SMB Personal (unique file IDs)" : "SMB Personal (unique file IDs)", "Share" : "Share", "Domain" : "Domain", + "SMB Collaborative (shared file IDs)" : "SMB Collaborative (shared file IDs)", + "Service Account" : "Service Account", + "Service Account Password" : "Service Account Password", "SMB / CIFS using OC login" : "SMB / CIFS using OC login", "Username as share" : "Username as share", "Note: " : "Note: ", diff --git a/apps/files_external/lib/Command/Applicable.php b/apps/files_external/lib/Command/Applicable.php index 86542701ed37..70e923666f13 100644 --- a/apps/files_external/lib/Command/Applicable.php +++ b/apps/files_external/lib/Command/Applicable.php @@ -97,7 +97,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $mountId = $input->getArgument('mount_id'); try { $mount = $this->globalService->getStorage($mountId); diff --git a/apps/files_external/lib/Command/Backends.php b/apps/files_external/lib/Command/Backends.php index f53d021108b0..c2fc1dd413f6 100644 --- a/apps/files_external/lib/Command/Backends.php +++ b/apps/files_external/lib/Command/Backends.php @@ -59,7 +59,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $authBackends = $this->backendService->getAuthMechanisms(); $storageBackends = $this->backendService->getBackends(); diff --git a/apps/files_external/lib/Command/Config.php b/apps/files_external/lib/Command/Config.php index b27b9506c9ba..a253439d303a 100644 --- a/apps/files_external/lib/Command/Config.php +++ b/apps/files_external/lib/Command/Config.php @@ -61,7 +61,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $mountId = $input->getArgument('mount_id'); $key = $input->getArgument('key'); try { diff --git a/apps/files_external/lib/Command/Create.php b/apps/files_external/lib/Command/Create.php index e13c4a08efd4..ea93edd4ec11 100644 --- a/apps/files_external/lib/Command/Create.php +++ b/apps/files_external/lib/Command/Create.php @@ -117,7 +117,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $input->getOption('user'); $mountPoint = $input->getArgument('mount_point'); $storageIdentifier = $input->getArgument('storage_backend'); diff --git a/apps/files_external/lib/Command/Delete.php b/apps/files_external/lib/Command/Delete.php index 9d6f0f01264a..1ae61d3ac4a8 100644 --- a/apps/files_external/lib/Command/Delete.php +++ b/apps/files_external/lib/Command/Delete.php @@ -81,7 +81,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $mountId = $input->getArgument('mount_id'); try { $mount = $this->globalService->getStorage($mountId); diff --git a/apps/files_external/lib/Command/Export.php b/apps/files_external/lib/Command/Export.php index 88e17a77a510..a9b75b1efc9c 100644 --- a/apps/files_external/lib/Command/Export.php +++ b/apps/files_external/lib/Command/Export.php @@ -44,7 +44,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $listCommand = new ListCommand($this->globalService, $this->userService, $this->userSession, $this->userManager); $listInput = new ArrayInput([], $listCommand->getDefinition()); $listInput->setArgument('user_id', $input->getArgument('user_id')); diff --git a/apps/files_external/lib/Command/Import.php b/apps/files_external/lib/Command/Import.php index 5dcb85410943..de7f8968f937 100644 --- a/apps/files_external/lib/Command/Import.php +++ b/apps/files_external/lib/Command/Import.php @@ -99,7 +99,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $input->getOption('user'); $path = $input->getArgument('path'); if ($path === '-') { diff --git a/apps/files_external/lib/Command/ListCommand.php b/apps/files_external/lib/Command/ListCommand.php index 73897a394223..d3ead5ebcc6e 100644 --- a/apps/files_external/lib/Command/ListCommand.php +++ b/apps/files_external/lib/Command/ListCommand.php @@ -111,7 +111,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('all')) { /** @var $mounts IStorageConfig[] */ $mounts = $this->globalService->getStorageForAllUsers(); diff --git a/apps/files_external/lib/Command/Verify.php b/apps/files_external/lib/Command/Verify.php index e720a2b64ecc..1013016a1348 100644 --- a/apps/files_external/lib/Command/Verify.php +++ b/apps/files_external/lib/Command/Verify.php @@ -63,7 +63,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $mountId = $input->getArgument('mount_id'); $configInput = $input->getOption('config'); diff --git a/apps/files_external/lib/Lib/Storage/Google.php b/apps/files_external/lib/Lib/Storage/Google.php index eb882038a45d..74b1cf3694df 100644 --- a/apps/files_external/lib/Lib/Storage/Google.php +++ b/apps/files_external/lib/Lib/Storage/Google.php @@ -474,6 +474,8 @@ public function rename($path1, $path2) { if ($file) { $newFile = $this->getDriveFile($path2); $toUpdate = new DriveFile(); + $addedParent = ''; + $removedParent = ''; if (\dirname($path1) === \dirname($path2)) { if ($newFile) { // rename to the name of the target file, could be an office file without extension diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js index 2c98da47d548..61a8da9e851b 100644 --- a/apps/files_sharing/js/app.js +++ b/apps/files_sharing/js/app.js @@ -209,18 +209,19 @@ OCA.Sharing.App = { fileList.fileSummary.$el.find('.filesize').remove(); }, - _setShareState: function(fileId, state, isRemote) { + _setShareState: function(fileId, state, isRemote, shareType) { var method = 'POST'; if (state === OC.Share.STATE_REJECTED) { method = 'DELETE'; } - var endPoint = isRemote === true ? 'remote_shares/pending/' : 'shares/pending/'; var xhr = $.ajax({ url: OC.linkToOCS('apps/files_sharing/api/v1') + endPoint + encodeURIComponent(fileId) + '?format=json', contentType: 'application/json', dataType: 'json', type: method, + // be aware that `shareType` should not be an empty string + data: JSON.stringify((shareType !== undefined ? { shareType: shareType } : {})), }); xhr.fail(function(response) { var message = ''; @@ -236,6 +237,7 @@ OCA.Sharing.App = { _shareStateActionHandler: function(context, newState) { var targetFileData = context.fileList.elementToFile(context.$file); var isRemote = targetFileData.shareLocationType === 'remote'; + const shareType = targetFileData.shareType; function responseCallback(response, status) { if (status === 'success') { var meta = response.ocs.meta; @@ -252,7 +254,7 @@ OCA.Sharing.App = { } context.fileList.showFileBusyState(context.$file, true); - this._setShareState(context.fileInfoModel.get('shares')[0].id, newState, isRemote) + this._setShareState(context.fileInfoModel.get('shares')[0].id, newState, isRemote, shareType) .then(responseCallback); }, diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js index e9eb3ac5d9ca..41afb6d45b7e 100644 --- a/apps/files_sharing/js/external.js +++ b/apps/files_sharing/js/external.js @@ -142,16 +142,20 @@ shares[index], false, function(result, share) { + let shareType = "user"; + if (share.hasOwnProperty('share_type') ){ + shareType = share.share_type; + } if (result) { // Accept - $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id}) + $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id, share_type: shareType }) .then(function() { fileList.reload(); }); } else { // Delete $.ajax({ - url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id), + url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id+"?share_type="+shareType), type: 'DELETE' }); } diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 93789ef86462..004f014cd574 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -151,6 +151,8 @@ hasShares = true; } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) { hasShares = true; + } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) { + hasShares = true; } }); OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink); diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index 7a8230d77680..e9b55312cbac 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -88,6 +88,7 @@ $dateColumn.before($tr.children('td:first')); $tr.find('td.filename input:checkbox').remove(); $tr.attr('data-share-location-type', fileData.shareLocationType); + $tr.attr('data-share-type', fileData.shareType); $tr.attr('data-share-id', _.pluck(fileData.shares, 'id').join(',')); // add row with expiration date for link only shares - influenced by _createRow of filelist if (this._linksOnly) { @@ -309,7 +310,8 @@ } fileInfo.shareState = parseInt($el.attr('data-share-state'), 10); - fileInfo.shareLocationType = $el.attr('data-share-location-type'); + fileInfo.shareLocationType = $el.attr('data-share-location-type'); + fileInfo.shareType = $el.attr('data-share-type') || ""; return fileInfo; }, @@ -355,7 +357,8 @@ path: OC.dirname(share.mountpoint), permissions: share.permissions, tags: share.tags || [], - shareLocationType: 'remote' + shareLocationType: 'remote', + shareType: share.share_type || '' }; file.shares = [{ diff --git a/apps/files_sharing/l10n/en_GB.js b/apps/files_sharing/l10n/en_GB.js index a34cf7a1fa00..625e86f9924b 100644 --- a/apps/files_sharing/l10n/en_GB.js +++ b/apps/files_sharing/l10n/en_GB.js @@ -4,7 +4,9 @@ OC.L10N.register( "Server to server sharing is not enabled on this server" : "Server to server sharing is not enabled on this server", "The mountpoint name contains invalid characters." : "The mountpoint name contains invalid characters.", "Not allowed to create a federated share with the same user server" : "Not allowed to create a federated share with the same user server", + "Could not authenticate to federated share, password might be wrong" : "Could not authenticate to federated share, password might be wrong", "Storage not valid" : "Storage not valid", + "Couldn't add federated share" : "Couldn't add federated share", "Shared with you" : "Shared with you", "Shared with others" : "Shared with others", "Shared by link" : "Shared by link", @@ -21,13 +23,25 @@ OC.L10N.register( "An error occurred while updating share state: {message}" : "An error occurred while updating share state: {message}", "Accept Share" : "Accept Share", "Decline Share" : "Decline Share", + "Do you want to add the federated share {name} from {owner}@{remote}?" : "Do you want to add the federated share {name} from {owner}@{remote}?", + "Federated share" : "Federated share", + "Federated share password" : "Federated share password", "Cancel" : "Cancel", + "Add federated share" : "Add federated share", + "The video cannot be played because your browser does not support the file type. Please try another browser." : "The video cannot be played because your browser does not support the file type. Please try another browser.", "You can upload into this folder" : "You can upload into this folder", + "Add to another cloud" : "Add to another cloud", + "Enter the server address to add the content to" : "Enter the server address to add the content to", "Add" : "Add", "No ownCloud installation (7 or higher) found at {remote}" : "No ownCloud installation (7 or higher) found at {remote}", "Invalid ownCloud url" : "Invalid ownCloud URL", "Share" : "Share", "Create public link" : "Create public link", + "Create and copy public link" : "Create and copy public link", + "Public quick link" : "Public quick link", + "Public link has been copied to the clipboard." : "Public link has been copied to the clipboard.", + "A new public link with download & view permissions has been created and copied to the clipboard." : "A new public link with download & view permissions has been created and copied to the clipboard.", + "The public link could not be created. Please contact the administrator for help." : "The public link could not be created. Please contact the administrator for help.", "No expiration date set" : "No expiration date set", "Declined" : "Declined", "Pending" : "Pending", @@ -36,6 +50,10 @@ OC.L10N.register( "A file or folder has been shared" : "A file or folder has been shared", "A file or folder was shared from another server" : "A file or folder was shared from another server", "A public shared file or folder was downloaded" : "A public shared file or folder was downloaded", + "You received a new federated share %2$s from %1$s" : "You received a new federated share %2$s from %1$s", + "You received a new federated share from %s" : "You received a new federated share from %s", + "%1$s accepted federated share %2$s" : "%1$s accepted federated share %2$s", + "%1$s declined federated share %2$s" : "%1$s declined federated share %2$s", "%1$s unshared %2$s from you" : "%1$s unshared %2$s from you", "Public shared folder %1$s was downloaded" : "Public shared folder %1$s was downloaded", "Public shared file %1$s was downloaded" : "Public shared file %1$s was downloaded", @@ -55,6 +73,7 @@ OC.L10N.register( "Your public link for %1$s expired" : "Your public link for %1$s expired", "The public link of %2$s for %1$s expired" : "The public link of %2$s for %1$s expired", "%2$s shared %1$s with you" : "%2$s shared %1$s with you", + "The share for %1$s expired" : "The share for %1$s expired", "%2$s removed the share for %1$s" : "%2$s removed the share for %1$s", "Downloaded via public link" : "Downloaded via public link", "Shared with %2$s" : "Shared with %2$s", @@ -73,12 +92,15 @@ OC.L10N.register( "Public link expired" : "Public link expired", "Public link of %2$s expired" : "Public link of %2$s expired", "Shared by %2$s" : "Shared by %2$s", + "Received federated share from %1$s" : "Received federated share from %1$s", + "Received federated share from %s" : "Received federated share from %s", "Shares" : "Shares", "File sharing" : "File sharing", "Public link" : "Public link", "Couldn't send mail to following recipient(s): %s " : "Couldn't send mail to following recipient(s): %s ", "Share API is disabled" : "Share API is disabled", "Wrong share ID, share doesn't exist" : "Wrong share ID, share doesn't exist", + "Share points to a node not available" : "Share points to a node not available", "Could not delete share" : "Could not delete share", "Please specify a file or folder path" : "Please specify a file or folder path", "Wrong path, file/folder doesn't exist" : "Wrong path, file/folder doesn't exist", @@ -88,9 +110,11 @@ OC.L10N.register( "Please specify a valid group" : "Please specify a valid group", "The group is blacklisted for sharing" : "The group is blacklisted for sharing", "Public link sharing is disabled by the administrator" : "Public link sharing is disabled by the administrator", + "Public link creation is only possible for certain groups" : "Public link creation is only possible for certain groups", "Public upload disabled by the administrator" : "Public upload disabled by the administrator", "Public upload is only possible for publicly shared folders" : "Public upload is only possible for publicly shared folders", "Sharing %s failed because the back end does not allow shares from type %s" : "Sharing %s failed because the back end does not allow shares from type %s", + "shareWith parameter must be a string" : "shareWith parameter must be a string", "Unknown share type" : "Unknown share type", "Could not lock path" : "Could not lock path", "Not a directory" : "Not a directory", @@ -127,6 +151,7 @@ OC.L10N.register( "Nothing to configure." : "Nothing to configure.", "Group Sharing Blacklist" : "Group Sharing Blacklist", "Exclude groups from receiving shares" : "Exclude groups from receiving shares", - "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." : "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." + "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." : "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual.", + "Only certain groups are allowed to create public links" : "Only certain groups are allowed to create public links" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_sharing/l10n/en_GB.json b/apps/files_sharing/l10n/en_GB.json index acbd3b1abbe8..01c06777bcd4 100644 --- a/apps/files_sharing/l10n/en_GB.json +++ b/apps/files_sharing/l10n/en_GB.json @@ -2,7 +2,9 @@ "Server to server sharing is not enabled on this server" : "Server to server sharing is not enabled on this server", "The mountpoint name contains invalid characters." : "The mountpoint name contains invalid characters.", "Not allowed to create a federated share with the same user server" : "Not allowed to create a federated share with the same user server", + "Could not authenticate to federated share, password might be wrong" : "Could not authenticate to federated share, password might be wrong", "Storage not valid" : "Storage not valid", + "Couldn't add federated share" : "Couldn't add federated share", "Shared with you" : "Shared with you", "Shared with others" : "Shared with others", "Shared by link" : "Shared by link", @@ -19,13 +21,25 @@ "An error occurred while updating share state: {message}" : "An error occurred while updating share state: {message}", "Accept Share" : "Accept Share", "Decline Share" : "Decline Share", + "Do you want to add the federated share {name} from {owner}@{remote}?" : "Do you want to add the federated share {name} from {owner}@{remote}?", + "Federated share" : "Federated share", + "Federated share password" : "Federated share password", "Cancel" : "Cancel", + "Add federated share" : "Add federated share", + "The video cannot be played because your browser does not support the file type. Please try another browser." : "The video cannot be played because your browser does not support the file type. Please try another browser.", "You can upload into this folder" : "You can upload into this folder", + "Add to another cloud" : "Add to another cloud", + "Enter the server address to add the content to" : "Enter the server address to add the content to", "Add" : "Add", "No ownCloud installation (7 or higher) found at {remote}" : "No ownCloud installation (7 or higher) found at {remote}", "Invalid ownCloud url" : "Invalid ownCloud URL", "Share" : "Share", "Create public link" : "Create public link", + "Create and copy public link" : "Create and copy public link", + "Public quick link" : "Public quick link", + "Public link has been copied to the clipboard." : "Public link has been copied to the clipboard.", + "A new public link with download & view permissions has been created and copied to the clipboard." : "A new public link with download & view permissions has been created and copied to the clipboard.", + "The public link could not be created. Please contact the administrator for help." : "The public link could not be created. Please contact the administrator for help.", "No expiration date set" : "No expiration date set", "Declined" : "Declined", "Pending" : "Pending", @@ -34,6 +48,10 @@ "A file or folder has been shared" : "A file or folder has been shared", "A file or folder was shared from another server" : "A file or folder was shared from another server", "A public shared file or folder was downloaded" : "A public shared file or folder was downloaded", + "You received a new federated share %2$s from %1$s" : "You received a new federated share %2$s from %1$s", + "You received a new federated share from %s" : "You received a new federated share from %s", + "%1$s accepted federated share %2$s" : "%1$s accepted federated share %2$s", + "%1$s declined federated share %2$s" : "%1$s declined federated share %2$s", "%1$s unshared %2$s from you" : "%1$s unshared %2$s from you", "Public shared folder %1$s was downloaded" : "Public shared folder %1$s was downloaded", "Public shared file %1$s was downloaded" : "Public shared file %1$s was downloaded", @@ -53,6 +71,7 @@ "Your public link for %1$s expired" : "Your public link for %1$s expired", "The public link of %2$s for %1$s expired" : "The public link of %2$s for %1$s expired", "%2$s shared %1$s with you" : "%2$s shared %1$s with you", + "The share for %1$s expired" : "The share for %1$s expired", "%2$s removed the share for %1$s" : "%2$s removed the share for %1$s", "Downloaded via public link" : "Downloaded via public link", "Shared with %2$s" : "Shared with %2$s", @@ -71,12 +90,15 @@ "Public link expired" : "Public link expired", "Public link of %2$s expired" : "Public link of %2$s expired", "Shared by %2$s" : "Shared by %2$s", + "Received federated share from %1$s" : "Received federated share from %1$s", + "Received federated share from %s" : "Received federated share from %s", "Shares" : "Shares", "File sharing" : "File sharing", "Public link" : "Public link", "Couldn't send mail to following recipient(s): %s " : "Couldn't send mail to following recipient(s): %s ", "Share API is disabled" : "Share API is disabled", "Wrong share ID, share doesn't exist" : "Wrong share ID, share doesn't exist", + "Share points to a node not available" : "Share points to a node not available", "Could not delete share" : "Could not delete share", "Please specify a file or folder path" : "Please specify a file or folder path", "Wrong path, file/folder doesn't exist" : "Wrong path, file/folder doesn't exist", @@ -86,9 +108,11 @@ "Please specify a valid group" : "Please specify a valid group", "The group is blacklisted for sharing" : "The group is blacklisted for sharing", "Public link sharing is disabled by the administrator" : "Public link sharing is disabled by the administrator", + "Public link creation is only possible for certain groups" : "Public link creation is only possible for certain groups", "Public upload disabled by the administrator" : "Public upload disabled by the administrator", "Public upload is only possible for publicly shared folders" : "Public upload is only possible for publicly shared folders", "Sharing %s failed because the back end does not allow shares from type %s" : "Sharing %s failed because the back end does not allow shares from type %s", + "shareWith parameter must be a string" : "shareWith parameter must be a string", "Unknown share type" : "Unknown share type", "Could not lock path" : "Could not lock path", "Not a directory" : "Not a directory", @@ -125,6 +149,7 @@ "Nothing to configure." : "Nothing to configure.", "Group Sharing Blacklist" : "Group Sharing Blacklist", "Exclude groups from receiving shares" : "Exclude groups from receiving shares", - "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." : "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." + "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual." : "These groups will not be available to share with. Members of the group are not restricted in initiating shares and can receive shares with other groups they are a member of as usual.", + "Only certain groups are allowed to create public links" : "Only certain groups are allowed to create public links" },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/files_sharing/l10n/ka_GE.js b/apps/files_sharing/l10n/ka_GE.js index ca1d733c64cb..bb93bfb14144 100644 --- a/apps/files_sharing/l10n/ka_GE.js +++ b/apps/files_sharing/l10n/ka_GE.js @@ -8,9 +8,11 @@ OC.L10N.register( "Pending" : "მოცდის რეჟიმში", "Shared by" : "აზიარებს", "Sharing" : "გაზიარება", + "This share is password-protected" : "ეს გაზიარება დაცულია პაროლით", "Password" : "პაროლი", "Name" : "სახელი", "Expiration date" : "ვადის გასვლის დრო", - "Download" : "ჩამოტვირთვა" + "Download" : "ჩამოტვირთვა", + "Direct link" : "პირდაპირი ბმული" }, "nplurals=2; plural=(n!=1);"); diff --git a/apps/files_sharing/l10n/ka_GE.json b/apps/files_sharing/l10n/ka_GE.json index a2215e41e2f6..f9f775e99e8a 100644 --- a/apps/files_sharing/l10n/ka_GE.json +++ b/apps/files_sharing/l10n/ka_GE.json @@ -6,9 +6,11 @@ "Pending" : "მოცდის რეჟიმში", "Shared by" : "აზიარებს", "Sharing" : "გაზიარება", + "This share is password-protected" : "ეს გაზიარება დაცულია პაროლით", "Password" : "პაროლი", "Name" : "სახელი", "Expiration date" : "ვადის გასვლის დრო", - "Download" : "ჩამოტვირთვა" + "Download" : "ჩამოტვირთვა", + "Direct link" : "პირდაპირი ბმული" },"pluralForm" :"nplurals=2; plural=(n!=1);" } \ No newline at end of file diff --git a/apps/files_sharing/l10n/vi.js b/apps/files_sharing/l10n/vi.js index 79309a2d27af..adcb7642cd5d 100644 --- a/apps/files_sharing/l10n/vi.js +++ b/apps/files_sharing/l10n/vi.js @@ -14,6 +14,7 @@ OC.L10N.register( "Cancel" : "Hủy", "Add" : "Thêm", "Share" : "Chia sẻ", + "Create public link" : "Tạo liên kết công khai", "Declined" : "Từ chối", "Pending" : "Đang chờ", "Shared by" : "Chia sẻ bởi", diff --git a/apps/files_sharing/l10n/vi.json b/apps/files_sharing/l10n/vi.json index c8bdf0a02e39..d871237fe7b9 100644 --- a/apps/files_sharing/l10n/vi.json +++ b/apps/files_sharing/l10n/vi.json @@ -12,6 +12,7 @@ "Cancel" : "Hủy", "Add" : "Thêm", "Share" : "Chia sẻ", + "Create public link" : "Tạo liên kết công khai", "Declined" : "Từ chối", "Pending" : "Đang chờ", "Shared by" : "Chia sẻ bởi", diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index 47637b98750c..11cd5437d8b4 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -81,7 +81,8 @@ public function __construct(array $urlParams = []) { $c->query('Request'), $c->query('ExternalManager'), $c->query('HttpClientService'), - $server->getEventDispatcher() + $server->getEventDispatcher(), + $server->getConfig() ); }); @@ -119,6 +120,8 @@ public function __construct(array $urlParams = []) { $server->getEventDispatcher(), $uid ), + $server->getConfig(), + $server->getLogger(), $uid ); }); diff --git a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php index 6f0780216162..7e652fecedc7 100644 --- a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php +++ b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php @@ -56,7 +56,7 @@ protected function configure() { ); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $remoteStorages = $this->getRemoteStorages(); $output->writeln(\count($remoteStorages) . " remote storage(s) need(s) to be checked"); diff --git a/apps/files_sharing/lib/Controller/RemoteOcsController.php b/apps/files_sharing/lib/Controller/RemoteOcsController.php index 97c437921c74..8d82b28cf736 100644 --- a/apps/files_sharing/lib/Controller/RemoteOcsController.php +++ b/apps/files_sharing/lib/Controller/RemoteOcsController.php @@ -29,6 +29,8 @@ use OCP\Share; use OCP\Files\StorageNotAvailableException; use OCP\Files\StorageInvalidException; +use OCP\IConfig; +use OCP\ILogger; class RemoteOcsController extends OCSController { /** @var IRequest */ @@ -40,23 +42,39 @@ class RemoteOcsController extends OCSController { /** @var string */ protected $uid; + /** + * @var IConfig + */ + protected $config; + + /** + * @var ILogger + */ + protected $logger; + /** * RemoteOcsController constructor. * * @param string $appName * @param IRequest $request * @param Manager $externalManager + * @param IConfig config + * @param ILogger $loggar * @param string $uid */ public function __construct( $appName, IRequest $request, Manager $externalManager, + IConfig $config, + ILogger $logger, $uid ) { parent::__construct($appName, $request); $this->request = $request; $this->externalManager = $externalManager; + $this->config = $config; + $this->logger = $logger; $this->uid = $uid; } @@ -126,6 +144,8 @@ public function declineShare($id) { */ public function getShares($includingPending = false) { $shares = []; + $groupExternalManager = null; + foreach ($this->externalManager->getAcceptedShares() as $shareInfo) { try { $shares[] = $this->extendShareInfo($shareInfo); @@ -136,6 +156,22 @@ public function getShares($includingPending = false) { } } + // Allow the Federated Groups app to overwrite the behaviour of this endpoint + $managerClass = $this->config->getSystemValue('sharing.groupExternalManager'); + if (!empty($managerClass)) { + $groupExternalManager = \OC::$server->query($managerClass); + + foreach ($groupExternalManager->getAcceptedShares() as $shareInfo) { + try { + $shares[] = $this->extendShareInfo($shareInfo); + } catch (StorageNotAvailableException $e) { + $this->logger->logException($e, ['app' => 'files_sharing']); + } catch (StorageInvalidException $e) { + $this->logger->logException($e, ['app' => 'files_sharing']); + } + } + } + if ($includingPending === true) { /** * pending shares have mountpoint looking like @@ -152,7 +188,10 @@ function ($share) { $share['mountpoint'] = \rtrim($share['mountpoint'], '}'); return $share; }, - $this->externalManager->getOpenShares() + \array_merge( + $this->externalManager->getOpenShares(), + $groupExternalManager === null ? [] : $groupExternalManager->getOpenShares() + ) ); $shares = \array_merge($shares, $openShares); } diff --git a/apps/files_sharing/lib/Controller/Share20OcsController.php b/apps/files_sharing/lib/Controller/Share20OcsController.php index 38e9f141257c..0a2d706cb78b 100644 --- a/apps/files_sharing/lib/Controller/Share20OcsController.php +++ b/apps/files_sharing/lib/Controller/Share20OcsController.php @@ -23,6 +23,7 @@ use Exception; use OC\Files\Filesystem; +use OC\Share20\Exception\ProviderException; use OCA\Files_Sharing\SharingAllowlist; use OCP\Constants; use OC\OCS\Result; @@ -267,7 +268,7 @@ protected function formatShare(IShare $share, $received = false) { if ($share->getToken() !== null) { $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); } - } elseif ($share->getShareType() === Share::SHARE_TYPE_REMOTE) { + } elseif ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) { $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $share->getSharedWith(); $result['token'] = $share->getToken(); @@ -287,6 +288,7 @@ protected function formatShare(IShare $share, $received = false) { * Get a specific share by id * * @NoAdminRequired + * @NoCSRFRequired * * @param string $id * @return Result @@ -552,7 +554,7 @@ public function createShare() { if ($password !== '') { $share->setPassword($password); } - } elseif ($shareType === Share::SHARE_TYPE_REMOTE) { + } elseif ($shareType === Share::SHARE_TYPE_REMOTE || $shareType === Share::SHARE_TYPE_REMOTE_GROUP) { if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); @@ -684,6 +686,7 @@ private function getSharedWithMe($node, $includeTags, $requestedShareTypes, $sta * the function will return an empty list. * * @NoAdminRequired + * @NoCSRFRequired * * - Get shares by the current user * - Get shares by the current user and reshares (?reshares=true) @@ -700,6 +703,7 @@ public function getShares() { return new Result(); } + $supportedShareTypes = $this->getSupportedShareTypes(); $sharedWithMe = $this->request->getParam('shared_with_me', null); $reshares = $this->request->getParam('reshares', null); $subfiles = $this->request->getParam('subfiles'); @@ -708,26 +712,16 @@ public function getShares() { $includeTags = $this->request->getParam('include_tags', false); $shareTypes = $this->request->getParam('share_types', ''); if ($shareTypes === '') { - $shareTypes = [ - Share::SHARE_TYPE_USER, - Share::SHARE_TYPE_GROUP, - Share::SHARE_TYPE_LINK, - Share::SHARE_TYPE_REMOTE, - ]; + $shareTypes = $supportedShareTypes; } else { $shareTypes = \explode(',', $shareTypes); } - $requestedShareTypes = [ - Share::SHARE_TYPE_USER => false, - Share::SHARE_TYPE_GROUP => false, - Share::SHARE_TYPE_LINK => false, - Share::SHARE_TYPE_REMOTE => false, - ]; - + $requestedShareTypes = array_fill_keys($supportedShareTypes, false); + if ($this->shareManager->outgoingServer2ServerSharesAllowed() === false) { // if outgoing remote shares aren't allowed, the remote share type can't be chosen - unset($requestedShareTypes[Share::SHARE_TYPE_REMOTE]); + unset($requestedShareTypes[Share::SHARE_TYPE_REMOTE], $requestedShareTypes[Share::SHARE_TYPE_REMOTE_GROUP]); } foreach ($shareTypes as $shareType) { if (isset($requestedShareTypes[$shareType])) { @@ -1209,16 +1203,27 @@ private function parseDate($expireDate) { */ private function getShareById($id, $recipient = null) { $share = null; - + $providerIds = \array_keys($this->shareManager->getProvidersCapabilities()); + // First check if it is an internal share. - try { - $share = $this->shareManager->getShareById('ocinternal:'.$id, $recipient); - } catch (ShareNotFound $e) { - if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { - throw new ShareNotFound(); + foreach ($providerIds as $providerId) { + try { + $share = $this->shareManager->getShareById($providerId .":". $id, $recipient); + return $share; + } catch (ShareNotFound $e) { + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { + throw new ShareNotFound(); + } + + continue; + } catch (ProviderException $e) { + // We should iterate all provider to find proper provider for given share + continue; } + } - $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $recipient); + if ($share === null) { + throw new ShareNotFound(); } return $share; @@ -1288,4 +1293,23 @@ private function getPermissionsFromRequest() { return $permission; } + + /** + * @return mixed + */ + private function getSupportedShareTypes() { + $providersCapabilities = $this->shareManager->getProvidersCapabilities(); + + $shareTypes = []; + + foreach ($providersCapabilities as $capabilities) { + foreach ($capabilities as $key => $value) { + $shareTypes[] = $key; + } + } + $shareTypes = \array_unique($shareTypes); + $shareTypes = array_keys(array_intersect(Share::CONVERT_SHARE_TYPE_TO_STRING, $shareTypes)); + + return $shareTypes; + } } diff --git a/apps/files_sharing/lib/Controllers/ExternalSharesController.php b/apps/files_sharing/lib/Controllers/ExternalSharesController.php index 62e0cf2794db..7cc05cca6921 100644 --- a/apps/files_sharing/lib/Controllers/ExternalSharesController.php +++ b/apps/files_sharing/lib/Controllers/ExternalSharesController.php @@ -29,6 +29,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\JSONResponse; use OCP\Http\Client\IClientService; +use OCP\IConfig; use OCP\IRequest; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; @@ -41,6 +42,8 @@ class ExternalSharesController extends Controller { /** @var \OCA\Files_Sharing\External\Manager */ private $externalManager; + /** @var \OCA\Files_Sharing\External\Manager */ + private $groupExternalManager = null; /** @var IClientService */ private $clientService; /** @@ -48,6 +51,10 @@ class ExternalSharesController extends Controller { */ private $dispatcher; + /** @var IConfig $config */ + private $config; + + public const group_share_type = "group"; /** * ExternalSharesController constructor. * @@ -56,18 +63,21 @@ class ExternalSharesController extends Controller { * @param \OCA\Files_Sharing\External\Manager $externalManager * @param IClientService $clientService * @param EventDispatcherInterface $eventDispatcher + * @param IConfig $config */ public function __construct( $appName, IRequest $request, \OCA\Files_Sharing\External\Manager $externalManager, IClientService $clientService, - EventDispatcherInterface $eventDispatcher + EventDispatcherInterface $eventDispatcher, + IConfig $config ) { parent::__construct($appName, $request); $this->externalManager = $externalManager; $this->clientService = $clientService; $this->dispatcher = $eventDispatcher; + $this->config = $config; } /** @@ -77,7 +87,13 @@ public function __construct( * @return JSONResponse */ public function index() { - return new JSONResponse($this->externalManager->getOpenShares()); + $federatedGroupResult = []; + $groupExternalManager = $this->initGroupManager(); + if ($groupExternalManager !== null) { + $federatedGroupResult = $groupExternalManager->getOpenShares(); + } + $result = array_merge($federatedGroupResult, $this->externalManager->getOpenShares()); + return new JSONResponse($result); } /** @@ -85,13 +101,16 @@ public function index() { * @NoOutgoingFederatedSharingRequired * * @param int $id + * @param string $share_type * @return JSONResponse */ - public function create($id) { - $shareInfo = $this->externalManager->getShare($id); + public function create($id, $share_type) { + $manager = $this->getManagerForShareType($share_type); + $shareInfo = $manager->getShare($id); + if ($shareInfo !== false) { - $mountPoint = $this->externalManager->getShareRecipientMountPoint($shareInfo); - $fileId = $this->externalManager->getShareFileId($shareInfo, $mountPoint); + $mountPoint = $manager->getShareRecipientMountPoint($shareInfo); + $fileId = $manager->getShareFileId($shareInfo, $mountPoint); $event = new GenericEvent( null, @@ -106,7 +125,7 @@ public function create($id) { ] ); $this->dispatcher->dispatch($event, 'remoteshare.accepted'); - $this->externalManager->acceptShare($id); + $manager->acceptShare($id); } return new JSONResponse(); } @@ -118,8 +137,9 @@ public function create($id) { * @param integer $id * @return JSONResponse */ - public function destroy($id) { - $shareInfo = $this->externalManager->getShare($id); + public function destroy($id, $share_type) { + $manager = $this->getManagerForShareType($share_type); + $shareInfo = $manager->getShare($id); if ($shareInfo !== false) { $event = new GenericEvent( null, @@ -131,11 +151,30 @@ public function destroy($id) { ] ); $this->dispatcher->dispatch($event, 'remoteshare.declined'); - $this->externalManager->declineShare($id); + $manager->declineShare($id); } return new JSONResponse(); } + private function initGroupManager() { + // Allow other apps to add an external manager for user-to-group shares + $managerClass = $this->config->getSystemValue('sharing.groupExternalManager'); + if ($managerClass !== '') { + return \OC::$server->query($managerClass); + } + return null; + } + + private function getManagerForShareType($share_type) { + $groupExternalManager = $this->initGroupManager(); + if ($share_type === self::group_share_type && $groupExternalManager !== null) { + $manager = $groupExternalManager; + } else { + $manager = $this->externalManager; + } + return $manager; + } + /** * Test whether the specified remote is accessible * diff --git a/apps/files_sharing/lib/Helper.php b/apps/files_sharing/lib/Helper.php index 726ab7197939..a770ba239be2 100644 --- a/apps/files_sharing/lib/Helper.php +++ b/apps/files_sharing/lib/Helper.php @@ -34,6 +34,7 @@ use OC\Files\View; use OCP\Files\NotFoundException; use OCP\User; +use OC\Helper\UserTypeHelper; class Helper { public static function registerHooks() { @@ -281,9 +282,15 @@ public static function getShareFolder($view = null) { if ($view === null) { $view = Filesystem::getView(); } + // for guests we default to root as their home storage is read-only + $user = User::getUser(); + $userTypeHelper = new UserTypeHelper(); + $isGuestUser = $userTypeHelper->isGuestUser($user); + if ($isGuestUser) { + return '/'; + } $shareFolder = \OC::$server->getConfig()->getSystemValue('share_folder', '/'); $shareFolder = Filesystem::normalizePath($shareFolder); - if (!$view->file_exists($shareFolder)) { // if the share folder doesn't exists, create the folder in order // to place the shares inside it. All the parent folders need to diff --git a/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php b/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php index 514149929d03..7fa328b898d3 100644 --- a/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php +++ b/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php @@ -24,6 +24,8 @@ use OC\Files\FileInfo; use OCA\Files_Sharing\Controller\RemoteOcsController; use OCA\Files_Sharing\External\Manager; +use OCP\IConfig; +use OCP\ILogger; use OCP\IRequest; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -38,16 +40,27 @@ class RemoteOcsControllerTest extends TestCase { /** @var Manager */ protected $externalManager; + /** @var IConfig */ + protected $config; + + /** @var ILogger */ + protected $logger; + /** @var RemoteOcsController | MockObject */ protected $controller; protected function setUp(): void { $this->request = $this->createMock(IRequest::class); $this->externalManager = $this->createMock(Manager::class); + $this->config = $this->createMock(IConfig::class); + $this->logger = $this->createMock(ILogger::class); + $this->controller = new RemoteOcsController( $this->appName, $this->request, $this->externalManager, + $this->config, + $this->logger, 'user' ); } @@ -170,6 +183,8 @@ public function testGetShare($getShareResult, $expectedStatusCode) { $this->appName, $this->request, $this->externalManager, + $this->config, + $this->logger, 'user' ]) ->setMethods(['getFileInfo']) diff --git a/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php index 0598929f22b8..babfb5c4e06b 100644 --- a/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php +++ b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php @@ -121,6 +121,20 @@ protected function setUp(): void { ->expects($this->any()) ->method('newShare') ->willReturn($this->newShare()); + $this->shareManager + ->method('getProvidersCapabilities') + ->willReturn([ + "ocinternal" => + [ + "user" => ["shareExpiration"], + "group" => ["shareExpiration"], + "link" => ["shareExpiration", "passwordProtected"] + ], + "ocFederatedSharing"=> + [ + "remote" => ["shareExpiration"] + ], + ]); $this->groupManager = $this->createMock(IGroupManager::class); $this->userManager = $this->createMock(IUserManager::class); $this->request = $this->createMock(IRequest::class); diff --git a/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php index 2e745d5675cf..0d9ee014986c 100644 --- a/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php +++ b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php @@ -65,7 +65,8 @@ public function getExternalShareController() { $this->request, $this->externalManager, $this->clientService, - \OC::$server->getEventDispatcher() + \OC::$server->getEventDispatcher(), + \OC::$server->getConfig() ); } @@ -107,7 +108,7 @@ public function testCreate() { $called[] = 'remoteshare.accepted'; \array_push($called, $event); }); - $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create($shareId)); + $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create($shareId, "remote")); $this->assertSame('remoteshare.accepted', $called[0]); $this->assertInstanceOf(GenericEvent::class, $called[1]); @@ -137,7 +138,7 @@ public function testDestroy() { \array_push($called, $event); }); - $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy($shareId)); + $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy($shareId, "user")); $this->assertSame('remoteshare.declined', $called[0]); $this->assertInstanceOf(GenericEvent::class, $called[1]); diff --git a/apps/files_sharing/tests/HooksTest.php b/apps/files_sharing/tests/HooksTest.php index 22b91a6ab4ed..b7e930015aa6 100644 --- a/apps/files_sharing/tests/HooksTest.php +++ b/apps/files_sharing/tests/HooksTest.php @@ -147,7 +147,7 @@ public function testPrivateLink() { 'resolvedWebLink' => null, 'resolvedDavLink' => null, ]); - $this->eventDispatcher->dispatch('files.resolvePrivateLink', $event); + $this->eventDispatcher->dispatch($event, 'files.resolvePrivateLink'); $this->assertEquals('/owncloud/index.php/apps/files/?view=sharingin&scrollto=123', $event->getArgument('resolvedWebLink')); $this->assertNull($event->getArgument('resolvedDavLink')); @@ -168,7 +168,7 @@ public function testPrivateLinkNoMatch() { 'resolvedWebLink' => null, 'resolvedDavLink' => null, ]); - $this->eventDispatcher->dispatch('files.resolvePrivateLink', $event); + $this->eventDispatcher->dispatch($event, 'files.resolvePrivateLink'); $this->assertNull($event->getArgument('resolvedWebLink')); $this->assertNull($event->getArgument('resolvedDavLink')); @@ -182,7 +182,7 @@ public function testDeleteGroup() { $this->sharingAllowlist->expects($this->once())->method('setPublicShareSharersGroupsAllowlist')->with([]); $event = new GenericEvent($group); - $this->eventDispatcher->dispatch('group.postDelete', $event); + $this->eventDispatcher->dispatch($event, 'group.postDelete'); } public function testPublishShareNotification() { @@ -196,7 +196,7 @@ public function testPublishShareNotification() { 'share' => ['id' => '123'], 'shareObject' => $share, ]); - $this->eventDispatcher->dispatch('share.afterCreate', $event); + $this->eventDispatcher->dispatch($event, 'share.afterCreate'); } public function testDiscardShareNotification() { @@ -210,7 +210,7 @@ public function testDiscardShareNotification() { 'share' => ['id' => '123'], 'shareObject' => $share, ]); - $this->eventDispatcher->dispatch('share.afterDelete', $event); + $this->eventDispatcher->dispatch($event, 'share.afterDelete'); } public function providesDataForCanGet() { @@ -271,7 +271,7 @@ public function testCheckDirectCanBeDownloaded($path, $userFolder, $run) { // Simulate direct download of file $event = new GenericEvent(null, [ 'path' => $path ]); - $this->eventDispatcher->dispatch('file.beforeGetDirect', $event); + $this->eventDispatcher->dispatch($event, 'file.beforeGetDirect'); $this->assertEquals($run, !$event->hasArgument('errorMessage')); } @@ -349,7 +349,7 @@ public function testCheckZipCanBeDownloaded($dir, $files, $userFolder, $run) { // Simulate zip download of folder folder $event = new GenericEvent(null, ['dir' => $dir, 'files' => $files, 'run' => true]); - $this->eventDispatcher->dispatch('file.beforeCreateZip', $event); + $this->eventDispatcher->dispatch($event, 'file.beforeCreateZip'); $this->assertEquals($run, $event->getArgument('run')); $this->assertEquals($run, !$event->hasArgument('errorMessage')); @@ -360,7 +360,7 @@ public function testCheckFileUserNotFound() { // Simulate zip download of folder folder $event = new GenericEvent(null, ['dir' => '/test', 'files' => ['test.txt'], 'run' => true]); - $this->eventDispatcher->dispatch('file.beforeCreateZip', $event); + $this->eventDispatcher->dispatch($event, 'file.beforeCreateZip'); // It should run as this would restrict e.g. share links otherwise $this->assertTrue($event->getArgument('run')); @@ -394,7 +394,7 @@ public function testPublishShareSelfUnshareEvent() { 'shareRecipient' => 'recipient_user', 'shareOwner' => 'owner_user', ]); - $this->eventDispatcher->dispatch('fromself.unshare', $event); + $this->eventDispatcher->dispatch($event, 'fromself.unshare'); } public function testExtendJsConfig() { diff --git a/apps/files_sharing/tests/js/externalSpec.js b/apps/files_sharing/tests/js/externalSpec.js index 21f88b3c333a..4d0ea3d7fed9 100644 --- a/apps/files_sharing/tests/js/externalSpec.js +++ b/apps/files_sharing/tests/js/externalSpec.js @@ -174,7 +174,7 @@ describe('OCA.Sharing external tests', function() { var request = fakeServer.requests[1]; var query = OC.parseQueryString(request.requestBody); expect(request.method).toEqual('POST'); - expect(query).toEqual({id: '123'}); + expect(query).toEqual({id: '123', share_type: 'user'}); expect(request.url).toEqual( OC.webroot + '/index.php/apps/files_sharing/api/externalShares' ); @@ -200,7 +200,7 @@ describe('OCA.Sharing external tests', function() { var request = fakeServer.requests[1]; expect(request.method).toEqual('DELETE'); expect(request.url).toEqual( - OC.webroot + '/index.php/apps/files_sharing/api/externalShares/123' + OC.webroot + '/index.php/apps/files_sharing/api/externalShares/123?share_type=user' ); expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true); diff --git a/apps/files_trashbin/lib/Command/CleanUp.php b/apps/files_trashbin/lib/Command/CleanUp.php index 54bb48079e85..c7ba7fe2fb04 100644 --- a/apps/files_trashbin/lib/Command/CleanUp.php +++ b/apps/files_trashbin/lib/Command/CleanUp.php @@ -64,7 +64,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $users = $input->getArgument('user_id'); if (!empty($users)) { foreach ($users as $user) { diff --git a/apps/files_trashbin/lib/Command/ExpireTrash.php b/apps/files_trashbin/lib/Command/ExpireTrash.php index 7a58fd98a1ea..9e30990b350a 100644 --- a/apps/files_trashbin/lib/Command/ExpireTrash.php +++ b/apps/files_trashbin/lib/Command/ExpireTrash.php @@ -67,7 +67,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $retentionEnabled = $this->trashExpiryManager->retentionEnabled(); if (!$retentionEnabled) { $output->writeln("Auto expiration is configured - expiration will be handled automatically."); diff --git a/apps/files_trashbin/lib/Helper.php b/apps/files_trashbin/lib/Helper.php index 0ba1672c80a3..a0045efaf4c8 100644 --- a/apps/files_trashbin/lib/Helper.php +++ b/apps/files_trashbin/lib/Helper.php @@ -48,7 +48,7 @@ public static function getTrashFiles($dir, $user, $sortAttribute = '', $sortDesc $view = new \OC\Files\View('/' . $user . '/files_trashbin/files'); if (\ltrim($dir, '/') !== '' && !$view->is_dir($dir)) { - throw new \Exception('Directory does not exists'); + throw new \Exception('Directory does not exist'); } $mount = $view->getMount($dir); diff --git a/apps/files_trashbin/tests/TrashbinTest.php b/apps/files_trashbin/tests/TrashbinTest.php index 0cbd4f74441c..8a9f550c8180 100644 --- a/apps/files_trashbin/tests/TrashbinTest.php +++ b/apps/files_trashbin/tests/TrashbinTest.php @@ -565,7 +565,7 @@ public function testPrivateLink() { 'resolvedWebLink' => null, 'resolvedDavLink' => null, ]); - \OC::$server->getEventDispatcher()->dispatch('files.resolvePrivateLink', $event); + \OC::$server->getEventDispatcher()->dispatch($event, 'files.resolvePrivateLink'); $this->assertEquals('/owncloud/index.php/apps/files/?view=trashbin&dir=/test.d1462861890/sub&scrollto=somefile.txt', $event->getArgument('resolvedWebLink')); $this->assertNull($event->getArgument('resolvedDavLink')); diff --git a/apps/files_versions/l10n/tr.js b/apps/files_versions/l10n/tr.js index a45c2fc15f4a..c4634e0c4778 100644 --- a/apps/files_versions/l10n/tr.js +++ b/apps/files_versions/l10n/tr.js @@ -2,8 +2,13 @@ OC.L10N.register( "files_versions", { "Versions" : "Sürümler", + "File {file} has been reverted and marked as new current version" : "{file} dosyası geri alındı ve yeni geçerli sürüm olarak işaretlendi", "Failed to revert {file} to revision {timestamp}." : "{file} dosyası {timestamp} gözden geçirmesine geri alınamadı.", + "Failed to publish version" : "Sürüm yayınlanamadı", "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"], - "Restore" : "Geri yükle" + "Restore" : "Geri yükle", + "persistent" : "kalıcı", + "Publish version" : "Yayın sürümü", + "current" : "geçerli" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/files_versions/l10n/tr.json b/apps/files_versions/l10n/tr.json index 1ab5dc7fcb56..eb2a59d6622c 100644 --- a/apps/files_versions/l10n/tr.json +++ b/apps/files_versions/l10n/tr.json @@ -1,7 +1,12 @@ { "translations": { "Versions" : "Sürümler", + "File {file} has been reverted and marked as new current version" : "{file} dosyası geri alındı ve yeni geçerli sürüm olarak işaretlendi", "Failed to revert {file} to revision {timestamp}." : "{file} dosyası {timestamp} gözden geçirmesine geri alınamadı.", + "Failed to publish version" : "Sürüm yayınlanamadı", "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"], - "Restore" : "Geri yükle" + "Restore" : "Geri yükle", + "persistent" : "kalıcı", + "Publish version" : "Yayın sürümü", + "current" : "geçerli" },"pluralForm" :"nplurals=2; plural=(n > 1);" } \ No newline at end of file diff --git a/apps/files_versions/lib/Command/CleanUp.php b/apps/files_versions/lib/Command/CleanUp.php index 6e3464b1d94c..8ccf10433751 100644 --- a/apps/files_versions/lib/Command/CleanUp.php +++ b/apps/files_versions/lib/Command/CleanUp.php @@ -57,7 +57,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $users = $input->getArgument('user_id'); if (!empty($users)) { foreach ($users as $user) { diff --git a/apps/files_versions/lib/Command/ExpireVersions.php b/apps/files_versions/lib/Command/ExpireVersions.php index a8ab34eddcae..21228d50e710 100644 --- a/apps/files_versions/lib/Command/ExpireVersions.php +++ b/apps/files_versions/lib/Command/ExpireVersions.php @@ -68,7 +68,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $maxAge = $this->expiration->getMaxAgeAsTimestamp(); if (!$maxAge) { $output->writeln("Auto expiration is configured - expiration will be handled automatically."); diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 44c18d55f8a3..6233ee62900f 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -469,7 +469,7 @@ public static function renameOrCopy($sourcePath, $targetPath, $operation) { if (self::metaEnabled()) { // NOTE: we need to move current file first as in case of interuption lack of this file could cause issues - + // Also move/copy the current version $src = '/files_versions/' . $sourcePath . MetaStorage::CURRENT_FILE_PREFIX . MetaStorage::VERSION_FILE_EXT; $dst = '/files_versions/' . $targetPath . MetaStorage::CURRENT_FILE_PREFIX . MetaStorage::VERSION_FILE_EXT; @@ -635,7 +635,7 @@ public static function publishCurrentVersion($filename) { if (Filesystem::is_dir($filename) || !Filesystem::file_exists($filename)) { return false; } - + list($uid, $currentFileName) = self::getUidAndFilename($filename); // overwrite current file metadata with minor=false to create new major version @@ -671,7 +671,7 @@ public static function getVersions($uid, $filename) { if ($dirContent === false) { return $versions; } - + // add historical versions if (\is_resource($dirContent)) { while (($entryName = \readdir($dirContent)) !== false) { @@ -682,7 +682,7 @@ public static function getVersions($uid, $filename) { $pathparts = \pathinfo($entryName); $timestamp = \substr($pathparts['extension'], 1); $filename = $pathparts['filename']; - + // ordering key $key = $timestamp . '#' . $filename; @@ -971,15 +971,17 @@ public static function expire($filename, $uid) { // if still not enough free space we rearrange the versions from all files if ($availableSpace <= 0) { $result = self::getFileHelper()->getAllVersions($uid); - $allVersions = $result['all']; + if ($result) { + $allVersions = $result['all']; - foreach ($result['by_file'] as $versions) { - list($toDeleteNew, $size) = self::getExpireList($time, $versions, $availableSpace <= 0); - $toDelete = \array_merge($toDelete, $toDeleteNew); - $sizeOfDeletedVersions += $size; + foreach ($result['by_file'] as $versions) { + list($toDeleteNew, $size) = self::getExpireList($time, $versions, $availableSpace <= 0); + $toDelete = \array_merge($toDelete, $toDeleteNew); + $sizeOfDeletedVersions += $size; + } + $availableSpace = $availableSpace + $sizeOfDeletedVersions; + $versionsSize = $versionsSize - $sizeOfDeletedVersions; } - $availableSpace = $availableSpace + $sizeOfDeletedVersions; - $versionsSize = $versionsSize - $sizeOfDeletedVersions; } // we need to check if we have to remove any empty folder based on the diff --git a/apps/updatenotification/l10n/pt_BR.js b/apps/updatenotification/l10n/pt_BR.js index 890f36c83cca..a663ec25d439 100644 --- a/apps/updatenotification/l10n/pt_BR.js +++ b/apps/updatenotification/l10n/pt_BR.js @@ -15,6 +15,7 @@ OC.L10N.register( "Update channel:" : "Atualização do canal:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Você pode sempre atualizar para uma versão / canal experimental mais recente. Mas você nunca pode voltar para um canal mais estável.", "Notify members of the following groups about available updates:" : "Notificar membros dos seguintes grupos sobre atualizações disponíveis.", - "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Somente notificação para atualizações de aplicativos estão disponíveis, porque o canal de atualização selecionada para ownCloud não permite notificações." + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Somente notificação para atualizações de aplicativos estão disponíveis, porque o canal de atualização selecionada para ownCloud não permite notificações.", + "Online updater has been automatically disabled as you are currently running an ownCloud Enterprise edition. Please update your ownCloud instance manually." : "O atualizador online foi desativado automaticamente porque você está executando uma edição OwnCloud Enterprise. Atualize sua instância ownCloud manualmente." }, "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/apps/updatenotification/l10n/pt_BR.json b/apps/updatenotification/l10n/pt_BR.json index 87618acc5273..69fdb762a400 100644 --- a/apps/updatenotification/l10n/pt_BR.json +++ b/apps/updatenotification/l10n/pt_BR.json @@ -13,6 +13,7 @@ "Update channel:" : "Atualização do canal:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Você pode sempre atualizar para uma versão / canal experimental mais recente. Mas você nunca pode voltar para um canal mais estável.", "Notify members of the following groups about available updates:" : "Notificar membros dos seguintes grupos sobre atualizações disponíveis.", - "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Somente notificação para atualizações de aplicativos estão disponíveis, porque o canal de atualização selecionada para ownCloud não permite notificações." + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Somente notificação para atualizações de aplicativos estão disponíveis, porque o canal de atualização selecionada para ownCloud não permite notificações.", + "Online updater has been automatically disabled as you are currently running an ownCloud Enterprise edition. Please update your ownCloud instance manually." : "O atualizador online foi desativado automaticamente porque você está executando uma edição OwnCloud Enterprise. Atualize sua instância ownCloud manualmente." },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" } \ No newline at end of file diff --git a/apps/updatenotification/l10n/sq.js b/apps/updatenotification/l10n/sq.js index 90f853ceb3d3..b2f7e48fde18 100644 --- a/apps/updatenotification/l10n/sq.js +++ b/apps/updatenotification/l10n/sq.js @@ -15,6 +15,7 @@ OC.L10N.register( "Update channel:" : "Kanal përditësimesh:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Mundeni përherë ta përditësoni me një version të ri / kanal eksperimental. Por nuk mund ta ulni kurrë versionin në një version më të qëndrueshëm.", "Notify members of the following groups about available updates:" : "Njoftoji anëtarët e grupeve vijues për përditësime të gatshme:", - "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Njoftim vetëm kur ka gati përditësime aplikimesh, ngaqë kanali i përditësimeve i përzgjedhur për ownCloud-in vetë nuk lejon njoftime." + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Njoftim vetëm kur ka gati përditësime aplikimesh, ngaqë kanali i përditësimeve i përzgjedhur për ownCloud-in vetë nuk lejon njoftime.", + "Online updater has been automatically disabled as you are currently running an ownCloud Enterprise edition. Please update your ownCloud instance manually." : "Përditësuesi që nga interneti është çaktivizuar automatikisht, ngaqë aktualisht xhironi një version ownCloud Enterprise. Ju lutemi, përditësojeni dorazi instancën tuaj ownCloud." }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/updatenotification/l10n/sq.json b/apps/updatenotification/l10n/sq.json index 5d9ec36cd440..b14bcd34ce25 100644 --- a/apps/updatenotification/l10n/sq.json +++ b/apps/updatenotification/l10n/sq.json @@ -13,6 +13,7 @@ "Update channel:" : "Kanal përditësimesh:", "You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel." : "Mundeni përherë ta përditësoni me një version të ri / kanal eksperimental. Por nuk mund ta ulni kurrë versionin në një version më të qëndrueshëm.", "Notify members of the following groups about available updates:" : "Njoftoji anëtarët e grupeve vijues për përditësime të gatshme:", - "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Njoftim vetëm kur ka gati përditësime aplikimesh, ngaqë kanali i përditësimeve i përzgjedhur për ownCloud-in vetë nuk lejon njoftime." + "Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications." : "Njoftim vetëm kur ka gati përditësime aplikimesh, ngaqë kanali i përditësimeve i përzgjedhur për ownCloud-in vetë nuk lejon njoftime.", + "Online updater has been automatically disabled as you are currently running an ownCloud Enterprise edition. Please update your ownCloud instance manually." : "Përditësuesi që nga interneti është çaktivizuar automatikisht, ngaqë aktualisht xhironi një version ownCloud Enterprise. Ju lutemi, përditësojeni dorazi instancën tuaj ownCloud." },"pluralForm" :"nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/apps/updatenotification/lib/Controller/AdminController.php b/apps/updatenotification/lib/Controller/AdminController.php index 9035d417c393..af0045da92ad 100644 --- a/apps/updatenotification/lib/Controller/AdminController.php +++ b/apps/updatenotification/lib/Controller/AdminController.php @@ -97,10 +97,21 @@ public function getPanel() { if ($this->config->getSystemValue('upgrade.disable-web', false) === true) { return false; } + + if (\OC_Util::getEditionString() === 'Enterprise') { + return $this->displayEnterprisePanel(); + } return $this->displayPanel(); } + /** + * @return TemplateResponse + */ + public function displayEnterprisePanel() { + return new TemplateResponse($this->appName, 'enterprise', [], ''); + } + /** * @return TemplateResponse */ diff --git a/apps/updatenotification/templates/enterprise.php b/apps/updatenotification/templates/enterprise.php new file mode 100644 index 000000000000..8a74c931e344 --- /dev/null +++ b/apps/updatenotification/templates/enterprise.php @@ -0,0 +1,6 @@ +
+ +

t('Updater')); ?>

+ t('Online updater has been automatically disabled as you are currently running an ownCloud Enterprise edition. Please update your ownCloud instance manually.')) ?> + +
diff --git a/build/yarn.lock b/build/yarn.lock index f3c03c4f4393..988a4a7da1c9 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -1572,9 +1572,9 @@ select@^1.1.2: integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== setprototypeof@1.1.1: version "1.1.1" diff --git a/changelog/10.12.2_2023-05-31/40792 b/changelog/10.12.2_2023-05-31/40792 new file mode 100644 index 000000000000..6c597fa18ea2 --- /dev/null +++ b/changelog/10.12.2_2023-05-31/40792 @@ -0,0 +1,3 @@ +Bugfix: Filter sensitive data in log for Session::loginInOwnCloud + +https://github.com/owncloud/core/pull/40792 diff --git a/changelog/10.12.2_2023-05-31/40803 b/changelog/10.12.2_2023-05-31/40803 new file mode 100644 index 000000000000..ebdfe19037b5 --- /dev/null +++ b/changelog/10.12.2_2023-05-31/40803 @@ -0,0 +1,3 @@ +Bugfix: Disallow permission tobe upgraded via federated sharing + +https://github.com/owncloud/core/pull/40803 diff --git a/changelog/CHANGELOG-html.tmpl b/changelog/CHANGELOG-html.tmpl index 8e08b965b488..5e040e31b71e 100644 --- a/changelog/CHANGELOG-html.tmpl +++ b/changelog/CHANGELOG-html.tmpl @@ -1224,7 +1224,7 @@

External storage

Dav App

diff --git a/changelog/CHANGELOG.tmpl b/changelog/CHANGELOG.tmpl index ca3697d07a9e..9214b55e217f 100644 --- a/changelog/CHANGELOG.tmpl +++ b/changelog/CHANGELOG.tmpl @@ -1181,7 +1181,7 @@ Details #### External storage - "Local" storage type can now be disabled by sysadmin in config.php [#26653](https://github.com/owncloud/core/issues/26653) -- External storage backends must use [core external storage API](https://doc.owncloud.org/server/10.0/developer_manual/app/extstorage.html) to work without "files_external" [#18160](https://github.com/owncloud/core/issues/18160) +- External storage backends must use [core external storage API](https://doc.owncloud.com/server/next/developer_manual/app/advanced/extstorage.html) to work without "files_external" [#18160](https://github.com/owncloud/core/issues/18160) - FTP external storage moved to a separate app [files_external_ftp](https://github.com/owncloud/files_external_ftp) #### Dav App diff --git a/changelog/unreleased/40518 b/changelog/unreleased/40518 new file mode 100644 index 000000000000..427f88c6f640 --- /dev/null +++ b/changelog/unreleased/40518 @@ -0,0 +1,16 @@ +Change: upgrade to Symfony 5 + +The Symfony PHP framework has been updated from major version 4 to 5. + +The following Symfony component versions are provided: +- symfony/console (v5.4.24) +- symfony/event-dispatcher (v5.4.22) +- symfony/process (v5.4.24) +- symfony/routing (v5.4.25) +- symfony/string (v5.4.22) +- symfony/translation (v5.4.24) + +https://github.com/owncloud/core/issues/39630 +https://github.com/owncloud/core/pull/40518 +https://github.com/owncloud/core/pull/40819 +https://github.com/owncloud/core/pull/40849 diff --git a/changelog/unreleased/40577 b/changelog/unreleased/40577 new file mode 100644 index 000000000000..02ebc8dcb44e --- /dev/null +++ b/changelog/unreleased/40577 @@ -0,0 +1,10 @@ +Enhancement: Add support for OCM via ScienceMesh + + +We've added an if-statement in the files_sharing ShareesController +code that searches for remote sharees. When the 'sciencemesh' app +is installed, use it instead of the federatedfilesharing app to +find sharee matches for OCM sharing. + +https://github.com/owncloud/core/issues/40577 +https://github.com/pondersource/oc-sciencemesh/pull/39 \ No newline at end of file diff --git a/changelog/unreleased/40715 b/changelog/unreleased/40715 new file mode 100644 index 000000000000..8a164604e080 --- /dev/null +++ b/changelog/unreleased/40715 @@ -0,0 +1,7 @@ +Enhancement: Improve X-Robots-Tag header values check + +Setup checks now allows other values other than "none" for X-Robots-Tag header. +If "none" or "noindex" and "nofollow" are missing, a security warning is raised. +Previously a header value with "noindex" and "nofollow" wasn't allowed even though it was valid. + +https://github.com/owncloud/core/pull/40715 diff --git a/changelog/unreleased/40726 b/changelog/unreleased/40726 index 4bb31f1fd268..af9c328cd467 100644 --- a/changelog/unreleased/40726 +++ b/changelog/unreleased/40726 @@ -1,5 +1,5 @@ Change: fix name length check on federated shares -A federated share with a too long name results in inaccessible data. +A federated share with a too long name results in potentially inaccessible data. https://github.com/owncloud/core/pull/40726 diff --git a/changelog/unreleased/40769 b/changelog/unreleased/40769 new file mode 100644 index 000000000000..928866937c8d --- /dev/null +++ b/changelog/unreleased/40769 @@ -0,0 +1,5 @@ +Change: validate email and string user input in UserController + +User input is validated now in UserController + +https://github.com/owncloud/core/pull/40769 diff --git a/changelog/unreleased/40771 b/changelog/unreleased/40771 new file mode 100644 index 000000000000..24a0f3a6ddc8 --- /dev/null +++ b/changelog/unreleased/40771 @@ -0,0 +1,6 @@ +Change: fix hiding Last Login column on Users page + +The Last Login column on the Users page is now correctly hidden if the setting +is initially unchecked. + +https://github.com/owncloud/core/pull/40771 diff --git a/changelog/unreleased/40779 b/changelog/unreleased/40779 new file mode 100644 index 000000000000..6e6a44701513 --- /dev/null +++ b/changelog/unreleased/40779 @@ -0,0 +1,10 @@ +Enhancement: Added occ command to remove obsolete storages + +Metadata coming from storages are stored in the DB. When a storage has been +removed from ownCloud, that metadata remains in the DB. + +The new occ command allows you to remove that metadata stored, reducing +the amount of space used by the DB as well as slightly improving the +performance since there will be less entries. + +https://github.com/owncloud/core/pull/40779 diff --git a/changelog/unreleased/40783 b/changelog/unreleased/40783 new file mode 100644 index 000000000000..843545803579 --- /dev/null +++ b/changelog/unreleased/40783 @@ -0,0 +1,6 @@ +Bugfix: Align to new accounts.google.com authorization URI + +Core 10.12.1 brought an update of the google/apiclient from version 2.12.6 to 2.13.1. However, in version 2.13.0 the accounts.google.com authorization URI has been updated. This change breaks old code that uses the "setApprovalPrompt('force')" instead of the newer "setPrompt('consent')" method, as this endpoint does not support the legacy approval prompt parameter. This has been now fixed. + +https://github.com/owncloud/core/pull/40783 +https://github.com/owncloud/core/issues/40777 diff --git a/changelog/unreleased/40793 b/changelog/unreleased/40793 new file mode 100644 index 000000000000..24fbde85db32 --- /dev/null +++ b/changelog/unreleased/40793 @@ -0,0 +1,7 @@ +Bugfix: Always return an int for the Symfony Command execute method + +Some occ commands could return an invalid exit status when executed. +This has been corrected. occ commands will now always return an integer +exit status. Zero (0) is success, any other value indicates a problem. + +https://github.com/owncloud/core/pull/40793 diff --git a/changelog/unreleased/40794 b/changelog/unreleased/40794 new file mode 100644 index 000000000000..1f5dd2c25e4a --- /dev/null +++ b/changelog/unreleased/40794 @@ -0,0 +1,9 @@ +Bugfix: Exit with success when signing-key has been set + +The "occ security:sign-key:create" command exited with status 1 even when the +signing key was successfully created. This has been corrected. The command +now exits with status zero (0) when the command succeeded. + +For all occ commands, zero (0) is success, any other value indicates a problem. + +https://github.com/owncloud/core/pull/40794 diff --git a/changelog/unreleased/40796 b/changelog/unreleased/40796 new file mode 100644 index 000000000000..f82c64b6f420 --- /dev/null +++ b/changelog/unreleased/40796 @@ -0,0 +1,7 @@ +Enhancement: Add commands to handle the trusted servers from command line + +New occ commands have been added to handle the trusted servers for federation +from command line. These commands will allow the admin to add list and remove +trusted servers + +https://github.com/owncloud/core/pull/40796 diff --git a/changelog/unreleased/40800 b/changelog/unreleased/40800 new file mode 100644 index 000000000000..9592547f4426 --- /dev/null +++ b/changelog/unreleased/40800 @@ -0,0 +1,7 @@ +Bugfix: Fix query used to delete thumbnails + +Fixed query that detects unused thumbnails to prevent unnecessary +deletes and potential recreations. + +https://github.com/owncloud/core/issues/40800 +https://github.com/owncloud/core/pull/40801 diff --git a/changelog/unreleased/40804 b/changelog/unreleased/40804 new file mode 100644 index 000000000000..55cdd1da7eb3 --- /dev/null +++ b/changelog/unreleased/40804 @@ -0,0 +1,5 @@ +Change: fix name length check on system tag creation + +A system tag with a too long name results in potentially inaccessible data. + +https://github.com/owncloud/core/pull/40804 \ No newline at end of file diff --git a/changelog/unreleased/40815 b/changelog/unreleased/40815 new file mode 100644 index 000000000000..87755db82891 --- /dev/null +++ b/changelog/unreleased/40815 @@ -0,0 +1,9 @@ +Bugfix: Always use json for federation post and get to exchange tokens + +After update of guzzle, it was no longer possible to request format of response to be json when adding in query parameter. One of OCSAuthAPIController fed instances was receiving requests without a hint that JSON needs to be used, and returned XML. On the other hand, OCSAuthAPIController expects only JSON for exchange, and thus failed to parse the message. +Now the exchange is correctly done. + +WARNING: the patch/fix needs to be applied on all federated severs that are not yet "paired" and have the issue with guzzle library. Otherwise pairing will not work. + +https://github.com/owncloud/core/pull/40815 +https://github.com/owncloud/enterprise/issues/5676 diff --git a/changelog/unreleased/40822 b/changelog/unreleased/40822 new file mode 100644 index 000000000000..2d9476f944a3 --- /dev/null +++ b/changelog/unreleased/40822 @@ -0,0 +1,6 @@ +Bugfix: Rare undefined variable error when using a Google Drive mount + +There can be the rare case that deleting a file from a Google Drive mount can throw an undefined variable error. Though the process completes without further issues, no errors should be thrown. This fix initializes the variables for these cases properly making the error go away. + +https://github.com/owncloud/core/pull/40822 +https://github.com/owncloud/core/issues/40802 diff --git a/changelog/unreleased/40830 b/changelog/unreleased/40830 new file mode 100644 index 000000000000..09966a5cea67 --- /dev/null +++ b/changelog/unreleased/40830 @@ -0,0 +1,9 @@ +Enhancement: Enforce 2-factor authentication + +2-factor authentication can be enforced now. The feature requires at least +an app implementing the 2-factor, otherwise no enforcement will be done. +If the 2-factor authentication is enforced, all users will be required to +use a 2-factor authentication app. Some specific groups selected by the admin +can be excluded to let those users bypass the 2-factor authentication. + +https://github.com/owncloud/core/pull/40830 diff --git a/changelog/unreleased/40832 b/changelog/unreleased/40832 new file mode 100644 index 000000000000..d0b0f98f4742 --- /dev/null +++ b/changelog/unreleased/40832 @@ -0,0 +1,12 @@ +Bugfix: Explicitly set open mode in the checksum wrapper + +Uploading files to some external storages through the desktop client +was causing issues due to the checksum wrapper. We're using additional +wrappers and the mode wasn't being detected correctly in some cases. +Using the right mode in the checksum wrapper was required in order to +decide whether we should discard the final checksum or not; in this case, +the checksum was being discarded, so it was causing a checksum mismatch. + +Now the open mode in the checksum wrapper is set explicitly. + +https://github.com/owncloud/core/pull/40832 diff --git a/changelog/unreleased/40841 b/changelog/unreleased/40841 new file mode 100644 index 000000000000..3d8a8ca108e4 --- /dev/null +++ b/changelog/unreleased/40841 @@ -0,0 +1,5 @@ +Bugfix: Automatically disable online updater for enterprise + +Online updater is not recommended for Enterprise installations and is now automatically disabled in such cases. + +https://github.com/owncloud/core/pull/40841 diff --git a/changelog/unreleased/40844 b/changelog/unreleased/40844 new file mode 100644 index 000000000000..fea859b4a8d0 --- /dev/null +++ b/changelog/unreleased/40844 @@ -0,0 +1,5 @@ +Bugfix: verbose command output + +Verbose command output of the background:queue:execute is now displayed. + +https://github.com/owncloud/core/pull/40844 diff --git a/changelog/unreleased/40847 b/changelog/unreleased/40847 new file mode 100644 index 000000000000..c41ba76132da --- /dev/null +++ b/changelog/unreleased/40847 @@ -0,0 +1,6 @@ +Bugfix: Versions expire job does not error with federated shares + +Versions expire job does not error with federated shares when versioning meta- +data is enabled. + +https://github.com/owncloud/core/pull/40847 diff --git a/changelog/unreleased/40856 b/changelog/unreleased/40856 new file mode 100644 index 000000000000..abba7cae6050 --- /dev/null +++ b/changelog/unreleased/40856 @@ -0,0 +1,6 @@ +Bugfix: Request header can hold an empty string if not set + +Due to Apache rewrite rules originally not existing headers can hold an empty +string. + +https://github.com/owncloud/core/pull/40856 diff --git a/changelog/unreleased/40859 b/changelog/unreleased/40859 new file mode 100644 index 000000000000..f392a0bb4b19 --- /dev/null +++ b/changelog/unreleased/40859 @@ -0,0 +1,6 @@ +Enhancement: Improve the performance of the occ files:remove-storage command + +The "--show-candidates" option of the "occ files:remove-storage" command +will take less time + +https://github.com/owncloud/core/pull/40859 diff --git a/changelog/unreleased/40864 b/changelog/unreleased/40864 new file mode 100644 index 000000000000..9b105beeba8a --- /dev/null +++ b/changelog/unreleased/40864 @@ -0,0 +1,5 @@ +Bugfix: Skip share_folder for guest users + +In https://github.com/owncloud/core/pull/40378 we've fixed the case of (not) moving the share target when the backend storage becomes temporary unavailable but we had the collateral effect that guests did not see anymore their received shares as we were forcing the creation of the target which failed for them as their storage is read-only. We now skip the share_folder config.php option for guests and default to root. + +https://github.com/owncloud/core/pull/40864 diff --git a/changelog/unreleased/PHPdependencies20230404onward b/changelog/unreleased/PHPdependencies20230404onward index 14c81532d978..904f69adbdcc 100644 --- a/changelog/unreleased/PHPdependencies20230404onward +++ b/changelog/unreleased/PHPdependencies20230404onward @@ -1,12 +1,33 @@ Change: Update PHP dependencies The following have been updated: -- guzzlehttp/guzzle (7.5.0 to 7.5.1) +- doctrine/deprecations (1.0.0 to 1.1.1) +- egulias/email-validator (3.2.5 to 3.2.6) +- guzzlehttp/guzzle (7.5.0 to 7.7.0) +- owncloud/tarstreamer (2.0.0 to 2.1.0) +- pear/pear-core-minimal (1.10.11 to 1.10.13) +- phpseclib/phpseclib (3.0.19 to 3.0.21) - punic/punic (3.8.0 to 3.8.1) +- sabre/http (5.1.6 to 5.1.7) +- sabre/uri (2.3.2 to 2.3.3) +- sabre/xml (2.2.5 to 2.2.6) The following have been updated in apps/files_external/3rdparty: - google/apiclient (2.13.1 to 2.13.2) +- firebase/php-jwt (v6.4.0 to v6.6.0) https://github.com/owncloud/core/pull/40724 https://github.com/owncloud/core/pull/40731 https://github.com/owncloud/core/pull/40742 +https://github.com/owncloud/core/pull/40753 +https://github.com/owncloud/core/pull/40789 +https://github.com/owncloud/core/pull/40806 +https://github.com/owncloud/core/pull/40819 +https://github.com/owncloud/core/pull/40825 +https://github.com/owncloud/core/pull/40833 +https://github.com/owncloud/core/pull/40838 +https://github.com/owncloud/core/pull/40839 +https://github.com/owncloud/core/pull/40849 +https://github.com/owncloud/core/pull/40853 +https://github.com/owncloud/core/pull/40854 +https://github.com/owncloud/core/pull/40867 diff --git a/composer.json b/composer.json index f69c8dc4b726..1435a6ae7c9f 100644 --- a/composer.json +++ b/composer.json @@ -38,28 +38,28 @@ "phpseclib/phpseclib": "^3.0", "opis/closure": "^3.6", "bantu/ini-get-wrapper": "v1.0.1", - "punic/punic": "^3.7", + "punic/punic": "^3.8", "pear/archive_tar": "1.4.14", - "symfony/console": "^4.4", - "symfony/event-dispatcher": "^4.4", - "symfony/routing": "^4.4", - "symfony/process": "^4.4", + "symfony/console": "^5.4", + "symfony/event-dispatcher": "^5.4", + "symfony/routing": "^5.4", + "symfony/process": "^5.4", "pimple/pimple": "^3.5", "nikic/php-parser": "^4.15", "icewind/streams": "0.7.7", "swiftmailer/swiftmailer": "^6.3", - "guzzlehttp/guzzle": "^7.5", + "guzzlehttp/guzzle": "^7.7", "league/flysystem": "^1.1", "pear/pear-core-minimal": "^v1.10", "interfasys/lognormalizer": "^v1.0", - "owncloud/tarstreamer": "v2.0.0", + "owncloud/tarstreamer": "v2.1.0", "christophwurst/id3parser": "^0.1.4", "sabre/dav": "^4.4", "sabre/http": "^5.1", "deepdiver/zipstreamer": "^2.0", - "symfony/translation": "^4.4", + "symfony/translation": "^5.4", "laminas/laminas-inputfilter": "^2.21", - "laminas/laminas-servicemanager": "^3.16", + "laminas/laminas-servicemanager": "^3.17", "laminas/laminas-validator": "^2.25", "composer/semver": "^3.3", "ext-json": "*", diff --git a/composer.lock b/composer.lock index 9e0a018bd13a..2bfd8e5ea1a0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ac1176a1aa200571a82be83107e29ddb", + "content-hash": "2ad9c3c64ac9fe99c4067fdbd461e151", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -487,25 +487,29 @@ }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -524,9 +528,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2023-06-03T09:27:29+00:00" }, { "name": "doctrine/event-manager", @@ -700,16 +704,16 @@ }, { "name": "egulias/email-validator", - "version": "3.2.5", + "version": "3.2.6", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "b531a2311709443320c786feb4519cfaf94af796" + "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b531a2311709443320c786feb4519cfaf94af796", - "reference": "b531a2311709443320c786feb4519cfaf94af796", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", + "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", "shasum": "" }, "require": { @@ -755,7 +759,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/3.2.5" + "source": "https://github.com/egulias/EmailValidator/tree/3.2.6" }, "funding": [ { @@ -763,25 +767,25 @@ "type": "github" } ], - "time": "2023-01-02T17:26:14+00:00" + "time": "2023-06-01T07:04:22+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.5.1", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9" + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b964ca597e86b752cd994f27293e9fa6b6a95ed9", - "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", @@ -793,7 +797,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.29 || ^9.5.23", "psr/log": "^1.1 || ^2.0 || ^3.0" }, @@ -807,9 +812,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "7.5-dev" } }, "autoload": { @@ -875,7 +877,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.5.1" + "source": "https://github.com/guzzle/guzzle/tree/7.7.0" }, "funding": [ { @@ -891,38 +893,37 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:30:08+00:00" + "time": "2023-05-21T14:04:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -959,7 +960,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/2.0.0" }, "funding": [ { @@ -975,7 +976,7 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2023-05-21T13:50:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -1738,16 +1739,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.4", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -1788,9 +1789,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-03-05T19:49:14+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "opis/closure", @@ -1859,27 +1860,33 @@ }, { "name": "owncloud/tarstreamer", - "version": "2.0.0", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/owncloud/TarStreamer.git", - "reference": "ad48505d1ab54a8e94e6b1cc5297bbed72e956de" + "reference": "163052d7a076fd3dd54d4f50e1ff2705b72604db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/owncloud/TarStreamer/zipball/ad48505d1ab54a8e94e6b1cc5297bbed72e956de", - "reference": "ad48505d1ab54a8e94e6b1cc5297bbed72e956de", + "url": "https://api.github.com/repos/owncloud/TarStreamer/zipball/163052d7a076fd3dd54d4f50e1ff2705b72604db", + "reference": "163052d7a076fd3dd54d4f50e1ff2705b72604db", "shasum": "" }, "require": { "php": ">=7.1" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.5", "pear/archive_tar": "~1.4", - "pear/pear-core-minimal": "v1.10.10", - "phpunit/phpunit": "^7.5" + "pear/pear-core-minimal": "v1.10.13", + "phpunit/phpunit": "^7.5|^8.5|^9.6" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false + } + }, "autoload": { "psr-4": { "ownCloud\\TarStreamer\\": "src/" @@ -1899,9 +1906,9 @@ ], "support": { "issues": "https://github.com/owncloud/TarStreamer/issues", - "source": "https://github.com/owncloud/TarStreamer/tree/master" + "source": "https://github.com/owncloud/TarStreamer/tree/v2.1.0" }, - "time": "2020-01-08T09:55:35+00:00" + "time": "2023-06-16T08:01:55+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2153,16 +2160,16 @@ }, { "name": "pear/pear-core-minimal", - "version": "v1.10.11", + "version": "v1.10.13", "source": { "type": "git", "url": "https://github.com/pear/pear-core-minimal.git", - "reference": "68d0d32ada737153b7e93b8d3c710ebe70ac867d" + "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/68d0d32ada737153b7e93b8d3c710ebe70ac867d", - "reference": "68d0d32ada737153b7e93b8d3c710ebe70ac867d", + "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/aed862e95fd286c53cc546734868dc38ff4b5b1d", + "reference": "aed862e95fd286c53cc546734868dc38ff4b5b1d", "shasum": "" }, "require": { @@ -2197,7 +2204,7 @@ "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", "source": "https://github.com/pear/pear-core-minimal" }, - "time": "2021-08-10T22:31:03+00:00" + "time": "2023-04-19T19:15:47+00:00" }, { "name": "pear/pear_exception", @@ -2260,16 +2267,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.19", + "version": "3.0.21", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95" + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1", + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1", "shasum": "" }, "require": { @@ -2350,7 +2357,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.19" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.21" }, "funding": [ { @@ -2366,7 +2373,7 @@ "type": "tidelift" } ], - "time": "2023-03-05T17:13:09+00:00" + "time": "2023-07-09T15:24:48+00:00" }, { "name": "pimple/pimple", @@ -2469,6 +2476,56 @@ }, "time": "2021-11-05T16:50:12+00:00" }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, { "name": "psr/http-client", "version": "1.0.2", @@ -2964,16 +3021,16 @@ }, { "name": "sabre/http", - "version": "5.1.6", + "version": "5.1.7", "source": { "type": "git", "url": "https://github.com/sabre-io/http.git", - "reference": "9976ac34ced206bd6579b7b37b401de9fac98dae" + "reference": "b6fa04f42f49156eaab3fb890c79f4c43a9559b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/http/zipball/9976ac34ced206bd6579b7b37b401de9fac98dae", - "reference": "9976ac34ced206bd6579b7b37b401de9fac98dae", + "url": "https://api.github.com/repos/sabre-io/http/zipball/b6fa04f42f49156eaab3fb890c79f4c43a9559b7", + "reference": "b6fa04f42f49156eaab3fb890c79f4c43a9559b7", "shasum": "" }, "require": { @@ -3023,29 +3080,32 @@ "issues": "https://github.com/sabre-io/http/issues", "source": "https://github.com/fruux/sabre-http" }, - "time": "2022-07-15T14:51:14+00:00" + "time": "2023-06-26T10:13:00+00:00" }, { "name": "sabre/uri", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/sabre-io/uri.git", - "reference": "eceb4a1b8b680b45e215574222d6ca00be541970" + "reference": "7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/uri/zipball/eceb4a1b8b680b45e215574222d6ca00be541970", - "reference": "eceb4a1b8b680b45e215574222d6ca00be541970", + "url": "https://api.github.com/repos/sabre-io/uri/zipball/7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b", + "reference": "7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.9", - "phpstan/phpstan": "^1.8", - "phpunit/phpunit": "^9.0" + "friendsofphp/php-cs-fixer": "^3.17", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "^9.6" }, "type": "library", "autoload": { @@ -3080,7 +3140,7 @@ "issues": "https://github.com/sabre-io/uri/issues", "source": "https://github.com/fruux/sabre-uri" }, - "time": "2022-09-19T11:58:52+00:00" + "time": "2023-06-09T06:54:04+00:00" }, { "name": "sabre/vobject", @@ -3188,16 +3248,16 @@ }, { "name": "sabre/xml", - "version": "2.2.5", + "version": "2.2.6", "source": { "type": "git", "url": "https://github.com/sabre-io/xml.git", - "reference": "a6af111850e7536d200d9637c34885cd3c77a86c" + "reference": "9cde7cdab1e50893cc83b037b40cd47bfde42a2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/xml/zipball/a6af111850e7536d200d9637c34885cd3c77a86c", - "reference": "a6af111850e7536d200d9637c34885cd3c77a86c", + "url": "https://api.github.com/repos/sabre-io/xml/zipball/9cde7cdab1e50893cc83b037b40cd47bfde42a2b", + "reference": "9cde7cdab1e50893cc83b037b40cd47bfde42a2b", "shasum": "" }, "require": { @@ -3253,7 +3313,7 @@ "issues": "https://github.com/sabre-io/xml/issues", "source": "https://github.com/fruux/sabre-xml" }, - "time": "2021-11-04T06:37:27+00:00" + "time": "2023-06-28T12:56:05+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -3333,43 +3393,46 @@ }, { "name": "symfony/console", - "version": "v4.4.49", + "version": "v5.4.24", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9" + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", - "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2" + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" }, "conflict": { "psr/log": ">=3", - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", - "symfony/process": "<3.3" + "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/log": "^1|^2", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { "psr/log": "For using the console logger", @@ -3402,8 +3465,14 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v4.4.49" + "source": "https://github.com/symfony/console/tree/v5.4.24" }, "funding": [ { @@ -3419,7 +3488,7 @@ "type": "tidelift" } ], - "time": "2022-11-05T17:10:16+00:00" + "time": "2023-05-26T05:13:16+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3490,39 +3559,40 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.4.44", + "version": "v5.4.22", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "1e866e9e5c1b22168e0ce5f0b467f19bba61266a" + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1e866e9e5c1b22168e0ce5f0b467f19bba61266a", - "reference": "1e866e9e5c1b22168e0ce5f0b467f19bba61266a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/event-dispatcher-contracts": "^1.1", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/error-handler": "~3.4|~4.4", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" }, "suggest": { "symfony/dependency-injection": "", @@ -3554,7 +3624,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.44" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" }, "funding": [ { @@ -3570,33 +3640,33 @@ "type": "tidelift" } ], - "time": "2022-07-20T09:59:04+00:00" + "time": "2023-03-17T11:31:58+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.13", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "1d5cd762abaa6b2a4169d3e77610193a7157129e" + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/1d5cd762abaa6b2a4169d3e77610193a7157129e", - "reference": "1d5cd762abaa6b2a4169d3e77610193a7157129e", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" }, "suggest": { - "psr/event-dispatcher": "", "symfony/event-dispatcher-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3633,7 +3703,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.13" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" }, "funding": [ { @@ -3649,7 +3719,89 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:41:36+00:00" + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-iconv", @@ -3734,6 +3886,87 @@ ], "time": "2022-11-03T14:55:06+00:00" }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, { "name": "symfony/polyfill-intl-idn", "version": "v1.27.0", @@ -4228,20 +4461,20 @@ }, { "name": "symfony/process", - "version": "v4.4.44", + "version": "v5.4.24", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2" + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", - "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", + "url": "https://api.github.com/repos/symfony/process/zipball/e3c46cc5689c8782944274bb30702106ecbe3b64", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", @@ -4270,7 +4503,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v4.4.44" + "source": "https://github.com/symfony/process/tree/v5.4.24" }, "funding": [ { @@ -4286,42 +4519,43 @@ "type": "tidelift" } ], - "time": "2022-06-27T13:16:42+00:00" + "time": "2023-05-17T11:26:05+00:00" }, { "name": "symfony/routing", - "version": "v4.4.44", + "version": "v5.4.25", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "f7751fd8b60a07f3f349947a309b5bdfce22d6ae" + "reference": "56bfc1394f7011303eb2e22724f9b422d3f14649" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/f7751fd8b60a07f3f349947a309b5bdfce22d6ae", - "reference": "f7751fd8b60a07f3f349947a309b5bdfce22d6ae", + "url": "https://api.github.com/repos/symfony/routing/zipball/56bfc1394f7011303eb2e22724f9b422d3f14649", + "reference": "56bfc1394f7011303eb2e22724f9b422d3f14649", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/config": "<4.2", - "symfony/dependency-injection": "<3.4", - "symfony/yaml": "<3.4" + "doctrine/annotations": "<1.12", + "symfony/config": "<5.3", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4", + "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^4.2|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", - "symfony/yaml": "^3.4|^4.0|^5.0" + "symfony/config": "^5.3|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0" }, "suggest": { - "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", @@ -4359,7 +4593,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v4.4.44" + "source": "https://github.com/symfony/routing/tree/v5.4.25" }, "funding": [ { @@ -4375,7 +4609,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T09:59:04+00:00" + "time": "2023-06-05T14:18:47+00:00" }, { "name": "symfony/service-contracts", @@ -4460,45 +4694,136 @@ ], "time": "2022-05-30T19:17:29+00:00" }, + { + "name": "symfony/string", + "version": "v5.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-14T06:11:53+00:00" + }, { "name": "symfony/translation", - "version": "v4.4.47", + "version": "v5.4.24", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "45036b1d53accc48fe9bab71ccd86d57eba0dd94" + "reference": "de237e59c5833422342be67402d487fbf50334ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/45036b1d53accc48fe9bab71ccd86d57eba0dd94", - "reference": "45036b1d53accc48fe9bab71ccd86d57eba0dd94", + "url": "https://api.github.com/repos/symfony/translation/zipball/de237e59c5833422342be67402d487fbf50334ff", + "reference": "de237e59c5833422342be67402d487fbf50334ff", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^1.1.6|^2" + "symfony/translation-contracts": "^2.3" }, "conflict": { - "symfony/config": "<3.4", - "symfony/dependency-injection": "<3.4", - "symfony/http-kernel": "<4.4", - "symfony/yaml": "<3.4" + "symfony/config": "<4.4", + "symfony/console": "<5.3", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" }, "provide": { - "symfony/translation-implementation": "1.0|2.0" + "symfony/translation-implementation": "2.3" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/console": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/finder": "~2.8|~3.0|~4.0|^5.0", - "symfony/http-kernel": "^4.4", - "symfony/intl": "^3.4|^4.0|^5.0", - "symfony/service-contracts": "^1.1.2|^2", - "symfony/yaml": "^3.4|^4.0|^5.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.0|^6.0", + "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" }, "suggest": { "psr/log-implementation": "To use logging capability in translator", @@ -4507,6 +4832,9 @@ }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { "Symfony\\Component\\Translation\\": "" }, @@ -4531,7 +4859,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v4.4.47" + "source": "https://github.com/symfony/translation/tree/v5.4.24" }, "funding": [ { @@ -4547,7 +4875,7 @@ "type": "tidelift" } ], - "time": "2022-10-03T15:15:11+00:00" + "time": "2023-05-19T12:34:17+00:00" }, { "name": "symfony/translation-contracts", @@ -5297,16 +5625,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.7", + "version": "9.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2" + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", - "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", "shasum": "" }, "require": { @@ -5380,7 +5708,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.7" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" }, "funding": [ { @@ -5396,7 +5724,7 @@ "type": "tidelift" } ], - "time": "2023-04-14T08:58:40+00:00" + "time": "2023-07-10T04:04:23+00:00" }, { "name": "roave/security-advisories", @@ -5404,19 +5732,20 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "6b077f852cc72d9c585dbf1241746b5af08ea1d4" + "reference": "bcc78ca7e0e2bf8f2f8afd4eb9aabb988d593c21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6b077f852cc72d9c585dbf1241746b5af08ea1d4", - "reference": "6b077f852cc72d9c585dbf1241746b5af08ea1d4", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/bcc78ca7e0e2bf8f2f8afd4eb9aabb988d593c21", + "reference": "bcc78ca7e0e2bf8f2f8afd4eb9aabb988d593c21", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", - "admidio/admidio": "<4.1.9", + "admidio/admidio": "<4.2.9", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "aheinze/cockpit": "<=2.2.1", + "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "akaunting/akaunting": "<2.1.13", "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", "alextselegidis/easyappointments": "<1.5", @@ -5427,17 +5756,21 @@ "amphp/http-client": ">=4,<4.4", "anchorcms/anchor-cms": "<=0.12.7", "andreapollastri/cipi": "<=3.1.15", - "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<=1.0.1|>=2,<=2.2.4", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", "apereo/phpcas": "<1.6", "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6|>=2.6,<2.7.10|>=3,<3.0.12|>=3.1,<3.1.3", "appwrite/server-ce": "<=1.2.1", "arc/web": "<3", "area17/twill": "<1.2.5|>=2,<2.5.3", + "artesaos/seotools": "<0.17.2", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "athlon1600/php-proxy": "<=5.1", + "athlon1600/php-proxy-app": "<=3", "automad/automad": "<1.8", "awesome-support/awesome-support": "<=6.0.7", "aws/aws-sdk-php": ">=3,<3.2.1", - "backdrop/backdrop": "<=1.23", + "azuracast/azuracast": "<0.18.3", + "backdrop/backdrop": "<1.24.2", "badaso/core": "<2.7", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", @@ -5446,8 +5779,8 @@ "barzahlen/barzahlen-php": "<2.0.1", "baserproject/basercms": "<4.7.5", "bassjobsen/bootstrap-3-typeahead": ">4.0.2", - "bigfork/silverstripe-form-capture": ">=3,<=3.1", - "billz/raspap-webgui": "<=2.6.6", + "bigfork/silverstripe-form-capture": ">=3,<3.1.1", + "billz/raspap-webgui": "<2.8.9", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", "bmarshall511/wordpress_zero_spam": "<5.2.13", "bolt/bolt": "<3.7.2", @@ -5472,19 +5805,20 @@ "cockpit-hq/cockpit": "<2.4.1", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", - "codeigniter4/framework": "<4.2.11", + "codeigniter4/framework": "<4.3.5", "codeigniter4/shield": "<1-beta.4|= 1.0.0-beta", "codiad/codiad": "<=2.8.4", "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", - "concrete5/concrete5": "<=9.1.3|>= 9.0.0RC1, < 9.1.3", + "concrete5/concrete5": "<9.2|>= 9.0.0RC1, < 9.1.3", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/core-bundle": "<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", "contao/managed-edition": "<=1.5", - "craftcms/cms": "<3.7.64|>= 4.0.0-RC1, < 4.3.7|>= 4.0.0-RC1, < 4.2.1", + "cosenary/instagram": "<=2.3", + "craftcms/cms": "<=4.4.9|>= 4.0.0-RC1, < 4.4.12|>= 4.0.0-RC1, <= 4.4.5|>= 4.0.0-RC1, <= 4.4.6|>= 4.0.0-RC1, < 4.4.6|>= 4.0.0-RC1, < 4.3.7|>= 4.0.0-RC1, < 4.2.1", "croogo/croogo": "<3.0.7", "cuyz/valinor": "<0.12", "czproject/git-php": "<4.0.3", @@ -5492,8 +5826,10 @@ "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3-beta", "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "desperado/xml-bundle": "<=0.1.7", "directmailteam/direct-mail": "<5.2.4", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", @@ -5504,9 +5840,9 @@ "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<16|>=16.0.1,<16.0.3|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dolibarr/dolibarr": "<17.0.1|= 12.0.5|>= 3.3.beta1, < 13.0.2", "dompdf/dompdf": "<2.0.2|= 2.0.2", - "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "drupal/core": ">=7,<7.96|>=8,<9.4.14|>=9.5,<9.5.8|>=10,<10.0.8", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", @@ -5556,42 +5892,46 @@ "fooman/tcpdf": "<6.2.22", "forkcms/forkcms": "<5.11.1", "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<10.8.2", + "francoisjacquet/rosariosis": "<11", "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "froala/wysiwyg-editor": "<3.2.7", - "froxlor/froxlor": "<2.0.14", + "froxlor/froxlor": "<2.1", "fuel/core": "<1.8.1", - "funadmin/funadmin": "<=3.2", + "funadmin/funadmin": "<=3.2|>=3.3.2,<=3.3.3", "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", - "getgrav/grav": "<1.7.34", + "getgrav/grav": "<1.7.42", "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1", "getkirby/panel": "<2.5.14", "getkirby/starterkit": "<=3.7.0.2", "gilacms/gila": "<=1.11.4", "globalpayments/php-sdk": "<2", + "gogentooss/samlbase": "<1.2.7", "google/protobuf": "<3.15", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", "grumpydictator/firefly-iii": "<6", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", - "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", "harvesthq/chosen": "<1.8.7", "helloxz/imgurl": "= 2.31|<=2.31", + "hhxsv5/laravel-s": "<3.7.36", "hillelcoren/invoice-ninja": "<5.3.35", "himiklab/yii2-jqgrid-widget": "<1.0.8", "hjue/justwriting": "<=1", "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", "hyn/multi-tenant": ">=5.6,<5.7.2", "ibexa/admin-ui": ">=4.2,<4.2.3", "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", "ibexa/post-install": "<=1.0.4", + "ibexa/user": ">=4,<4.4.3", "icecoder/icecoder": "<=8.1", "idno/known": "<=1.3.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", @@ -5601,6 +5941,7 @@ "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "impresscms/impresscms": "<=1.4.3", "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", + "in2code/ipandlanguageredirect": "<5.1.2", "in2code/lux": "<17.6.1|>=18,<24.0.2", "innologi/typo3-appointments": "<2.0.6", "intelliants/subrion": "<=4.2.1", @@ -5620,24 +5961,26 @@ "kazist/phpwhois": "<=4.2.6", "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", + "khodakhah/nodcms": "<=3", "kimai/kimai": "<1.1", - "kitodo/presentation": "<3.1.2", + "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", "klaviyo/magento2-extension": ">=1,<3", "knplabs/knp-snappy": "<1.4.2", "krayin/laravel-crm": "<1.2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-diactoros": "<2.18.1|>=2.24,<2.24.2|>=2.25,<2.25.2|= 2.23.0|= 2.22.0|= 2.21.0|= 2.20.0|= 2.19.0", "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", "laravel/fortify": "<1.11.1", "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", "latte/latte": "<2.10.8", - "lavalite/cms": "<=5.8", + "lavalite/cms": "= 9.0.0|<=9", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", "league/flysystem": "<1.1.4|>=2,<2.1.1", + "league/oauth2-server": ">=8.3.2,<8.5.3", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", "librenms/librenms": "<22.10", "liftkit/database": "<2.13.2", @@ -5663,14 +6006,15 @@ "melisplatform/melis-front": "<5.0.1", "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", "mgallegos/laravel-jqgrid": "<=1.3", - "microweber/microweber": "<1.3.3", + "microweber/microweber": "<=1.3.4", "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", "mobiledetect/mobiledetectlib": "<2.8.32", "modx/revolution": "<= 2.8.3-pl|<2.8", "mojo42/jirafeau": "<4.4", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.0.7|>=4.1-beta,<4.1.2|= 3.11", + "moodle/moodle": "<4.2-rc.2|= 4.2.0|= 3.11", + "movim/moxl": ">=0.8,<=0.10", "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", "neoan3-apps/template": "<1.1.1", @@ -5682,10 +6026,11 @@ "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nilsteampassnet/teampass": "<3.0.3", + "nilsteampassnet/teampass": "<3.0.10", "notrinos/notrinos-erp": "<=0.7", "noumo/easyii": "<=0.9", "nukeviet/nukeviet": "<4.5.2", + "nyholm/psr7": "<1.6.1", "nystudio107/craft-seomatic": "<3.4.12", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": "<1.1.2", @@ -5699,6 +6044,7 @@ "opencart/opencart": "<=3.0.3.7", "openid/php-openid": "<2.3", "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", + "opensource-workshop/connect-cms": "<1.7.2|>=2,<2.3.2", "orchid/platform": ">=9,<9.4.4", "oro/commerce": ">=4.1,<5.0.6", "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", @@ -5712,10 +6058,12 @@ "paypal/merchant-sdk-php": "<3.12", "pear/archive_tar": "<1.4.14", "pear/crypt_gpg": "<1.6.7", + "pear/pear": "<=1.10.1", "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", "phanan/koel": "<5.1.4", "php-mod/curl": "<2.3.2", + "phpbb/phpbb": ">=3.2,<3.2.10|>=3.3,<3.3.1", "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", @@ -5724,24 +6072,26 @@ "phpoffice/phpexcel": "<1.8", "phpoffice/phpspreadsheet": "<1.16", "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.19", - "phpservermon/phpservermon": "<=3.5.2", + "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.2.5", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pi/pi": "<=2.5", + "pimcore/customer-management-framework-bundle": "<3.4.1", "pimcore/data-hub": "<1.2.4", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<10.5.20", + "pimcore/pimcore": "<10.5.23", "pixelfed/pixelfed": "<=0.11.4", "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<4.12.5|>= 4.0.0-BETA5, < 4.4.2", + "pocketmine/pocketmine-mp": "<4.20.5|>=4.21,<4.21.1|< 4.18.0-ALPHA2|>= 4.0.0-BETA5, < 4.4.2", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": "<8.0.1", + "prestashop/prestashop": "<8.0.4", "prestashop/productcomments": "<5.0.2", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", @@ -5757,7 +6107,8 @@ "pyrocms/pyrocms": "<=3.9.1", "rainlab/debugbar-plugin": "<3.1", "rankmath/seo-by-rank-math": "<=1.0.95", - "react/http": ">=0.7,<1.7", + "rap2hpoutre/laravel-log-viewer": "<0.13", + "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", "remdex/livehelperchat": "<3.99", "rmccue/requests": ">=1.6,<1.8", @@ -5767,23 +6118,24 @@ "s-cart/core": "<6.9", "s-cart/s-cart": "<6.9", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", - "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "sabre/dav": "<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.4.18", - "shopware/platform": "<=6.4.18", + "sheng/yiicms": "<=1.2", + "shopware/core": "<=6.4.20", + "shopware/platform": "<=6.4.20", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.14", + "shopware/shopware": "<=5.7.17", "shopware/storefront": "<=6.4.8.1", "shopxo/shopxo": "<2.2.6", "showdoc/showdoc": "<2.10.4", - "silverstripe/admin": ">=1,<1.11.3", + "silverstripe/admin": "<1.12.7", "silverstripe/assets": ">=1,<1.11.1", "silverstripe/cms": "<4.11.3", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.11.14", + "silverstripe/framework": "<4.12.5", "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1", "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", @@ -5801,6 +6153,7 @@ "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", "simplito/elliptic-php": "<1.0.6", "sitegeist/fluid-components": "<3.5", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", "slim/slim": "<2.6", "smarty/smarty": "<3.1.48|>=4,<4.3.1", "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", @@ -5811,9 +6164,10 @@ "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<22.2.3", - "statamic/cms": "<3.2.39|>=3.3,<3.3.2", + "statamic/cms": "<4.10", "stormpath/sdk": ">=0,<9.9.99", - "studio-42/elfinder": "<2.1.59", + "studio-42/elfinder": "<2.1.62", + "subhh/libconnect": "<7.0.8|>=8,<8.1", "subrion/cms": "<=4.2.1", "sukohi/surpass": "<1", "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", @@ -5862,13 +6216,14 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tastyigniter/tastyigniter": "<3.3", + "tcg/voyager": "<=1.4", "tecnickcom/tcpdf": "<6.2.22", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<=5.1.7", - "thorsten/phpmyfaq": "<3.1.12", + "thorsten/phpmyfaq": "<3.2-beta.2", "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", "tinymighty/wiki-seo": "<1.2.2", "titon/framework": ">=0,<9.9.99", @@ -5876,6 +6231,7 @@ "topthink/framework": "<6.0.14", "topthink/think": "<=6.1.1", "topthink/thinkphp": "<=3.2.3", + "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", "tribalsystems/zenario": "<=9.3.57595", "truckersmp/phpwhois": "<=4.3.1", "ttskch/pagination-service-provider": "<1", @@ -5900,21 +6256,24 @@ "vova07/yii2-fileapi-widget": "<0.1.9", "vrana/adminer": "<4.8.1", "wallabag/tcpdf": "<6.2.22", - "wallabag/wallabag": "<2.5.4", + "wallabag/wallabag": "<=2.5.4", "wanglelecc/laracms": "<=1.0.3", "web-auth/webauthn-framework": ">=3.3,<3.3.4", "webbuilders-group/silverstripe-kapost-bridge": "<0.4", "webcoast/deferred-image-processing": "<1.0.2", + "webklex/laravel-imap": "<5.3", + "webklex/php-imap": "<5.3", "webpa/webpa": "<3.1.2", + "wikibase/wikibase": "<=1.39.3", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", - "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", + "wintercms/winter": "<1.2.3", "woocommerce/woocommerce": "<6.6", "wp-cli/wp-cli": "<2.5", - "wp-graphql/wp-graphql": "<0.3.5", + "wp-graphql/wp-graphql": "<=1.14.5", "wpanel/wpanel4-cms": "<=4.3.1", "wpcloud/wp-stateless": "<3.2", - "wwbn/avideo": "<12.4", + "wwbn/avideo": "<=12.4", "xataface/xataface": "<3", "xpressengine/xpressengine": "<3.0.15", "yeswiki/yeswiki": "<4.1", @@ -5932,6 +6291,7 @@ "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", "yoast-seo-for-typo3/yoast_seo": "<7.2.3", "yourls/yourls": "<=1.8.2", + "zencart/zencart": "<1.5.8", "zendesk/zendesk_api_client_php": "<2.2.11", "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", @@ -5996,7 +6356,7 @@ "type": "tidelift" } ], - "time": "2023-04-17T18:04:34+00:00" + "time": "2023-07-11T01:32:50+00:00" }, { "name": "sebastian/cli-parser", @@ -6298,16 +6658,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -6352,7 +6712,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -6360,7 +6720,7 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", diff --git a/config/config.apps.sample.php b/config/config.apps.sample.php index 515c523789d4..751e7f3d014a 100644 --- a/config/config.apps.sample.php +++ b/config/config.apps.sample.php @@ -493,6 +493,8 @@ * * Possible keys: `wnd.connector.opts.timeout` INTEGER * + * Possible keys: `wnd2.cachewrapper.normalize` BOOL + * * *Note* With WND 2.1.0, key `wnd.storage.testForHiddenMount` is obsolete and has been removed completely. */ @@ -613,6 +615,21 @@ */ 'wnd.connector.opts.timeout' => 20000, // 20 seconds +/** + * Manage UTF-8 Glyph Normalization on macOS + * A glyph is a character like `ñ` as used in the spanish word `señorita` which can be composed by two different byte sequences. + * With https://www.utf8-chartable.de/unicode-utf8-table.pl?number=1024&unicodeinhtml=hex[UTF-8], glyphs can have two valid representations of these sequences in filesystems. + * https://unicode.org/reports/tr15/#Norm_Forms[Normalization] makes it possible to determine whether any two Unicode strings are equivalent. + * The most used normalization forms are NFC and NFD. By default, ownCloud usually normalizes names to NFC. + * With macOS and HFS+ as filesystem, NFD is required. + * When using WND collaborative mount points connecting to macOS with HFS+, or any other filesystem using NFD, probing both forms can be enforced by setting the config variable `wnd2.cachewrapper.normalize` to true. + * This is necessary because if a file accessed via collaborative WND contains NFD characters, WND will not find the file and the WND app will assume user doesn't have access to it. + * As a result, the file will not be shown. + * + * As a mandatory prerequisite, the mount point setting `Compatibility with Mac NFD encoding` must be checked. + */ +'wnd2.cachewrapper.normalize' => false, + /** * App: Workflow / Tagging * diff --git a/config/config.sample.php b/config/config.sample.php index 7bacd0c525e5..fd7d3efe8481 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1512,6 +1512,7 @@ /** * Define a default folder for shared files and folders other than root + * Please note that this setting is skipped for guests and the root folder will be used for such users. */ 'share_folder' => '/', @@ -1542,7 +1543,7 @@ * * NOTE: Lowering this value may lead to unexpected behaviour, and can include data loss. */ -'minimum.supported.desktop.version' => '2.3.3', +'minimum.supported.desktop.version' => '3.2.1', /** * Define the suggested poll interval for clients diff --git a/core/Command/App/CheckCode.php b/core/Command/App/CheckCode.php index a2c28452db5a..50eb4f6feffc 100644 --- a/core/Command/App/CheckCode.php +++ b/core/Command/App/CheckCode.php @@ -78,7 +78,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appId = $input->getArgument('app-id'); $checkList = new EmptyCheck(); diff --git a/core/Command/App/Disable.php b/core/Command/App/Disable.php index dc885f8b1fc5..fbb942ac5b6a 100644 --- a/core/Command/App/Disable.php +++ b/core/Command/App/Disable.php @@ -53,7 +53,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appId = $input->getArgument('app-id'); if ($this->manager->isInstalled($appId)) { try { diff --git a/core/Command/App/Enable.php b/core/Command/App/Enable.php index 144babf4daee..e908c8d008ea 100644 --- a/core/Command/App/Enable.php +++ b/core/Command/App/Enable.php @@ -61,7 +61,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appId = $input->getArgument('app-id'); if (!\OC_App::getAppPath($appId)) { diff --git a/core/Command/App/GetPath.php b/core/Command/App/GetPath.php index 9eea208018bc..e92d00318a20 100644 --- a/core/Command/App/GetPath.php +++ b/core/Command/App/GetPath.php @@ -46,9 +46,9 @@ protected function configure() { * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code + * @return int 0 if everything went fine, or an error code */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $path = \OC_App::getAppPath($appName); if ($path !== false) { diff --git a/core/Command/App/ListApps.php b/core/Command/App/ListApps.php index eb6663e07280..34a414c2f1fe 100644 --- a/core/Command/App/ListApps.php +++ b/core/Command/App/ListApps.php @@ -81,7 +81,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appNameSubString = $input->getArgument('search-pattern'); $minimalView = $input->getOption('minimal'); diff --git a/core/Command/Background/Base.php b/core/Command/Background/Base.php index 825ba2ebdff4..2e67be36c259 100644 --- a/core/Command/Background/Base.php +++ b/core/Command/Background/Base.php @@ -60,14 +60,15 @@ protected function configure() { } /** - * Executing this command will set the background job mode for owncloud. - * The mode to set is specified by the concrete sub class by implementing the - * getMode() function. - * - * @param InputInterface $input - * @param OutputInterface $output - */ - protected function execute(InputInterface $input, OutputInterface $output) { + * Executing this command will set the background job mode for owncloud. + * The mode to set is specified by the concrete subclass by implementing the + * getMode() function. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int { $mode = $this->getMode(); $this->config->setAppValue('core', 'backgroundjobs_mode', $mode); $output->writeln("Set mode for background jobs to '$mode'"); diff --git a/core/Command/Background/Queue/Delete.php b/core/Command/Background/Queue/Delete.php index b4800f4a0532..988c9b36b5c1 100644 --- a/core/Command/Background/Queue/Delete.php +++ b/core/Command/Background/Queue/Delete.php @@ -48,7 +48,7 @@ protected function configure() { * @param OutputInterface $output * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $id = $input->getArgument('Job ID'); $job = $this->jobList->getById($id); diff --git a/core/Command/Background/Queue/Execute.php b/core/Command/Background/Queue/Execute.php index 62b8fb9a10f2..72e0c3ec8c94 100644 --- a/core/Command/Background/Queue/Execute.php +++ b/core/Command/Background/Queue/Execute.php @@ -64,7 +64,7 @@ protected function configure() { * @param InputInterface $input * @param OutputInterface $output */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (!$input->getOption('accept-warning')) { $helper = new QuestionHelper(); $q = <<setHeaders(['Job ID', 'Job', 'Job Arguments', 'Last Run', 'Last Checked', 'Reserved At', 'Execution Duration (s)']); $this->jobList->listJobs(function (IJob $job) use ($t) { @@ -70,5 +70,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { ]); }); $t->render(); + return 0; } } diff --git a/core/Command/Check.php b/core/Command/Check.php index 73f6e2541d44..3f77ff7135be 100644 --- a/core/Command/Check.php +++ b/core/Command/Check.php @@ -46,7 +46,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $errors = \OC_Util::checkServer($this->config); if (!empty($errors)) { $errors = \array_map(function ($item) { diff --git a/core/Command/Config/App/DeleteConfig.php b/core/Command/Config/App/DeleteConfig.php index 0547e7eb71cc..6d7690edb480 100644 --- a/core/Command/Config/App/DeleteConfig.php +++ b/core/Command/Config/App/DeleteConfig.php @@ -65,7 +65,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $configName = $input->getArgument('name'); diff --git a/core/Command/Config/App/GetConfig.php b/core/Command/Config/App/GetConfig.php index 390af2078274..50f168f5d651 100644 --- a/core/Command/Config/App/GetConfig.php +++ b/core/Command/Config/App/GetConfig.php @@ -70,9 +70,9 @@ protected function configure() { * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code + * @return int 0 if everything went fine, or an error code */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $configName = $input->getArgument('name'); $defaultValue = $input->getOption('default-value'); diff --git a/core/Command/Config/App/SetConfig.php b/core/Command/Config/App/SetConfig.php index c17361f15d86..4ab1f171ef14 100644 --- a/core/Command/Config/App/SetConfig.php +++ b/core/Command/Config/App/SetConfig.php @@ -71,7 +71,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $configName = $input->getArgument('name'); diff --git a/core/Command/Config/Import.php b/core/Command/Config/Import.php index 4bc5a185b645..2add77156e99 100644 --- a/core/Command/Config/Import.php +++ b/core/Command/Config/Import.php @@ -53,7 +53,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $importFile = $input->getArgument('file'); if ($importFile !== null) { $content = $this->getArrayFromFile($importFile); diff --git a/core/Command/Config/ListConfigs.php b/core/Command/Config/ListConfigs.php index 68275ab5b606..c1632ce2f865 100644 --- a/core/Command/Config/ListConfigs.php +++ b/core/Command/Config/ListConfigs.php @@ -69,7 +69,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $app = $input->getArgument('app'); $noSensitiveValues = !$input->getOption('private'); diff --git a/core/Command/Config/System/DeleteConfig.php b/core/Command/Config/System/DeleteConfig.php index ff0a41d0367a..baee001a7213 100644 --- a/core/Command/Config/System/DeleteConfig.php +++ b/core/Command/Config/System/DeleteConfig.php @@ -60,7 +60,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $configNames = $input->getArgument('name'); $configName = $configNames[0]; diff --git a/core/Command/Config/System/GetConfig.php b/core/Command/Config/System/GetConfig.php index 27d0ccd1d204..62b05354668d 100644 --- a/core/Command/Config/System/GetConfig.php +++ b/core/Command/Config/System/GetConfig.php @@ -65,9 +65,9 @@ protected function configure() { * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code + * @return int 0 if everything went fine, or an error code */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $configNames = $input->getArgument('name'); $configName = \array_shift($configNames); $defaultValue = $input->getOption('default-value'); diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php index 92d6210c6ac7..9f44fd36cd2a 100644 --- a/core/Command/Config/System/SetConfig.php +++ b/core/Command/Config/System/SetConfig.php @@ -74,7 +74,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $configNames = $input->getArgument('name'); $configName = $configNames[0]; $configValue = $this->castValue($input->getOption('value'), $input->getOption('type')); diff --git a/core/Command/Db/ConvertMysqlToMB4.php b/core/Command/Db/ConvertMysqlToMB4.php index e8d7a863dbd8..37772f24589b 100644 --- a/core/Command/Db/ConvertMysqlToMB4.php +++ b/core/Command/Db/ConvertMysqlToMB4.php @@ -59,7 +59,7 @@ protected function configure() { ->setDescription('Convert charset of MySQL/MariaDB to use utf8mb4.'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) { $output->writeln("This command is only valid for MySQL/MariaDB databases."); return 1; diff --git a/core/Command/Db/ConvertType.php b/core/Command/Db/ConvertType.php index 01741fae147a..b51971858291 100644 --- a/core/Command/Db/ConvertType.php +++ b/core/Command/Db/ConvertType.php @@ -211,10 +211,10 @@ protected function readPassword(InputInterface $input, OutputInterface $output) /** * @param InputInterface $input * @param OutputInterface $output - * @return int|null|void + * @return int * @throws \Exception */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('This feature is currently experimental.'); $this->targetType = $this->connectionFactory->normalizeType($input->getArgument('type')); $this->targetHostname = $input->getArgument('hostname'); @@ -252,11 +252,12 @@ protected function execute(InputInterface $input, OutputInterface $output) { '@phan-var \Symfony\Component\Console\Helper\QuestionHelper $dialog'; $continue = $dialog->ask($input, $output, new Question('Continue with the conversion (y/n)? [n] ', false)); if ($continue !== 'y') { - return; + return 0; } } $intersectingTables = \array_intersect($toTables, $fromTables); $this->convertDB($fromDB, $toDB, $intersectingTables, $input, $output); + return 0; } /** diff --git a/core/Command/Db/Migrations/ExecuteCommand.php b/core/Command/Db/Migrations/ExecuteCommand.php index 22b9d4870ff8..dc7e62fe1515 100644 --- a/core/Command/Db/Migrations/ExecuteCommand.php +++ b/core/Command/Db/Migrations/ExecuteCommand.php @@ -54,7 +54,7 @@ protected function configure() { parent::configure(); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output)); $version = $input->getArgument('version'); diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php index 26a5dd94d120..543043cf570b 100644 --- a/core/Command/Db/Migrations/GenerateCommand.php +++ b/core/Command/Db/Migrations/GenerateCommand.php @@ -109,7 +109,7 @@ protected function configure() { parent::configure(); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output)); diff --git a/core/Command/Db/Migrations/MigrateCommand.php b/core/Command/Db/Migrations/MigrateCommand.php index d2e1910e6f0e..4940805f81d9 100644 --- a/core/Command/Db/Migrations/MigrateCommand.php +++ b/core/Command/Db/Migrations/MigrateCommand.php @@ -51,7 +51,7 @@ protected function configure() { parent::configure(); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output)); $version = $input->getArgument('version'); diff --git a/core/Command/Db/Migrations/StatusCommand.php b/core/Command/Db/Migrations/StatusCommand.php index 431dd6ba507d..e98767ce3014 100644 --- a/core/Command/Db/Migrations/StatusCommand.php +++ b/core/Command/Db/Migrations/StatusCommand.php @@ -48,7 +48,7 @@ protected function configure() { ->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on'); } - public function execute(InputInterface $input, OutputInterface $output) { + public function execute(InputInterface $input, OutputInterface $output): int { $appName = $input->getArgument('app'); $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output)); diff --git a/core/Command/Db/RestoreDefaultRowFormat.php b/core/Command/Db/RestoreDefaultRowFormat.php index 2b7536fd2e52..84e9cad2b88d 100644 --- a/core/Command/Db/RestoreDefaultRowFormat.php +++ b/core/Command/Db/RestoreDefaultRowFormat.php @@ -51,7 +51,7 @@ protected function configure() { ->setDescription('Restore default row format of MySQL/MariaDB tables.'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) { $output->writeln("This command is only valid for MySQL/MariaDB databases."); return 1; diff --git a/core/Command/Encryption/ChangeKeyStorageRoot.php b/core/Command/Encryption/ChangeKeyStorageRoot.php index 9fcbd1012911..0b53200a79bf 100644 --- a/core/Command/Encryption/ChangeKeyStorageRoot.php +++ b/core/Command/Encryption/ChangeKeyStorageRoot.php @@ -79,7 +79,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $oldRoot = $this->util->getKeyStorageRoot(); $newRoot = $input->getArgument('newRoot'); diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php index 0d0c504a42c8..98e864b9de99 100644 --- a/core/Command/Encryption/DecryptAll.php +++ b/core/Command/Encryption/DecryptAll.php @@ -132,7 +132,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $confirmed = $input->getOption('continue'); if (($confirmed !== 'yes') && ($confirmed !== 'no')) { $output->writeln('Continue can accept either yes or no'); diff --git a/core/Command/Encryption/Disable.php b/core/Command/Encryption/Disable.php index f091a74c2420..5eb494ed1607 100644 --- a/core/Command/Encryption/Disable.php +++ b/core/Command/Encryption/Disable.php @@ -50,7 +50,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $qb = $this->db->getQueryBuilder(); $qb->select($qb->expr()->literal('1')) ->from('filecache', 'fc') diff --git a/core/Command/Encryption/Enable.php b/core/Command/Encryption/Enable.php index e36ce0e776c5..cf43f88eaffc 100644 --- a/core/Command/Encryption/Enable.php +++ b/core/Command/Encryption/Enable.php @@ -52,7 +52,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->encryptionManager->isEnabled()) { $output->writeln('Encryption is already enabled'); } else { diff --git a/core/Command/Encryption/EncryptAll.php b/core/Command/Encryption/EncryptAll.php index e9c6e483798d..7813d00ee73e 100644 --- a/core/Command/Encryption/EncryptAll.php +++ b/core/Command/Encryption/EncryptAll.php @@ -107,7 +107,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->encryptionManager->isEnabled() === false) { throw new \Exception('Server side encryption is not enabled'); } diff --git a/core/Command/Encryption/ListModules.php b/core/Command/Encryption/ListModules.php index 99fd4585f9c9..7aa2bafc9376 100644 --- a/core/Command/Encryption/ListModules.php +++ b/core/Command/Encryption/ListModules.php @@ -48,7 +48,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $encryptionModules = $this->encryptionManager->getEncryptionModules(); $defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId(); diff --git a/core/Command/Encryption/SetDefaultModule.php b/core/Command/Encryption/SetDefaultModule.php index 7665d170a8cf..65117c7463bb 100644 --- a/core/Command/Encryption/SetDefaultModule.php +++ b/core/Command/Encryption/SetDefaultModule.php @@ -53,7 +53,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $moduleId = $input->getArgument('module'); if ($moduleId === $this->encryptionManager->getDefaultEncryptionModuleId()) { diff --git a/core/Command/Encryption/ShowKeyStorageRoot.php b/core/Command/Encryption/ShowKeyStorageRoot.php index 10ea9fc4821d..e8699c5b081f 100644 --- a/core/Command/Encryption/ShowKeyStorageRoot.php +++ b/core/Command/Encryption/ShowKeyStorageRoot.php @@ -45,7 +45,7 @@ protected function configure() { ->setDescription('Show current key storage root.'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $currentRoot = $this->util->getKeyStorageRoot(); $rootDescription = $currentRoot !== '' ? $currentRoot : 'default storage location (data/)'; diff --git a/core/Command/Encryption/Status.php b/core/Command/Encryption/Status.php index 7bf1847969ea..a927b0ee2064 100644 --- a/core/Command/Encryption/Status.php +++ b/core/Command/Encryption/Status.php @@ -47,7 +47,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $this->writeArrayInOutputFormat($input, $output, [ 'enabled' => $this->encryptionManager->isEnabled(), 'defaultModule' => $this->encryptionManager->getDefaultEncryptionModuleId(), diff --git a/core/Command/Group/Add.php b/core/Command/Group/Add.php index 78e454e07a9e..c0eaa53e3898 100644 --- a/core/Command/Group/Add.php +++ b/core/Command/Group/Add.php @@ -50,7 +50,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupName = $input->getArgument('group'); $group = $this->groupManager->get($groupName); if (!$group) { diff --git a/core/Command/Group/AddMember.php b/core/Command/Group/AddMember.php index d582ee166967..1db11aa188cd 100644 --- a/core/Command/Group/AddMember.php +++ b/core/Command/Group/AddMember.php @@ -62,7 +62,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupName = $input->getArgument('group'); $group = $this->groupManager->get($groupName); $errorFound = false; diff --git a/core/Command/Group/Delete.php b/core/Command/Group/Delete.php index f89b699e19f7..220c53231502 100644 --- a/core/Command/Group/Delete.php +++ b/core/Command/Group/Delete.php @@ -50,7 +50,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupName = $input->getArgument('group'); $group = $this->groupManager->get($groupName); if ($group === null) { diff --git a/core/Command/Group/ListGroupMembers.php b/core/Command/Group/ListGroupMembers.php index f73990bf55d8..e85240c6a8a9 100644 --- a/core/Command/Group/ListGroupMembers.php +++ b/core/Command/Group/ListGroupMembers.php @@ -53,7 +53,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupName = $input->getArgument('group'); $group = $this->groupManager->get($groupName); if (!$group) { diff --git a/core/Command/Group/ListGroups.php b/core/Command/Group/ListGroups.php index 46c34613c22c..09c43962c094 100644 --- a/core/Command/Group/ListGroups.php +++ b/core/Command/Group/ListGroups.php @@ -54,7 +54,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupNameSubString = $input->getArgument('search-pattern'); $groups = $this->groupManager->search($groupNameSubString, null, null, 'management', true); $groups = \array_map(function ($group) { diff --git a/core/Command/Group/RemoveMember.php b/core/Command/Group/RemoveMember.php index 0296d95c38a4..894c32d0a6fe 100644 --- a/core/Command/Group/RemoveMember.php +++ b/core/Command/Group/RemoveMember.php @@ -62,7 +62,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $groupName = $input->getArgument('group'); $group = $this->groupManager->get($groupName); $errorFound = false; diff --git a/core/Command/Integrity/CheckApp.php b/core/Command/Integrity/CheckApp.php index 3553fc2263d2..e72cf6b35f41 100644 --- a/core/Command/Integrity/CheckApp.php +++ b/core/Command/Integrity/CheckApp.php @@ -59,7 +59,7 @@ protected function configure() { /** * {@inheritdoc } */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appid = $input->getArgument('appid'); $path = \strval($input->getOption('path')); $result = $this->checker->verifyAppSignature($appid, $path); diff --git a/core/Command/Integrity/CheckCore.php b/core/Command/Integrity/CheckCore.php index 3b83dfc967df..31d0df9888ca 100644 --- a/core/Command/Integrity/CheckCore.php +++ b/core/Command/Integrity/CheckCore.php @@ -56,7 +56,7 @@ protected function configure() { /** * {@inheritdoc } */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $this->checker->runInstanceVerification(); $result = $this->checker->getResults(); $this->writeArrayInOutputFormat($input, $output, $result); diff --git a/core/Command/Integrity/SignApp.php b/core/Command/Integrity/SignApp.php index 90d1e4fd6c20..93461d82b1d0 100644 --- a/core/Command/Integrity/SignApp.php +++ b/core/Command/Integrity/SignApp.php @@ -73,7 +73,7 @@ protected function configure() { /** * {@inheritdoc } */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $path = $input->getOption('path'); $privateKeyPath = $input->getOption('privateKey'); $keyBundlePath = $input->getOption('certificate'); @@ -82,20 +82,20 @@ protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('This command requires the --path, --privateKey and --certificate.'); $output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"'); $output->writeln('For more information please consult the documentation: '. $documentationUrl); - return null; + return 1; } $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); if ($privateKey === false) { - $output->writeln(\sprintf('Private key "%s" does not exists.', $privateKeyPath)); - return null; + $output->writeln(\sprintf('Private key "%s" does not exist.', $privateKeyPath)); + return 1; } if ($keyBundle === false) { - $output->writeln(\sprintf('Certificate "%s" does not exists.', $keyBundlePath)); - return null; + $output->writeln(\sprintf('Certificate "%s" does not exist.', $keyBundlePath)); + return 1; } /** @var RSA $rsa */ diff --git a/core/Command/Integrity/SignCore.php b/core/Command/Integrity/SignCore.php index 2b78a3492db4..3e86de78ee09 100644 --- a/core/Command/Integrity/SignCore.php +++ b/core/Command/Integrity/SignCore.php @@ -67,26 +67,26 @@ protected function configure() { /** * {@inheritdoc } */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $privateKeyPath = $input->getOption('privateKey'); $keyBundlePath = $input->getOption('certificate'); $path = $input->getOption('path'); if ($privateKeyPath === null || $keyBundlePath === null || $path === null) { $output->writeln('--privateKey, --certificate and --path are required.'); - return null; + return 1; } $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); if ($privateKey === false) { - $output->writeln(\sprintf('Private key "%s" does not exists.', $privateKeyPath)); - return null; + $output->writeln(\sprintf('Private key "%s" does not exist.', $privateKeyPath)); + return 1; } if ($keyBundle === false) { - $output->writeln(\sprintf('Certificate "%s" does not exists.', $keyBundlePath)); - return null; + $output->writeln(\sprintf('Certificate "%s" does not exist.', $keyBundlePath)); + return 1; } /** @var RSA $rsa */ diff --git a/core/Command/L10n/CreateJs.php b/core/Command/L10n/CreateJs.php index 3e79278be694..db17d6201a14 100644 --- a/core/Command/L10n/CreateJs.php +++ b/core/Command/L10n/CreateJs.php @@ -47,7 +47,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $app = $input->getArgument('app'); $lang = $input->getArgument('lang'); diff --git a/core/Command/Log/Manage.php b/core/Command/Log/Manage.php index 7e153b6938b5..916cf3c0eb6e 100644 --- a/core/Command/Log/Manage.php +++ b/core/Command/Log/Manage.php @@ -68,7 +68,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { // collate config setting to the end, to avoid partial configuration $toBeSet = []; diff --git a/core/Command/Log/OwnCloud.php b/core/Command/Log/OwnCloud.php index 4c2850404205..d737dba80cf5 100644 --- a/core/Command/Log/OwnCloud.php +++ b/core/Command/Log/OwnCloud.php @@ -62,7 +62,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $toBeSet = []; if ($input->getOption('enable')) { diff --git a/core/Command/Maintenance/DataFingerprint.php b/core/Command/Maintenance/DataFingerprint.php index 19003a11f3a3..665e90401b71 100644 --- a/core/Command/Maintenance/DataFingerprint.php +++ b/core/Command/Maintenance/DataFingerprint.php @@ -54,7 +54,7 @@ protected function configure() { ->setDescription('Update the systems data-fingerprint after a backup is restored.'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $warning = <<addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to the data directory.', \OC::$SERVERROOT."/data"); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { // validate the environment $server = \OC::$server; $setupHelper = new Setup( diff --git a/core/Command/Maintenance/Mimetype/UpdateDB.php b/core/Command/Maintenance/Mimetype/UpdateDB.php index 82f0ac38c4fb..224fa796fbad 100644 --- a/core/Command/Maintenance/Mimetype/UpdateDB.php +++ b/core/Command/Maintenance/Mimetype/UpdateDB.php @@ -60,7 +60,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { '@phan-var \OC\Files\MimetypeDetector $this->mimetypeDetector'; $mappings = $this->mimetypeDetector->getAllMappings(); diff --git a/core/Command/Maintenance/Mimetype/UpdateJS.php b/core/Command/Maintenance/Mimetype/UpdateJS.php index 89467a2a7e5f..6a9872022200 100644 --- a/core/Command/Maintenance/Mimetype/UpdateJS.php +++ b/core/Command/Maintenance/Mimetype/UpdateJS.php @@ -142,7 +142,7 @@ private function getLegacyThemes() { * @param OutputInterface $output * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $fileName = \OC::$SERVERROOT.'/core/js/mimetypelist.js'; $success = \file_put_contents( diff --git a/core/Command/Maintenance/Mode.php b/core/Command/Maintenance/Mode.php index 4b9e2c2f4026..59d56e192f2e 100644 --- a/core/Command/Maintenance/Mode.php +++ b/core/Command/Maintenance/Mode.php @@ -56,7 +56,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('on')) { $this->config->setSystemValue('maintenance', true); $output->writeln('Maintenance mode enabled'); diff --git a/core/Command/Maintenance/Repair.php b/core/Command/Maintenance/Repair.php index 96c756367e69..e30370a0ee5a 100644 --- a/core/Command/Maintenance/Repair.php +++ b/core/Command/Maintenance/Repair.php @@ -95,7 +95,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $appSteps = $this->getAppsRepairSteps($output); // Handle listing repair steps $steps = \array_merge( diff --git a/core/Command/Maintenance/SingleUser.php b/core/Command/Maintenance/SingleUser.php index d49464633d38..f02f570ea532 100644 --- a/core/Command/Maintenance/SingleUser.php +++ b/core/Command/Maintenance/SingleUser.php @@ -59,7 +59,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('on')) { $this->config->setSystemValue('singleuser', true); $output->writeln('Single user mode enabled'); diff --git a/core/Command/Maintenance/UpdateHtaccess.php b/core/Command/Maintenance/UpdateHtaccess.php index 24b54bd00437..04c6b4828752 100644 --- a/core/Command/Maintenance/UpdateHtaccess.php +++ b/core/Command/Maintenance/UpdateHtaccess.php @@ -31,7 +31,7 @@ protected function configure() { ->setDescription('Updates the .htaccess file.'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { \OC\Setup::updateHtaccess(); $output->writeln('.htaccess has been updated'); return 0; diff --git a/core/Command/Previews/Cleanup.php b/core/Command/Previews/Cleanup.php index 17cfc5178287..bbe9a4be9d61 100644 --- a/core/Command/Previews/Cleanup.php +++ b/core/Command/Previews/Cleanup.php @@ -49,7 +49,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $all = $input->hasOption('all'); $chunk_size = $input->getArgument('chunk_size'); $chunk_size_valid = false; diff --git a/core/Command/Security/CreateSignKey.php b/core/Command/Security/CreateSignKey.php index ee06a28bd828..dbe0a43aed02 100644 --- a/core/Command/Security/CreateSignKey.php +++ b/core/Command/Security/CreateSignKey.php @@ -58,11 +58,11 @@ protected function configure() { ->addArgument( 'user', InputArgument::REQUIRED, - 'The is of the user' + 'The id of the user' ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('user'); $user = $this->userManager->get($uid); if ($user === null) { @@ -82,6 +82,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { } $newSigningKey = $this->secureRandom->generate(64); $this->config->setUserValue($uid, 'core', 'signing-key', $newSigningKey, $signingKey); - return 1; + return 0; } } diff --git a/core/Command/Security/ImportCertificate.php b/core/Command/Security/ImportCertificate.php index e12e18d2c74a..987353e16a48 100644 --- a/core/Command/Security/ImportCertificate.php +++ b/core/Command/Security/ImportCertificate.php @@ -47,7 +47,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $path = $input->getArgument('path'); if (!\file_exists($path)) { diff --git a/core/Command/Security/ListCertificates.php b/core/Command/Security/ListCertificates.php index a795a460df5a..f2bee52ba4fd 100644 --- a/core/Command/Security/ListCertificates.php +++ b/core/Command/Security/ListCertificates.php @@ -48,7 +48,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $outputType = $input->getOption('output'); if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { $certificates = \array_map(function (ICertificate $certificate) { diff --git a/core/Command/Security/ListRoutes.php b/core/Command/Security/ListRoutes.php index a39aa2e0dc06..f82ec91253d7 100644 --- a/core/Command/Security/ListRoutes.php +++ b/core/Command/Security/ListRoutes.php @@ -50,7 +50,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $outputType = $input->getOption('output'); \OC_App::loadApps(); diff --git a/core/Command/Security/RemoveCertificate.php b/core/Command/Security/RemoveCertificate.php index 03543d00d620..6a9bae9bc038 100644 --- a/core/Command/Security/RemoveCertificate.php +++ b/core/Command/Security/RemoveCertificate.php @@ -48,7 +48,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $name = $input->getArgument('name'); if ($this->certificateManager->removeCertificate($name)) { diff --git a/core/Command/Status.php b/core/Command/Status.php index bcbb3032e62e..8d4a243da37a 100644 --- a/core/Command/Status.php +++ b/core/Command/Status.php @@ -37,7 +37,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $values = [ 'installed' => (bool) \OC::$server->getConfig()->getSystemValue('installed', false), 'first_install_version' => \OC::$server->getConfig()->getAppValue('core', 'first_install_version', 'unknown'), diff --git a/core/Command/System/Cron.php b/core/Command/System/Cron.php index c5fc80d64b50..81f1bb19c83c 100644 --- a/core/Command/System/Cron.php +++ b/core/Command/System/Cron.php @@ -74,7 +74,7 @@ protected function configure() { * @param OutputInterface $output * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (\OCP\Util::needUpgrade()) { $output->writeln('Update required, skipping cron'); return 1; diff --git a/core/Command/TwoFactorAuth/Disable.php b/core/Command/TwoFactorAuth/Disable.php index b8f5f8882896..e1ca2b29363b 100644 --- a/core/Command/TwoFactorAuth/Disable.php +++ b/core/Command/TwoFactorAuth/Disable.php @@ -49,7 +49,7 @@ protected function configure() { $this->addArgument('uid', InputArgument::REQUIRED); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); $user = $this->userManager->get($uid); if ($user === null) { diff --git a/core/Command/TwoFactorAuth/Enable.php b/core/Command/TwoFactorAuth/Enable.php index 2959caf32e4f..6fec24df3a66 100644 --- a/core/Command/TwoFactorAuth/Enable.php +++ b/core/Command/TwoFactorAuth/Enable.php @@ -49,7 +49,7 @@ protected function configure() { $this->addArgument('uid', InputArgument::REQUIRED); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); $user = $this->userManager->get($uid); if ($user === null) { diff --git a/core/Command/Upgrade.php b/core/Command/Upgrade.php index f73467f99c9a..19d529975f2f 100644 --- a/core/Command/Upgrade.php +++ b/core/Command/Upgrade.php @@ -92,8 +92,10 @@ protected function configure() { * * @param InputInterface $input input interface * @param OutputInterface $output output interface + * + * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL && !$input->hasParameterOption('--verbose=0', true)) { // set to more verbose on upgrade if no explicit verbosity was set diff --git a/core/Command/User/Add.php b/core/Command/User/Add.php index c7b58240b65b..78174164d041 100644 --- a/core/Command/User/Add.php +++ b/core/Command/User/Add.php @@ -92,7 +92,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); if ($this->userManager->userExists($uid)) { $output->writeln('The user "' . $uid . '" already exists.'); diff --git a/core/Command/User/Delete.php b/core/Command/User/Delete.php index 8692338d765d..47e4cf20f44c 100644 --- a/core/Command/User/Delete.php +++ b/core/Command/User/Delete.php @@ -61,7 +61,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); $user = $this->userManager->get($uid); if ($user === null) { diff --git a/core/Command/User/Disable.php b/core/Command/User/Disable.php index 8c3a9518308a..79737f92ffdc 100644 --- a/core/Command/User/Disable.php +++ b/core/Command/User/Disable.php @@ -50,7 +50,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $this->userManager->get($input->getArgument('uid')); if ($user === null) { $output->writeln('User does not exist'); diff --git a/core/Command/User/Enable.php b/core/Command/User/Enable.php index 8783fbea8769..8751e926b3ee 100644 --- a/core/Command/User/Enable.php +++ b/core/Command/User/Enable.php @@ -50,7 +50,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $this->userManager->get($input->getArgument('uid')); if ($user === null) { $output->writeln('User does not exist'); diff --git a/core/Command/User/HomeListDirs.php b/core/Command/User/HomeListDirs.php index 1cfd06a117ee..837205f63ccf 100644 --- a/core/Command/User/HomeListDirs.php +++ b/core/Command/User/HomeListDirs.php @@ -47,7 +47,7 @@ protected function configure() { ->setDescription('List all available root directories for user homes that are currently in use'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (Filesystem::isPrimaryObjectStorageEnabled() === true) { $output->writeln('We detected that the instance is running on a S3 primary object storage, home directories might not be accurate'); } diff --git a/core/Command/User/HomeListUsers.php b/core/Command/User/HomeListUsers.php index 75faac38794d..af3b89957b68 100644 --- a/core/Command/User/HomeListUsers.php +++ b/core/Command/User/HomeListUsers.php @@ -68,7 +68,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (Filesystem::isPrimaryObjectStorageEnabled() === true) { $output->writeln('We detected that the instance is running on a S3 primary object storage, users might not be accurate'); } diff --git a/core/Command/User/Inactive.php b/core/Command/User/Inactive.php index 7b9f4620ee7b..45320fbf19ee 100644 --- a/core/Command/User/Inactive.php +++ b/core/Command/User/Inactive.php @@ -53,7 +53,7 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $days = $input->getArgument('days'); if ((!\is_int($days) && !\ctype_digit($days)) || $days < 1) { throw new InvalidArgumentException('Days must be integer and above zero'); diff --git a/core/Command/User/LastSeen.php b/core/Command/User/LastSeen.php index b6e27880f956..d7bff04fba76 100644 --- a/core/Command/User/LastSeen.php +++ b/core/Command/User/LastSeen.php @@ -53,7 +53,7 @@ protected function configure() { ); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $this->userManager->get($input->getArgument('uid')); if ($user === null) { $output->writeln('User does not exist'); diff --git a/core/Command/User/ListUserGroups.php b/core/Command/User/ListUserGroups.php index dc04745efe54..87408d723235 100644 --- a/core/Command/User/ListUserGroups.php +++ b/core/Command/User/ListUserGroups.php @@ -59,7 +59,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); if (!$this->userManager->userExists($uid)) { $output->writeln("User $uid does not exist."); diff --git a/core/Command/User/ListUsers.php b/core/Command/User/ListUsers.php index 7e922a35527c..cfc2247568f2 100644 --- a/core/Command/User/ListUsers.php +++ b/core/Command/User/ListUsers.php @@ -93,7 +93,7 @@ private function add(&$row, $key, $val, $useKey) { } } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $userNameSubString = $input->getArgument('search-pattern'); $attributes = \array_map('mb_strtolower', $input->getOption('attributes')); $showAllAttributes = $input->getOption('show-all-attributes'); diff --git a/core/Command/User/Modify.php b/core/Command/User/Modify.php index 5e9eb35e1dbb..f856fb1fcd8d 100644 --- a/core/Command/User/Modify.php +++ b/core/Command/User/Modify.php @@ -93,7 +93,7 @@ protected function validateInput(InputInterface $input) { } } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $uid = $input->getArgument('uid'); $key = $input->getArgument('key'); $value = $input->getArgument('value'); diff --git a/core/Command/User/MoveHome.php b/core/Command/User/MoveHome.php index 52b8deba422c..40d6a2b49d88 100644 --- a/core/Command/User/MoveHome.php +++ b/core/Command/User/MoveHome.php @@ -53,7 +53,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $user = $this->getUser($input); $userId = $user->getUID(); $oldHome = $user->getHome(); diff --git a/core/Command/User/Report.php b/core/Command/User/Report.php index a6523cb8109f..dab8f80517b1 100644 --- a/core/Command/User/Report.php +++ b/core/Command/User/Report.php @@ -57,7 +57,7 @@ protected function configure() { ->setDescription('shows how many users have access'); } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { if (Filesystem::isPrimaryObjectStorageEnabled() === true) { $output->writeln('We detected that the instance is running on a S3 primary object storage, user directories count might not be accurate'); } diff --git a/core/Command/User/ResetPassword.php b/core/Command/User/ResetPassword.php index 45e036e600f0..2feaff69d0b1 100644 --- a/core/Command/User/ResetPassword.php +++ b/core/Command/User/ResetPassword.php @@ -98,7 +98,7 @@ protected function configure() { ; } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { $username = $input->getArgument('user'); $emailLink = $input->getOption('send-email'); $displayLink = $input->getOption('output-link'); diff --git a/core/Command/User/Setting.php b/core/Command/User/Setting.php index f68065fc054d..bed7290743c7 100644 --- a/core/Command/User/Setting.php +++ b/core/Command/User/Setting.php @@ -122,7 +122,7 @@ protected function configure() { protected function checkInput(InputInterface $input) { $uid = $input->getArgument('uid'); if (!$input->getOption('ignore-missing-user') && !$this->userManager->userExists($uid)) { - throw new \InvalidArgumentException('The user "' . $uid . '" does not exists.'); + throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.'); } if ($input->getArgument('key') === '' && $input->hasParameterOption('--default-value')) { @@ -153,7 +153,7 @@ protected function checkInput(InputInterface $input) { } } - protected function execute(InputInterface $input, OutputInterface $output) { + protected function execute(InputInterface $input, OutputInterface $output): int { try { $this->checkInput($input); } catch (\InvalidArgumentException $e) { diff --git a/core/Controller/OcsController.php b/core/Controller/OcsController.php index e28fbd808d4c..e2b2e2e136cc 100644 --- a/core/Controller/OcsController.php +++ b/core/Controller/OcsController.php @@ -110,6 +110,7 @@ public function checkPerson($login, $password) { * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute * * @NoAdminRequired + * @NoCSRFRequired * * @return Result */ diff --git a/core/css/icons.css b/core/css/icons.css index 40c81111fb1a..6f2ff89a9351 100644 --- a/core/css/icons.css +++ b/core/css/icons.css @@ -203,6 +203,10 @@ img.icon-loading-small-dark, object.icon-loading-small-dark, video.icon-loading- background-image: url('../img/actions/history.svg'); } +.icon-group { + background-image: url('../img/actions/group.svg'); +} + .icon-info { background-image: url('../img/actions/info.svg'); } diff --git a/core/css/share.css b/core/css/share.css index a6f7bd67d7cc..22ea16d4c6be 100644 --- a/core/css/share.css +++ b/core/css/share.css @@ -53,9 +53,16 @@ .share-autocomplete-item { display: flex; + align-items: center; max-width: 220px; } +.share-autocomplete-item .icon { + margin-left: auto; + margin-right: 5px; + background-size: 24px 24px; +} + @media (min-width: 1152px) { .share-autocomplete-item { max-width: 20vw; diff --git a/core/img/actions/group.svg b/core/img/actions/group.svg new file mode 100644 index 000000000000..9b37641c5d13 --- /dev/null +++ b/core/img/actions/group.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index 3e4e5097b30e..b4fd2d2c7822 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -238,17 +238,34 @@ var securityHeaders = { 'X-XSS-Protection': '0', 'X-Content-Type-Options': 'nosniff', - 'X-Robots-Tag': 'none', + 'X-Robots-Tag': ['none', 'noindex', 'nofollow'], 'X-Frame-Options': 'SAMEORIGIN', 'X-Download-Options': 'noopen', 'X-Permitted-Cross-Domain-Policies': 'none', }; for (var header in securityHeaders) { - if(!xhr.getResponseHeader(header) || xhr.getResponseHeader(header).toLowerCase() !== securityHeaders[header].toLowerCase()) { + if (header === 'X-Robots-Tag') { + xRobotsTagValues = []; + if (xhr.getResponseHeader(header)) { + xRobotsTagValues = xhr.getResponseHeader(header).split(',').map(function(item) { + return item.trim(); + }); + } + + var hasNoneDirective = xRobotsTagValues.indexOf('none') !== -1; + var hasNoIndexAndNoFollowDirectives = xRobotsTagValues.indexOf('noindex') !== -1 && xRobotsTagValues.indexOf('nofollow') !== -1; + + if (!hasNoneDirective && !hasNoIndexAndNoFollowDirectives) { + messages.push({ + msg: t('core', 'The "{header}" HTTP header is misconfigured. Expected values are "none" or "noindex, nofollow". This is a potential security or privacy risk and we recommend adjusting this setting.', {header: header}), + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + }); + } + } else if (!xhr.getResponseHeader(header) || xhr.getResponseHeader(header).toLowerCase() !== securityHeaders[header].toLowerCase()) { messages.push({ - msg: t('core', 'The "{header}" HTTP header is not configured to equal to "{expected}". This is a potential security or privacy risk and we recommend adjusting this setting.', {header: header, expected: securityHeaders[header]}), - type: OC.SetupChecks.MESSAGE_TYPE_WARNING + msg: t('core', 'The "{header}" HTTP header is not configured to equal to "{expected}". This is a potential security or privacy risk and we recommend adjusting this setting.', {header: header, expected: securityHeaders[header]}), + type: OC.SetupChecks.MESSAGE_TYPE_WARNING }); } } diff --git a/core/js/share.js b/core/js/share.js index 28de617b055d..c4d0e2a5222b 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -9,6 +9,7 @@ OC.Share = _.extend(OC.Share || {}, { SHARE_TYPE_LINK:3, SHARE_TYPE_GUEST:4, SHARE_TYPE_REMOTE:6, + SHARE_TYPE_REMOTE_GROUP:7, STATE_ACCEPTED: 0, STATE_PENDING: 1, diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 856814912dae..6b6a131e3c65 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -62,6 +62,9 @@ '{{/if}}' + '
{{typeInfo}}' + '' + + '{{#if showIcon}}' + + '' + + '{{/if}}' + '' + '' + ''; @@ -353,8 +356,9 @@ }, autocompleteRenderItem: function(ul, item) { - var text = item.label; + let showIcon = false; + let iconClass = "" var typeInfo = t('core', 'User'); if (item.batch) { @@ -363,6 +367,11 @@ if (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) { typeInfo = t('core', 'Group'); } + if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) { + typeInfo = t('core', 'Federated Group'); + showIcon = true + iconClass = "icon-contacts-dark" + } if (item.value.shareType === OC.Share.SHARE_TYPE_GUEST) { typeInfo = t('core', 'Guest'); } @@ -375,7 +384,7 @@ typeInfo = t('core', 'Federated'); } } - if(item.value.userType === OC.User.USER_TYPE_GUEST){ + if (item.value.userType === OC.User.USER_TYPE_GUEST) { typeInfo = t('core', 'Guest'); } @@ -383,12 +392,14 @@ var $el = $(template({ showAvatar: this.configModel.areAvatarsEnabled(), displayName: text, + showIcon, + iconClass, typeInfo: typeInfo, additionalInfo: item.value.shareWithAdditionalInfo, shareTypeClass: (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) ? 'group' : 'user' })); - if(this.configModel.areAvatarsEnabled()) { + if (this.configModel.areAvatarsEnabled()) { var $avatar = $el.find('.avatardiv'); if (item.value.shareType === OC.Share.SHARE_TYPE_USER) { $avatar.avatar(item.value.shareWith, 32, undefined, undefined, undefined, item.label); diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js index 6a9c4137c86d..759e5923ccc0 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -422,9 +422,8 @@ describe('OC.SetupChecks tests', function() { msg: 'The "X-Content-Type-Options" HTTP header is not configured to equal to "nosniff". This is a potential security or privacy risk and we recommend adjusting this setting.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING }, { - msg: 'The "X-Robots-Tag" HTTP header is not configured to equal to "none". This is a potential security or privacy risk and we recommend adjusting this setting.', + msg: 'The "X-Robots-Tag" HTTP header is misconfigured. Expected values are "none" or "noindex, nofollow". This is a potential security or privacy risk and we recommend adjusting this setting.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING - }, { msg: 'The "X-Frame-Options" HTTP header is not configured to equal to "SAMEORIGIN". This is a potential security or privacy risk and we recommend adjusting this setting.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING diff --git a/core/l10n/en_GB.js b/core/l10n/en_GB.js index 6e81fdf67c2b..1ada0eaa63ae 100644 --- a/core/l10n/en_GB.js +++ b/core/l10n/en_GB.js @@ -151,6 +151,7 @@ OC.L10N.register( "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\".", "Error occurred while checking server setup" : "Error occurred whilst checking server setup", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips.", diff --git a/core/l10n/en_GB.json b/core/l10n/en_GB.json index 113a504253b1..6513133672e6 100644 --- a/core/l10n/en_GB.json +++ b/core/l10n/en_GB.json @@ -149,6 +149,7 @@ "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\".", "Error occurred while checking server setup" : "Error occurred whilst checking server setup", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips.", diff --git a/core/l10n/ka_GE.js b/core/l10n/ka_GE.js index 7d62f0114045..92f6e1c3fb50 100644 --- a/core/l10n/ka_GE.js +++ b/core/l10n/ka_GE.js @@ -1,6 +1,11 @@ OC.L10N.register( "core", { + "Unknown filetype" : "უცნობი ფაილის ტიპი", + "Invalid image" : "არასწორი სურათი", + "Turned on maintenance mode" : "შენახვის რეჟიმი ჩართულია", + "Turned off maintenance mode" : "შენახვის რეჟიმი გამორთულია ", + "Updated database" : " მონაცემთა ბაზა განახლებულია", "Sunday" : "კვირა", "Monday" : "ორშაბათი", "Tuesday" : "სამშაბათი", @@ -73,7 +78,11 @@ OC.L10N.register( "Rename" : "გადარქმევა", "Delete" : "წაშლა", "The object type is not specified." : "ობიექტის ტიპი არ არის მითითებული.", + "Enter new" : "შეიყვანეთ ახალი", "Add" : "დამატება", + "Edit tags" : "თეგების რედაქტირება", + "Error loading dialog template: {error}" : "შეცდომა დიალოგის შაბლონის ჩატვირთვისას: {შეცდომა}", + "No tags selected for deletion." : " წასაშლელად თეგები არ არის არჩეული.", "The update was unsuccessful. Please report this issue to the ownCloud community." : "განახლება ვერ განხორციელდა. გთხოვთ შეგვატყობინოთ ამ პრობლემის შესახებ აქ: ownCloud community.", "The update was successful. Redirecting you to ownCloud now." : "განახლება ვერ განხორციელდა. გადამისამართება თქვენს ownCloud–ზე.", "Personal" : "პირადი", @@ -82,6 +91,7 @@ OC.L10N.register( "Admin" : "ადმინისტრატორი", "Help" : "დახმარება", "Access forbidden" : "წვდომა აკრძალულია", + "Cheers!" : "გამარჯვებები!", "Imprint" : "ბეჭედი", "Create an admin account" : "შექმენი ადმინ ექაუნტი", "Username" : "მომხმარებლის სახელი", @@ -95,6 +105,8 @@ OC.L10N.register( "Finish setup" : "კონფიგურაციის დასრულება", "Log out" : "გამოსვლა", "Search" : "ძებნა", + "Server side authentication failed!" : "სერვერის მხრიდან ავტორიზაცია ვერ მოხერხდა!", + "Please contact your administrator." : "გთხოვთ, დაუკავშირდეთ თქვენს ადმინისტრატორს.", "Login" : "ლოგინი", "Alternative Logins" : "ალტერნატიული Login–ი", "Use the following link to reset your password: {link}" : "გამოიყენე შემდეგი ლინკი პაროლის შესაცვლელად: {link}", diff --git a/core/l10n/ka_GE.json b/core/l10n/ka_GE.json index c54bf4b30467..06d205298676 100644 --- a/core/l10n/ka_GE.json +++ b/core/l10n/ka_GE.json @@ -1,4 +1,9 @@ { "translations": { + "Unknown filetype" : "უცნობი ფაილის ტიპი", + "Invalid image" : "არასწორი სურათი", + "Turned on maintenance mode" : "შენახვის რეჟიმი ჩართულია", + "Turned off maintenance mode" : "შენახვის რეჟიმი გამორთულია ", + "Updated database" : " მონაცემთა ბაზა განახლებულია", "Sunday" : "კვირა", "Monday" : "ორშაბათი", "Tuesday" : "სამშაბათი", @@ -71,7 +76,11 @@ "Rename" : "გადარქმევა", "Delete" : "წაშლა", "The object type is not specified." : "ობიექტის ტიპი არ არის მითითებული.", + "Enter new" : "შეიყვანეთ ახალი", "Add" : "დამატება", + "Edit tags" : "თეგების რედაქტირება", + "Error loading dialog template: {error}" : "შეცდომა დიალოგის შაბლონის ჩატვირთვისას: {შეცდომა}", + "No tags selected for deletion." : " წასაშლელად თეგები არ არის არჩეული.", "The update was unsuccessful. Please report this issue to the ownCloud community." : "განახლება ვერ განხორციელდა. გთხოვთ შეგვატყობინოთ ამ პრობლემის შესახებ აქ: ownCloud community.", "The update was successful. Redirecting you to ownCloud now." : "განახლება ვერ განხორციელდა. გადამისამართება თქვენს ownCloud–ზე.", "Personal" : "პირადი", @@ -80,6 +89,7 @@ "Admin" : "ადმინისტრატორი", "Help" : "დახმარება", "Access forbidden" : "წვდომა აკრძალულია", + "Cheers!" : "გამარჯვებები!", "Imprint" : "ბეჭედი", "Create an admin account" : "შექმენი ადმინ ექაუნტი", "Username" : "მომხმარებლის სახელი", @@ -93,6 +103,8 @@ "Finish setup" : "კონფიგურაციის დასრულება", "Log out" : "გამოსვლა", "Search" : "ძებნა", + "Server side authentication failed!" : "სერვერის მხრიდან ავტორიზაცია ვერ მოხერხდა!", + "Please contact your administrator." : "გთხოვთ, დაუკავშირდეთ თქვენს ადმინისტრატორს.", "Login" : "ლოგინი", "Alternative Logins" : "ალტერნატიული Login–ი", "Use the following link to reset your password: {link}" : "გამოიყენე შემდეგი ლინკი პაროლის შესაცვლელად: {link}", diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index 893669cfe8c5..95ecc403d2f9 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -151,6 +151,7 @@ OC.L10N.register( "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "Você está executando no modo DEBUG, isso pode causar efeitos colaterais indesejados. Remova o sinalizador \"debug\" do \"config.php\".", "Error occurred while checking server setup" : "Erro ao verificar a configuração do servidor", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "O seu diretório de dados e os arquivos estão, provavelmente, acessíveis a partir da Internet. O arquivo .htaccess não está funcionando. Nós sugerimos que você configure o servidor web de uma forma que o diretório de dados não seja acessível ou mova o diretório de dados para fora do diretório raiz de documentos do servidor web.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "O cabeçalho HTTP \"{header}\" está configurado incorretamente. Os valores esperados são \"nenhum\" ou \"noindex, nofollow\". Este é um risco potencial de segurança ou privacidade e recomendamos ajustar esta configuração.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "O \"{header}\" cabeçalho HTTP não está configurado igual ao \"{expected}\". Este é um risco potencial para a segurança e recomendamos ajustar essa configuração.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "O \"Strict-Transport-Security\" cabeçalho HTTP não está configurado para pelo menos \"{segundos}\" segundos. Para maior segurança recomendamos a ativação HSTS como descrito em nossas dicas de segurança.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Você está acessando este site via HTTP. Nós fortemente sugerimos que você ao invéz, configure o servidor para exigir o uso de HTTPS como descrito em nossas dicas de segurança.", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 580bb5d0f9d2..930d79cefaf0 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -149,6 +149,7 @@ "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "Você está executando no modo DEBUG, isso pode causar efeitos colaterais indesejados. Remova o sinalizador \"debug\" do \"config.php\".", "Error occurred while checking server setup" : "Erro ao verificar a configuração do servidor", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "O seu diretório de dados e os arquivos estão, provavelmente, acessíveis a partir da Internet. O arquivo .htaccess não está funcionando. Nós sugerimos que você configure o servidor web de uma forma que o diretório de dados não seja acessível ou mova o diretório de dados para fora do diretório raiz de documentos do servidor web.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "O cabeçalho HTTP \"{header}\" está configurado incorretamente. Os valores esperados são \"nenhum\" ou \"noindex, nofollow\". Este é um risco potencial de segurança ou privacidade e recomendamos ajustar esta configuração.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "O \"{header}\" cabeçalho HTTP não está configurado igual ao \"{expected}\". Este é um risco potencial para a segurança e recomendamos ajustar essa configuração.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "O \"Strict-Transport-Security\" cabeçalho HTTP não está configurado para pelo menos \"{segundos}\" segundos. Para maior segurança recomendamos a ativação HSTS como descrito em nossas dicas de segurança.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Você está acessando este site via HTTP. Nós fortemente sugerimos que você ao invéz, configure o servidor para exigir o uso de HTTPS como descrito em nossas dicas de segurança.", diff --git a/core/l10n/sq.js b/core/l10n/sq.js index 9f2a43d967e0..bd85f0fbd77a 100644 --- a/core/l10n/sq.js +++ b/core/l10n/sq.js @@ -151,6 +151,7 @@ OC.L10N.register( "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "Po e xhironi nën mënyrën DEBUG, kjo mund të shkaktojë efekte anësore të padëshiruara. Ju lutemi, hiqeni shenjën \"debug\" nga \"config.php\".", "Error occurred while checking server setup" : "Ndodhi një gabim gjatë kontrollit të rregullimit të shërbyesit", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Drejtoria juaj e të dhënave dhe kartelat tuaja ka shumë mundësi të jenë të arritshme që nga interneti. Kartela .htaccess s’funksionon. Këshillojmë me forcë që ta formësoni shërbyesin tuaj në një mënyrë që drejtoria e të dhënave të mos lejojë më hyrje, ose ta zhvendosni drejtorinë e të dhënave jashtë rrënjës së dokumenteve të shërbyesit.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Kryet HTTP “{header}” janë formësuar keq. Vlerat e pritshme janë “none” ose “noindex, nofollow”. Kjo përbën një rrezik potencial sigurie ose privatësie dhe \nkëshillojmë të ndreqet ky rregullim.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Kryet HTTP \"{header}\" s’është formësuar të jetë i njëjtë me \"{expected}\". Ky është një rrezik potencial sigurie dhe privatësie dhe këshillojmë të ndreqet ky rregullim.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "Parametri \"Strict-Transport-Security\" HTTP s’është formësuar të paktën \"{seconds}\" sekonda. Për siguri të thelluar, ju këshillojmë aktivizimin e HSTS-së, ashtu si përshkruhet në këshillat tona mbi sigurinë.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Po e përdorni këtë sajt përmes HTTP-je. Këshillojmë me forcë ta formësoni shërbyesin tuaj të kërkojë medoemos përdorimin e HTTPS-së, siç përshkruhet te këshillat tona mbi sigurinë.", diff --git a/core/l10n/sq.json b/core/l10n/sq.json index 08943ed64e5f..bc12e5b68fc7 100644 --- a/core/l10n/sq.json +++ b/core/l10n/sq.json @@ -149,6 +149,7 @@ "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "Po e xhironi nën mënyrën DEBUG, kjo mund të shkaktojë efekte anësore të padëshiruara. Ju lutemi, hiqeni shenjën \"debug\" nga \"config.php\".", "Error occurred while checking server setup" : "Ndodhi një gabim gjatë kontrollit të rregullimit të shërbyesit", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Drejtoria juaj e të dhënave dhe kartelat tuaja ka shumë mundësi të jenë të arritshme që nga interneti. Kartela .htaccess s’funksionon. Këshillojmë me forcë që ta formësoni shërbyesin tuaj në një mënyrë që drejtoria e të dhënave të mos lejojë më hyrje, ose ta zhvendosni drejtorinë e të dhënave jashtë rrënjës së dokumenteve të shërbyesit.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Kryet HTTP “{header}” janë formësuar keq. Vlerat e pritshme janë “none” ose “noindex, nofollow”. Kjo përbën një rrezik potencial sigurie ose privatësie dhe \nkëshillojmë të ndreqet ky rregullim.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Kryet HTTP \"{header}\" s’është formësuar të jetë i njëjtë me \"{expected}\". Ky është një rrezik potencial sigurie dhe privatësie dhe këshillojmë të ndreqet ky rregullim.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "Parametri \"Strict-Transport-Security\" HTTP s’është formësuar të paktën \"{seconds}\" sekonda. Për siguri të thelluar, ju këshillojmë aktivizimin e HSTS-së, ashtu si përshkruhet në këshillat tona mbi sigurinë.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Po e përdorni këtë sajt përmes HTTP-je. Këshillojmë me forcë ta formësoni shërbyesin tuaj të kërkojë medoemos përdorimin e HTTPS-së, siç përshkruhet te këshillat tona mbi sigurinë.", diff --git a/core/l10n/tr.js b/core/l10n/tr.js index 921c3be3f11e..02edb2366fcf 100644 --- a/core/l10n/tr.js +++ b/core/l10n/tr.js @@ -151,6 +151,7 @@ OC.L10N.register( "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "DEBUG modunda çalışıyorsunuz, bu istenmeyen yan etkilere neden olabilir. Lütfen \"debug\" işaretini \"config.php\" dosyasından kaldırın.", "Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "data dizininiz ve dosyalarınız büyük ihtimalle İnternet üzerinden erişilebilir. .htaccess dosyası çalışmıyor. Web sunucunuzu yapılandırarak data dizinine erişimi kapatmanızı veya data dizinini web sunucu belge dizini dışına almanızı şiddetle tavsiye ederiz.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı yanlış yapılandırılmış. Beklenen değerler \"none\" veya \"noindex, nofollow\" şeklindedir. Bu potansiyel bir güvenlik veya gizlilik riskidir ve bu ayarı değiştirmenizi öneririz.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için güvenlik ipuçlarımızda belirtilen HSTS etkinleştirmesini öneririz.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Bu siteye HTTP aracılığıyla erişiyorsunuz. Sunucunuzu güvenlik ipuçlarımızda gösterildiği şekilde HTTPS kullanımını zorlamak üzere yapılandırmanızı şiddetle öneririz.", diff --git a/core/l10n/tr.json b/core/l10n/tr.json index 445a80f90afb..e4e3918e8b52 100644 --- a/core/l10n/tr.json +++ b/core/l10n/tr.json @@ -149,6 +149,7 @@ "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "DEBUG modunda çalışıyorsunuz, bu istenmeyen yan etkilere neden olabilir. Lütfen \"debug\" işaretini \"config.php\" dosyasından kaldırın.", "Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "data dizininiz ve dosyalarınız büyük ihtimalle İnternet üzerinden erişilebilir. .htaccess dosyası çalışmıyor. Web sunucunuzu yapılandırarak data dizinine erişimi kapatmanızı veya data dizinini web sunucu belge dizini dışına almanızı şiddetle tavsiye ederiz.", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı yanlış yapılandırılmış. Beklenen değerler \"none\" veya \"noindex, nofollow\" şeklindedir. Bu potansiyel bir güvenlik veya gizlilik riskidir ve bu ayarı değiştirmenizi öneririz.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için güvenlik ipuçlarımızda belirtilen HSTS etkinleştirmesini öneririz.", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "Bu siteye HTTP aracılığıyla erişiyorsunuz. Sunucunuzu güvenlik ipuçlarımızda gösterildiği şekilde HTTPS kullanımını zorlamak üzere yapılandırmanızı şiddetle öneririz.", diff --git a/core/l10n/vi.js b/core/l10n/vi.js index cc975a616d4d..660052c7b7ba 100644 --- a/core/l10n/vi.js +++ b/core/l10n/vi.js @@ -93,12 +93,16 @@ OC.L10N.register( "Error" : "Lỗi", "Error while sharing" : "Lỗi trong quá trình chia sẻ", "Error while unsharing" : "Lỗi trong quá trình gỡ chia sẻ", + "The public link will expire no later than {days} days after it is created" : "Liên kết công khai sẽ hết hạn trong {days} ngày sau khi được tạo.", + "Create public link" : "Tạo liên kết công khai", "Edit" : "Sửa", "Remove" : "Xóa", "Copy to clipboard" : "Sao chép vào clipboard", + "There are currently no link shares, you can create one" : "Chưa có liên kết nào được chia sẽ, bạn có thể tạo một liên kết mới.", "Anyone with the link has access to the file/folder" : "Bất cứ ai liên kết đều có quyền truy cập tệp tin/thư mục", "Name" : "Tên", "Password" : "Mật khẩu", + "Create link share: {name}" : "Chia sẽ liên kết tập tin: {name}", "Share" : "Chia sẻ", "Save" : "Lưu", "Email link to person" : "Liên kết email tới cá nhân", @@ -113,8 +117,10 @@ OC.L10N.register( "change" : "thay đôi", "delete" : "xóa", "access control" : "quản lý truy cập", + "No users or groups found" : "Không có người dùng hoặc nhóm", "User" : "Người dùng", "Group" : "N", + "User and Groups" : "Người dùng hoặc Nhóm", "Public Links" : "Liên kết công khai", "Rename" : "Sửa tên", "Delete" : "Xóa", @@ -152,6 +158,7 @@ OC.L10N.register( "Server side authentication failed!" : "Xác thực phía máy chủ không thành công!", "Please contact your administrator." : "Vui lòng liên hệ với quản trị viên.", "Login" : "Đăng nhập", + "Username or email" : "Tên đăng nhập hoặc Email", "Alternative Logins" : "Đăng nhập khác", "Use the following link to reset your password: {link}" : "Dùng đường dẫn sau để khôi phục lại mật khẩu : {link}", "New password" : "Mật khẩu mới", diff --git a/core/l10n/vi.json b/core/l10n/vi.json index 001377d40975..9af55918a30c 100644 --- a/core/l10n/vi.json +++ b/core/l10n/vi.json @@ -91,12 +91,16 @@ "Error" : "Lỗi", "Error while sharing" : "Lỗi trong quá trình chia sẻ", "Error while unsharing" : "Lỗi trong quá trình gỡ chia sẻ", + "The public link will expire no later than {days} days after it is created" : "Liên kết công khai sẽ hết hạn trong {days} ngày sau khi được tạo.", + "Create public link" : "Tạo liên kết công khai", "Edit" : "Sửa", "Remove" : "Xóa", "Copy to clipboard" : "Sao chép vào clipboard", + "There are currently no link shares, you can create one" : "Chưa có liên kết nào được chia sẽ, bạn có thể tạo một liên kết mới.", "Anyone with the link has access to the file/folder" : "Bất cứ ai liên kết đều có quyền truy cập tệp tin/thư mục", "Name" : "Tên", "Password" : "Mật khẩu", + "Create link share: {name}" : "Chia sẽ liên kết tập tin: {name}", "Share" : "Chia sẻ", "Save" : "Lưu", "Email link to person" : "Liên kết email tới cá nhân", @@ -111,8 +115,10 @@ "change" : "thay đôi", "delete" : "xóa", "access control" : "quản lý truy cập", + "No users or groups found" : "Không có người dùng hoặc nhóm", "User" : "Người dùng", "Group" : "N", + "User and Groups" : "Người dùng hoặc Nhóm", "Public Links" : "Liên kết công khai", "Rename" : "Sửa tên", "Delete" : "Xóa", @@ -150,6 +156,7 @@ "Server side authentication failed!" : "Xác thực phía máy chủ không thành công!", "Please contact your administrator." : "Vui lòng liên hệ với quản trị viên.", "Login" : "Đăng nhập", + "Username or email" : "Tên đăng nhập hoặc Email", "Alternative Logins" : "Đăng nhập khác", "Use the following link to reset your password: {link}" : "Dùng đường dẫn sau để khôi phục lại mật khẩu : {link}", "New password" : "Mật khẩu mới", diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js index 25b3a0002830..ce3d7c3905fd 100644 --- a/core/l10n/zh_CN.js +++ b/core/l10n/zh_CN.js @@ -151,6 +151,7 @@ OC.L10N.register( "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "你在以 DEBUG 模式运行,这可能导致意外的副作用。请从 \"config.php\" 文件中移除 \"debug\" 标识。", "Error occurred while checking server setup" : "当检查服务器启动时出错", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "你的数据目录和你的文件可能从互联网被访问到。.htaccess 文件不工作。我们强烈建议你配置你的网页服务器,使数据目录不再可访问,或者将数据目录移动到网页服务器根文档目录之外。", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : " HTTP头“{header}”配置错误。可接受的值为“none”或者“noindex, nofollow”。这是一个潜在的安全或隐私风险,我们建议您调整这个设置。", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP 头部没有配置和 \"{expected}\" 的一样。这是一个潜在的安全或者隐私风险,我们调整这项设置。", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "HTTP 严格传输安全(Strict-Transport-Security)报头未配置到至少“{seconds}”秒。处于增强安全性考虑,我们推荐按照安全提示启用 HSTS。", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "您正在通过 HTTP 访问该站点,我们强烈建议您按照安全提示配置服务器强制使用 HTTPS。", @@ -183,6 +184,8 @@ OC.L10N.register( "Name" : "名称", "Filename" : "文件名", "Password" : "密码", + "Download / View / Upload / Edit" : "下载/查看/上传/编辑", + "Recipients can view, download and edit contents." : "接收者可以查看、下载和编辑内容。", "Can not remove required password" : "无法移除要求的密码", "Edit link share: {name}" : "编辑共享链接: {name}", "Create link share: {name}" : "创建共享链接: {name}", @@ -216,6 +219,7 @@ OC.L10N.register( "Email notification was sent!" : "电子邮件通知已发送!", "Email notification not sent" : "电子邮件通知未发送", "Share details could not be loaded for this item." : "无法加载这个项目的分享详情", + "No users or groups found" : "没有发现用户或组", "No users or groups found for {search}" : "{search} 条件下没有找到用户或用户组", "No users found for {search}" : "没有找到 {search} 用户", "_Please enter at least {chars} character for suggestions_::_Please enter at least {chars} characters for suggestions_" : ["请输入至少 {chars} 字符作为建议"], @@ -233,6 +237,8 @@ OC.L10N.register( "Share with users, groups or federated users…" : "与用户、组或联合用户共享……", "Share with users or groups…" : "与用户或组分享...", "Share with users or federated users…" : "与用户或联合用户共享…", + "Could not be shared with the following users: {users}" : "不能分享给下面的用户:{users}", + "Add multiple users" : "添加多个用户", "Error removing share" : "移除分享时出错", "Unknown Share" : "未知共享", "Non-existing tag #{tag}" : "标签 #{tag} 不存在", @@ -282,6 +288,7 @@ OC.L10N.register( "The share will expire on %s." : "此分享将在 %s 过期。", "Personal note from the sender: \n %s." : "来自发送者的个人留言:\n %s.", "Cheers!" : "干杯!", + "The application was authorized successfully. You will now get redirected to the requested page, otherwise you can close this window." : "该应用程序已成功获得授权。你将会被重定向到请求的页面,或者你可以关闭这个窗口。", "Internal Server Error" : "内部服务器错误", "The server encountered an internal error and was unable to complete your request." : "服务器发送一个内部错误并且无法完成你的请求。", "Please contact the server administrator if this error reappears multiple times and include the technical details below in your report." : "如果此错误多次复现请联系服务器管理员,并在报告中包含以下技术细节。", @@ -310,6 +317,7 @@ OC.L10N.register( "Database name" : "数据库名", "Database tablespace" : "数据库表空间", "Database host" : "数据库主机", + "Please specify the port number along with the host name (e.g., localhost:5432)." : "请指定主机名和端口号(例如 localhost:5432)。", "Performance warning" : "性能警告", "SQLite will be used as database." : "SQLite 将被作为数据库使用。", "For larger installations we recommend to choose a different database backend." : "对于更大的安装,我们建议选择一个不同的数据库后端。", @@ -350,6 +358,7 @@ OC.L10N.register( "Cancel login" : "取消登录", "Please authenticate using the selected factor." : "请使用所选择的因素验证。", "An error occurred while verifying the token" : "在验证令牌时出错", + "You are accessing the server through an untrusted domain." : "你正在通过一个不受信任的域名访问服务器。", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. " : "请联系你的系统管理员。如果你是系统管理员,配置 config/config.php 文件中参数 \"trusted_domain\" 设置。", "An example configuration is provided in config/config.sample.php or at the documentation." : "一个示例配置在 config/config.sample.php 文件或 文档中有提供。", "App update required" : "必须的应用更新", diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json index 651c55ea7b03..cad0526edf23 100644 --- a/core/l10n/zh_CN.json +++ b/core/l10n/zh_CN.json @@ -149,6 +149,7 @@ "You are running in DEBUG mode, this can cause unwanted side effects. Please remove the \"debug\" flag from \"config.php\"." : "你在以 DEBUG 模式运行,这可能导致意外的副作用。请从 \"config.php\" 文件中移除 \"debug\" 标识。", "Error occurred while checking server setup" : "当检查服务器启动时出错", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "你的数据目录和你的文件可能从互联网被访问到。.htaccess 文件不工作。我们强烈建议你配置你的网页服务器,使数据目录不再可访问,或者将数据目录移动到网页服务器根文档目录之外。", + "The \"{header}\" HTTP header is misconfigured. Expected values are \"none\" or \"noindex, nofollow\". This is a potential security or privacy risk and we recommend adjusting this setting." : " HTTP头“{header}”配置错误。可接受的值为“none”或者“noindex, nofollow”。这是一个潜在的安全或隐私风险,我们建议您调整这个设置。", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP 头部没有配置和 \"{expected}\" 的一样。这是一个潜在的安全或者隐私风险,我们调整这项设置。", "The \"Strict-Transport-Security\" HTTP header is not configured to at least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our security tips." : "HTTP 严格传输安全(Strict-Transport-Security)报头未配置到至少“{seconds}”秒。处于增强安全性考虑,我们推荐按照安全提示启用 HSTS。", "You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our security tips." : "您正在通过 HTTP 访问该站点,我们强烈建议您按照安全提示配置服务器强制使用 HTTPS。", @@ -181,6 +182,8 @@ "Name" : "名称", "Filename" : "文件名", "Password" : "密码", + "Download / View / Upload / Edit" : "下载/查看/上传/编辑", + "Recipients can view, download and edit contents." : "接收者可以查看、下载和编辑内容。", "Can not remove required password" : "无法移除要求的密码", "Edit link share: {name}" : "编辑共享链接: {name}", "Create link share: {name}" : "创建共享链接: {name}", @@ -214,6 +217,7 @@ "Email notification was sent!" : "电子邮件通知已发送!", "Email notification not sent" : "电子邮件通知未发送", "Share details could not be loaded for this item." : "无法加载这个项目的分享详情", + "No users or groups found" : "没有发现用户或组", "No users or groups found for {search}" : "{search} 条件下没有找到用户或用户组", "No users found for {search}" : "没有找到 {search} 用户", "_Please enter at least {chars} character for suggestions_::_Please enter at least {chars} characters for suggestions_" : ["请输入至少 {chars} 字符作为建议"], @@ -231,6 +235,8 @@ "Share with users, groups or federated users…" : "与用户、组或联合用户共享……", "Share with users or groups…" : "与用户或组分享...", "Share with users or federated users…" : "与用户或联合用户共享…", + "Could not be shared with the following users: {users}" : "不能分享给下面的用户:{users}", + "Add multiple users" : "添加多个用户", "Error removing share" : "移除分享时出错", "Unknown Share" : "未知共享", "Non-existing tag #{tag}" : "标签 #{tag} 不存在", @@ -280,6 +286,7 @@ "The share will expire on %s." : "此分享将在 %s 过期。", "Personal note from the sender: \n %s." : "来自发送者的个人留言:\n %s.", "Cheers!" : "干杯!", + "The application was authorized successfully. You will now get redirected to the requested page, otherwise you can close this window." : "该应用程序已成功获得授权。你将会被重定向到请求的页面,或者你可以关闭这个窗口。", "Internal Server Error" : "内部服务器错误", "The server encountered an internal error and was unable to complete your request." : "服务器发送一个内部错误并且无法完成你的请求。", "Please contact the server administrator if this error reappears multiple times and include the technical details below in your report." : "如果此错误多次复现请联系服务器管理员,并在报告中包含以下技术细节。", @@ -308,6 +315,7 @@ "Database name" : "数据库名", "Database tablespace" : "数据库表空间", "Database host" : "数据库主机", + "Please specify the port number along with the host name (e.g., localhost:5432)." : "请指定主机名和端口号(例如 localhost:5432)。", "Performance warning" : "性能警告", "SQLite will be used as database." : "SQLite 将被作为数据库使用。", "For larger installations we recommend to choose a different database backend." : "对于更大的安装,我们建议选择一个不同的数据库后端。", @@ -348,6 +356,7 @@ "Cancel login" : "取消登录", "Please authenticate using the selected factor." : "请使用所选择的因素验证。", "An error occurred while verifying the token" : "在验证令牌时出错", + "You are accessing the server through an untrusted domain." : "你正在通过一个不受信任的域名访问服务器。", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. " : "请联系你的系统管理员。如果你是系统管理员,配置 config/config.php 文件中参数 \"trusted_domain\" 设置。", "An example configuration is provided in config/config.sample.php or at the documentation." : "一个示例配置在 config/config.sample.php 文件或 文档中有提供。", "App update required" : "必须的应用更新", diff --git a/lib/l10n/ka_GE.js b/lib/l10n/ka_GE.js index 5d4d6b016026..d1a7a1b98868 100644 --- a/lib/l10n/ka_GE.js +++ b/lib/l10n/ka_GE.js @@ -1,6 +1,8 @@ OC.L10N.register( "lib", { + "Unknown filetype" : "უცნობი ფაილის ტიპი", + "Invalid image" : "არასწორი სურათი", "today" : "დღეს", "yesterday" : "გუშინ", "last month" : "გასულ თვეში", diff --git a/lib/l10n/ka_GE.json b/lib/l10n/ka_GE.json index 407ae168145f..2e47362f20b3 100644 --- a/lib/l10n/ka_GE.json +++ b/lib/l10n/ka_GE.json @@ -1,4 +1,6 @@ { "translations": { + "Unknown filetype" : "უცნობი ფაილის ტიპი", + "Invalid image" : "არასწორი სურათი", "today" : "დღეს", "yesterday" : "გუშინ", "last month" : "გასულ თვეში", diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js index dab1940c3e3c..017787e526bb 100644 --- a/lib/l10n/nl.js +++ b/lib/l10n/nl.js @@ -61,7 +61,7 @@ OC.L10N.register( "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "De app kan niet worden geïnstalleerd, omdat de versie in info.xml niet dezelfde is als de versie zoals die in de app store staat vermeld", "Apps" : "Apps", "General" : "Algemeen", - "Storage" : "Opslaglimiet", + "Storage" : "Opslag", "Security" : "Beveiliging", "User Authentication" : "Gebruiker authenticatie", "Encryption" : "Versleuteling", diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json index be4d5c196aaa..984d70b5a12e 100644 --- a/lib/l10n/nl.json +++ b/lib/l10n/nl.json @@ -59,7 +59,7 @@ "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "De app kan niet worden geïnstalleerd, omdat de versie in info.xml niet dezelfde is als de versie zoals die in de app store staat vermeld", "Apps" : "Apps", "General" : "Algemeen", - "Storage" : "Opslaglimiet", + "Storage" : "Opslag", "Security" : "Beveiliging", "User Authentication" : "Gebruiker authenticatie", "Encryption" : "Versleuteling", diff --git a/lib/l10n/tr.js b/lib/l10n/tr.js index 3cb821fa5aa2..0cb4aa0a9a05 100644 --- a/lib/l10n/tr.js +++ b/lib/l10n/tr.js @@ -18,6 +18,9 @@ OC.L10N.register( "Following platforms are supported: %s" : "Aşağıdaki platformlar destekleniyor: %s", "ownCloud %s or higher is required." : "ownCloud %s veya daha üstü gerekli.", "ownCloud %s or lower is required." : "ownCloud %s veya daha düşük sürüm gerekli.", + "%s is member of a group not allowed to access through this login mechanism" : "%s, bu oturum açma mekanizması aracılığıyla erişmesine izin verilmeyen bir grubun üyesidir", + "%s isn't member of a group allowed to access through this login mechanism" : "%s, bu oturum açma mekanizması aracılığıyla erişmesine izin verilen bir grubun üyesi değil", + "A login policy has blocked the login" : "Bir oturum açma politikası oturum açmayı engelledi", "Unknown filetype" : "Bilinmeyen dosya türü", "Invalid image" : "Geçersiz resim", "Avatar image is not square" : "Avatar resmi kare değil", diff --git a/lib/l10n/tr.json b/lib/l10n/tr.json index ef3e31c7c16a..a19c3a47fb45 100644 --- a/lib/l10n/tr.json +++ b/lib/l10n/tr.json @@ -16,6 +16,9 @@ "Following platforms are supported: %s" : "Aşağıdaki platformlar destekleniyor: %s", "ownCloud %s or higher is required." : "ownCloud %s veya daha üstü gerekli.", "ownCloud %s or lower is required." : "ownCloud %s veya daha düşük sürüm gerekli.", + "%s is member of a group not allowed to access through this login mechanism" : "%s, bu oturum açma mekanizması aracılığıyla erişmesine izin verilmeyen bir grubun üyesidir", + "%s isn't member of a group allowed to access through this login mechanism" : "%s, bu oturum açma mekanizması aracılığıyla erişmesine izin verilen bir grubun üyesi değil", + "A login policy has blocked the login" : "Bir oturum açma politikası oturum açmayı engelledi", "Unknown filetype" : "Bilinmeyen dosya türü", "Invalid image" : "Geçersiz resim", "Avatar image is not square" : "Avatar resmi kare değil", diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index e4110f1a7424..6ca1ecc2ca7f 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -172,7 +172,7 @@ protected function xmlToArray($xml) { } else { $array[$element] = $data; } - // Just a value + // Just a value } else { if ($totalElement > 1) { $array[$element][] = $this->xmlToArray($node); diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index a698c0f58c92..d220feeccd1a 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -427,8 +427,8 @@ protected function decodeContent() { } } - // Handle application/x-www-form-urlencoded for methods other than GET - // or post correctly + // Handle application/x-www-form-urlencoded for methods other than GET + // or post correctly } elseif ($this->method !== 'GET' && $this->method !== 'POST' && \strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php index 82460d6a780d..60711217edf2 100644 --- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php @@ -142,7 +142,8 @@ public function beforeController($controller, $methodName) { // CSRF check - also registers the CSRF token since the session may be closed later Util::callRegister(); if (!$this->reflector->hasAnnotation('NoCSRFRequired')) { - if (!$this->request->passesCSRFCheck() && $this->request->getHeader("Authorization") === null) { + $hasNoAuthHeader = ($this->request->getHeader("Authorization") === null || trim($this->request->getHeader("Authorization")) === ''); + if (!$this->request->passesCSRFCheck() && $hasNoAuthHeader) { throw new CrossSiteRequestForgeryException(); } } diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php index 1899220dd075..2f3ac967e7ce 100644 --- a/lib/private/Authentication/TwoFactorAuth/Manager.php +++ b/lib/private/Authentication/TwoFactorAuth/Manager.php @@ -33,6 +33,7 @@ use OCP\ILogger; use OCP\ISession; use OCP\IUser; +use OCP\IGroupManager; class Manager { public const SESSION_UID_KEY = 'two_factor_auth_uid'; @@ -43,6 +44,9 @@ class Manager { /** @var ISession */ private $session; + /** @var IGroupManager */ + private $groupManager; + /** @var IConfig */ private $config; @@ -55,13 +59,15 @@ class Manager { /** * @param AppManager $appManager * @param ISession $session + * @param IGroupManager $groupManager * @param IConfig $config * @param IRequest $request * @param ILogger $logger */ - public function __construct(AppManager $appManager, ISession $session, IConfig $config, IRequest $request, ILogger $logger) { + public function __construct(AppManager $appManager, ISession $session, IGroupManager $groupManager, IConfig $config, IRequest $request, ILogger $logger) { $this->appManager = $appManager; $this->session = $session; + $this->groupManager = $groupManager; $this->config = $config; $this->request = $request; $this->logger = $logger; @@ -74,10 +80,29 @@ public function __construct(AppManager $appManager, ISession $session, IConfig $ * @return boolean */ public function isTwoFactorAuthenticated(IUser $user) { + if ($this->isTwoFactorEnforcedForUser($user)) { + return \count($this->getProviders($user)) > 0; + } $twoFactorEnabled = ((int) $this->config->getUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 0)) === 0; return $twoFactorEnabled && \count($this->getProviders($user)) > 0; } + public function isTwoFactorEnforcedForUser(IUser $user) { + if ($this->config->getAppValue('core', 'enforce_2fa', 'no') !== 'yes') { + return false; + } + + $enforce2faExcludedGroups = \json_decode($this->config->getAppValue('core', 'enforce_2fa_excluded_groups', '[]'), true); + if (!empty($enforce2faExcludedGroups)) { + foreach ($enforce2faExcludedGroups as $group) { + if ($this->groupManager->isInGroup($user->getUID(), $group)) { + return false; + } + } + } + return true; + } + /** * Disable 2FA checks for the given user * @@ -135,6 +160,14 @@ public function getProviders(IUser $user) { } } + // if 2-factor is enforced, we must not filter out providers that + // might not be enabled or configured. The providers are expected + // to handle this problem on their own, usually by allowing + // configuration (at least partially) in the challenge page. + if ($this->isTwoFactorEnforcedForUser($user)) { + return $providers; + } + return \array_filter($providers, function ($provider) use ($user) { /* @var $provider IProvider */ return $provider->isTwoFactorAuthEnabledForUser($user); diff --git a/lib/private/DB/Adapter.php b/lib/private/DB/Adapter.php index 734b5acd0ce1..7e55f45fad3b 100644 --- a/lib/private/DB/Adapter.php +++ b/lib/private/DB/Adapter.php @@ -81,7 +81,7 @@ public function unlockTable() { } /** - * Insert a row if the matching row does not exists. + * Insert a row if the matching row does not exist. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) * @param array $input data that should be inserted into the table (column name => value) diff --git a/lib/private/DB/AdapterSqlite.php b/lib/private/DB/AdapterSqlite.php index 898f482a4b8f..dfb616aef8d5 100644 --- a/lib/private/DB/AdapterSqlite.php +++ b/lib/private/DB/AdapterSqlite.php @@ -48,7 +48,7 @@ public function fixupStatement($statement) { } /** - * Insert a row if the matching row does not exists. + * Insert a row if the matching row does not exist. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) * @param array $input data that should be inserted into the table (column name => value) diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index 46d3ac2a18ad..bbb97a7a30b4 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -262,7 +262,7 @@ public function realLastInsertId($seqName = null) { } /** - * Insert a row if the matching row does not exists. + * Insert a row if the matching row does not exist. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) * @param array $input data that should be inserted into the table (column name => value) diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 32c7998f482c..9c0b6e418c2a 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -948,7 +948,7 @@ public function getIncomplete() { * get the path of a file on this storage by it's file id * * @param int $id the file id of the file or folder to search - * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache + * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exist within this cache */ public function getPathById($id) { if (!isset(self::$path_cache[(int)$id])) { diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 4265413e6766..454e4062ac41 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -256,7 +256,7 @@ public function rename($path1, $path2) { } if (!$this->file_exists($path1)) { - \OCP\Util::writeLog('core', 'unable to rename, file does not exists : ' . $path1, \OCP\Util::ERROR); + \OCP\Util::writeLog('core', 'unable to rename, file does not exist : ' . $path1, \OCP\Util::ERROR); return false; } diff --git a/lib/private/Files/Storage/Wrapper/Checksum.php b/lib/private/Files/Storage/Wrapper/Checksum.php index a187acaae7a8..b405f14ad1f6 100644 --- a/lib/private/Files/Storage/Wrapper/Checksum.php +++ b/lib/private/Files/Storage/Wrapper/Checksum.php @@ -64,7 +64,7 @@ public function fopen($path, $mode) { $requirement = $this->getChecksumRequirement($path, $mode); if ($requirement === self::PATH_NEW_OR_UPDATED) { - return \OC\Files\Stream\Checksum::wrap($stream, $path); + return \OC\Files\Stream\Checksum::wrap($stream, $path, $mode); } // If file is without checksum we save the path and create @@ -73,7 +73,7 @@ public function fopen($path, $mode) { // the checksum is then saved to oc_filecache for subsequent // retrieval (see onClose()) if ($requirement == self::PATH_IN_CACHE_WITHOUT_CHECKSUM) { - $checksumStream = \OC\Files\Stream\Checksum::wrap($stream, $path); + $checksumStream = \OC\Files\Stream\Checksum::wrap($stream, $path, $mode); return CallbackWrapper::wrap( $checksumStream, null, @@ -167,7 +167,7 @@ private static function getChecksumsInDbFormat($path) { /** * check if the file metadata should not be fetched * NOTE: files with a '.part' extension are ignored as well! - * prevents unfinished put requests to fetch metadata which does not exists + * prevents unfinished put requests to fetch metadata which does not exist * * @param string $file * @return boolean @@ -187,7 +187,7 @@ public static function isPartialFile($file) { */ public function file_put_contents($path, $data) { $memoryStream = \fopen('php://memory', 'r+'); - $checksumStream = \OC\Files\Stream\Checksum::wrap($memoryStream, $path); + $checksumStream = \OC\Files\Stream\Checksum::wrap($memoryStream, $path, "wb"); \fwrite($checksumStream, $data); \fclose($checksumStream); diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index 2aa83acf6cb7..906568d088da 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -310,17 +310,17 @@ public function rename($path1, $path2) { if ($renameOk) { $sourceKeyDeleteOk = $this->keyStorage->deleteAllFileKeys($source); if (!$sourceKeyDeleteOk) { - $this->logger->error("Renaming {$path1} to {$path2} succeeded, but key {$target} wasn't deleted from the original location in {$source}"); + $this->logger->error("Renaming {$path1} to {$path2} succeeded, but key for file {$target} wasn't removed from its original location"); } } else { $this->logger->error("Renaming {$path1} to {$path2} failed"); $targetKeyDeleteOk = $this->keyStorage->deleteAllFileKeys($target); if (!$targetKeyDeleteOk) { - $this->logger->error("Copied key {$source} wasn't removed from the target location in {$target}"); + $this->logger->error("Copied key for file {$source} wasn't removed from its target location"); } } } else { - $this->logger->error("Failed to copied keys from {$source} to {$target} while renaming {$path1} to {$path2}"); + $this->logger->error("Failed to copy keys while renaming {$path1} to {$path2}"); } return $renameOk && $copyKeysOk; diff --git a/lib/private/Files/Stream/Checksum.php b/lib/private/Files/Stream/Checksum.php index 622bde5610a5..49e2f7c78a06 100644 --- a/lib/private/Files/Stream/Checksum.php +++ b/lib/private/Files/Stream/Checksum.php @@ -68,9 +68,10 @@ public function __construct(array $algos = ['sha1', 'md5', 'adler32']) { /** * @param $source * @param $path + * @param $mode the fopen's mode of the source * @return resource */ - public static function wrap($source, $path) { + public static function wrap($source, $path, $mode) { $context = \stream_context_create([ 'occhecksum' => [ 'source' => $source, @@ -78,11 +79,9 @@ public static function wrap($source, $path) { ] ]); - // need to check the underlying stream's mode - // The `wrapSource` will use 'r+' by default, so the - // `stream_open` function might use that mode wrongly. - $meta = \stream_get_meta_data($source); - $mode = $meta['mode'] ?? 'r+'; + // Assume that the underlying stream is compatible with the requested mode. + // Getting the mode of the source might not be reliable due to additional + // wrappers masking it, usually forcing it to be "r+" return Wrapper::wrapSource( $source, $context, diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php index 9f5318101cb8..7ec3b2d6cccd 100644 --- a/lib/private/Files/Stream/Encryption.php +++ b/lib/private/Files/Stream/Encryption.php @@ -298,7 +298,7 @@ public function stream_read($count) { $result .= \substr($this->cache, $blockPosition, $remainingLength); $this->position += $remainingLength; $count = 0; - // otherwise remainder of current block is fetched, the block is flushed and the position updated + // otherwise remainder of current block is fetched, the block is flushed and the position updated } else { $result .= \substr($this->cache, $blockPosition); $this->flush(); @@ -359,8 +359,8 @@ public function stream_write($data) { $this->position += $remainingLength; $length += $remainingLength; $data = ''; - // if $data doesn't fit the current block, the fill the current block and reiterate - // after the block is filled, it is flushed and $data is updatedxxx + // if $data doesn't fit the current block, the fill the current block and reiterate + // after the block is filled, it is flushed and $data is updatedxxx } else { $this->cache = \substr($this->cache, 0, $blockPosition) . \substr($data, 0, $this->unencryptedBlockSize - $blockPosition); diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index aa13e58e39b0..cd6b375c2a6b 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -869,14 +869,14 @@ public function rename($path1, $path2) { } else { $result = false; } - // moving a file/folder within the same mount point + // moving a file/folder within the same mount point } elseif ($storage1 === $storage2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { $result = false; } - // moving a file/folder between storages (from $storage1 to $storage2) + // moving a file/folder between storages (from $storage1 to $storage2) } else { $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); } diff --git a/lib/private/Lock/DBLockingProvider.php b/lib/private/Lock/DBLockingProvider.php index deb0cc66a43b..470b4f7cf248 100644 --- a/lib/private/Lock/DBLockingProvider.php +++ b/lib/private/Lock/DBLockingProvider.php @@ -107,7 +107,7 @@ public function __construct(IDBConnection $connection, ILogger $logger, ITimeFac } /** - * Insert a file locking row if it does not exists. + * Insert a file locking row if it does not exist. * * @param string $path * @param int $lock diff --git a/lib/private/Log.php b/lib/private/Log.php index a1fba6eb0c04..6739d7c09088 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -81,6 +81,7 @@ class Log implements ILogger { 'validateUserPass', 'loginWithPassword', 'createSessionToken', + 'loginInOwnCloud', // TokenProvider 'getToken', @@ -392,11 +393,15 @@ public function log($level, $message, array $context = []) { if ($level >= $minLevel) { $logger = $this->logger; - // check if logger supports extra fields + // check if logger supports extra fields, and which method is available if (!empty($extraFields) && \is_callable([$logger, 'writeExtra'])) { \call_user_func([$logger, 'writeExtra'], $app, $formattedMessage, $level, $logConditionFile, $extraFields); - } else { + } elseif (\is_callable([$logger, 'write'])) { \call_user_func([$logger, 'write'], $app, $formattedMessage, $level, $logConditionFile); + } elseif (\is_callable([$logger, 'log'])) { + \call_user_func([$logger, 'log'], $level, $formattedMessage, $context); + } else { + throw new \Exception("No logger method available. Trying to log message '$formattedMessage'."); } } diff --git a/lib/private/PreviewCleanup.php b/lib/private/PreviewCleanup.php index 94932fb8e30f..2b0c5f0b4ae1 100644 --- a/lib/private/PreviewCleanup.php +++ b/lib/private/PreviewCleanup.php @@ -77,12 +77,13 @@ public function process(bool $all = false, int $chunkSize = 1000, \Closure $prog private function queryPreviewsToDelete(int $startFileId = 0, int $chunkSize = 1000): array { $isOracle = ($this->connection->getDatabasePlatform() instanceof OraclePlatform); - $sql = "select `fileid`, `name`, `user_id` from `*PREFIX*filecache` `fc` -join `*PREFIX*mounts` on `storage` = `storage_id` -where `parent` in (select `fileid` from `*PREFIX*filecache` where `storage` in (select `numeric_id` from `oc_storages` where `id` like 'home::%' or `id` like 'object::user:%') and `path` = 'thumbnails') - and `fc`.`fileid` not in (select `fileid` from `*PREFIX*filecache` where `fc`.`name` = CAST(`*PREFIX*filecache`.`fileid` as CHAR(24))) - and `fc`.`fileid` > ? - order by `user_id`, `fileid`"; + $sql = "select `thumb`.`fileid`, `thumb`.`name`, `user_id` + from `*PREFIX*mounts`, `*PREFIX*filecache` `thumb` left join `*PREFIX*filecache` `file` on `thumb`.`name` = trim(cast(`file`.`fileid` as CHAR(24))) +where `thumb`.`parent` in (select `fileid` from `*PREFIX*filecache` where `storage` in (select `numeric_id` from `*PREFIX*storages` where `id` like 'home::%' or `id` like 'object::user:%') and `path` = 'thumbnails') + and `*PREFIX*mounts`.`storage_id` = `thumb`.`storage` + and `file`.`fileid` is null + and `thumb`.`fileid` > ? + order by `user_id`, `thumb`.`fileid`"; if ($isOracle) { $sql = "select * from ($sql) where ROWNUM <= $chunkSize"; diff --git a/lib/private/Server.php b/lib/private/Server.php index 75bfb10398a7..93e389a752c6 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -402,7 +402,14 @@ public function __construct($webRoot, \OC\Config $config) { }); $this->registerService('\OC\Authentication\TwoFactorAuth\Manager', function (Server $c) { - return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig(), $c->getRequest(), $c->getLogger()); + return new \OC\Authentication\TwoFactorAuth\Manager( + $c->getAppManager(), + $c->getSession(), + $c->getGroupManager(), + $c->getConfig(), + $c->getRequest(), + $c->getLogger() + ); }); $this->registerService('NavigationManager', function (Server $c) { diff --git a/lib/private/Settings/SettingsManager.php b/lib/private/Settings/SettingsManager.php index 1c7220cf072f..f1c79447e23d 100644 --- a/lib/private/Settings/SettingsManager.php +++ b/lib/private/Settings/SettingsManager.php @@ -49,6 +49,7 @@ use OC\Settings\Panels\Personal\Tokens; use OC\Settings\Panels\Personal\Cors; use OC\Settings\Panels\Personal\Quota; +use OC\Settings\Panels\Admin\Enforce2fa; use OC\Settings\Panels\Admin\BackgroundJobs; use OC\Settings\Panels\Admin\Certificates; use OC\Settings\Panels\Admin\Encryption; @@ -236,6 +237,7 @@ private function getBuiltInSections($type) { private function getBuiltInPanels($type) { if ($type === 'admin') { return [ + Enforce2fa::class, LegacyAdmin::class, BackgroundJobs::class, Logging::class, diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index 690eee470b30..b7a1b6f44935 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -130,7 +130,7 @@ private function createDatabase($connection) { \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); } if (! \pg_fetch_row($result)) { - //The database does not exists... let's create it + //The database does not exist... let's create it $query = "CREATE DATABASE \"$e_name\" OWNER \"$e_user\""; $result = \pg_query($connection, $query); if (!$result) { diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php index 8583b6da6b33..908e27395382 100644 --- a/lib/private/Share/Constants.php +++ b/lib/private/Share/Constants.php @@ -31,6 +31,7 @@ class Constants { public const SHARE_TYPE_GUEST = 4; public const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it public const SHARE_TYPE_REMOTE = 6; + public const SHARE_TYPE_REMOTE_GROUP = 7; public const CONVERT_SHARE_TYPE_TO_STRING = [ self::SHARE_TYPE_USER => 'user', @@ -39,6 +40,7 @@ class Constants { self::SHARE_TYPE_GUEST => 'guest', self::SHARE_TYPE_CONTACT => 'contact', self::SHARE_TYPE_REMOTE => 'remote', + self::SHARE_TYPE_REMOTE_GROUP => 'remote_group', ]; /** diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index eb9b25b9a8cd..3340519450c3 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -1108,9 +1108,9 @@ public static function unshare($itemType, $itemSource, $shareType, $shareWith, $ // delete the item with the expected share_type and owner if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) { $toDelete = $item; - // if there is more then one result we don't have to delete the children - // but update their parent. For group shares the new parent should always be - // the original group share and not the db entry with the unique name + // if there is more then one result we don't have to delete the children + // but update their parent. For group shares the new parent should always be + // the original group share and not the db entry with the unique name } elseif ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) { $newParent = $item['parent']; } else { diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index bac7968de6ec..4a69bd7f4c84 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -52,6 +52,7 @@ use OCP\Share\IAttributes; use OCP\Share\IManager; use OCP\Share\IProviderFactory; +use OC\Share20\Exception\ProviderException; use OCP\Share\IShare; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\GenericEvent; @@ -266,7 +267,7 @@ protected function generalChecks(\OCP\Share\IShare $share) { if ($share->getSharedWith() !== null) { throw new \InvalidArgumentException('SharedWith should be empty'); } - } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE || $share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) { if ($share->getSharedWith() === null) { throw new \InvalidArgumentException('SharedWith should not be empty'); } @@ -1529,10 +1530,32 @@ public function getShareByToken($token) { // If it is not a link share try to fetch a federated share by token if ($share === null) { - $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE); - $share = $provider->getShareByToken($token); + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE); + $share = $provider->getShareByToken($token); + } catch(ShareNotFound $ex) { + $this->logger->error( + "shared file not found by token: $token for federated user share, try to check federated group share.", + ['app' => __CLASS__] + ); + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE_GROUP); + if ($provider !== null) { + $share = $provider->getShareByToken($token); + } + } catch (ShareNotFound $ex) { + $this->logger->error( + "shared file not found by token: $token for federated group share", + ['app' => __CLASS__] + ); + } catch (ProviderException $ex) { + $this->logger->logException( + $ex, + ['app' => __CLASS__] + ); + } + } } - if (self::shareHasExpired($share)) { $this->activityManager->setAgentAuthor(IEvent::AUTOMATION_AUTHOR); try { diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 243a702cc564..ae9478065bf6 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -130,7 +130,8 @@ public function getProviderForType($shareType) { $shareType === \OCP\Share::SHARE_TYPE_GROUP || $shareType === \OCP\Share::SHARE_TYPE_LINK) { $provider = $this->defaultShareProvider(); - } elseif ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + } elseif ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || + $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) { $provider = $this->federatedShareProvider(); } diff --git a/lib/private/TempManager.php b/lib/private/TempManager.php index ec01f61f7edc..cfa5ae9b6006 100644 --- a/lib/private/TempManager.php +++ b/lib/private/TempManager.php @@ -28,29 +28,30 @@ namespace OC; +use Exception; +use OC_Helper; use OCP\ILogger; use OCP\IConfig; use OCP\ITempManager; +use UnexpectedValueException; class TempManager implements ITempManager { /** @var string[] Current temporary files and folders, used for cleanup */ - protected $current = []; - /** @var string i.e. /tmp on linux systems */ - protected $tmpBaseDir; - /** @var ILogger */ - protected $log; - /** @var IConfig */ - protected $config; + protected array $current = []; + /** @var ?string i.e. /tmp on linux systems */ + protected ?string $tmpBaseDir = null; + protected ILogger $logger; + protected IConfig $config; /** Prefix */ public const TMP_PREFIX = 'oc_tmp_'; /** - * @param \OCP\ILogger $logger - * @param \OCP\IConfig $config + * @param ILogger $logger + * @param IConfig $config */ public function __construct(ILogger $logger, IConfig $config) { - $this->log = $logger; + $this->logger = $logger; $this->config = $config; $this->tmpBaseDir = $this->getTempBaseDir(); } @@ -63,7 +64,7 @@ public function __construct(ILogger $logger, IConfig $config) { * @param string $postFix Postfix appended to the temporary file name, may be user controlled * @return string */ - private function buildFileNameWithSuffix($absolutePath, $postFix = '') { + private function buildFileNameWithSuffix(string $absolutePath, string $postFix = ''): string { if ($postFix !== '') { $postFix = '.' . \ltrim($postFix, '.'); $postFix = \str_replace(['\\', '/'], '', $postFix); @@ -81,7 +82,7 @@ private function buildFileNameWithSuffix($absolutePath, $postFix = '') { */ public function getTemporaryFile($postFix = '') { if (\is_writable($this->tmpBaseDir)) { - // To create an unique file and prevent the risk of race conditions + // To create a unique file and prevent the risk of race conditions // or duplicated temporary files by other means such as collisions // we need to create the file using `tempnam` and append a possible // postfix to it later @@ -92,22 +93,23 @@ public function getTemporaryFile($postFix = '') { // temporary file if ($postFix !== '') { $fileNameWithPostfix = $this->buildFileNameWithSuffix($file, $postFix); + $old_umask = \umask(0077); \touch($fileNameWithPostfix); - \chmod($fileNameWithPostfix, 0600); + \umask($old_umask); $this->current[] = $fileNameWithPostfix; return $fileNameWithPostfix; } return $file; - } else { - $this->log->warning( - 'Can not create a temporary file in directory {dir}. Check it exists and has correct permissions', - [ - 'dir' => $this->tmpBaseDir, - ] - ); - return false; } + + $this->logger->warning( + 'Can not create a temporary file in directory {dir}. Check it exists and has correct permissions', + [ + 'dir' => $this->tmpBaseDir, + ] + ); + return false; } /** @@ -118,7 +120,7 @@ public function getTemporaryFile($postFix = '') { */ public function getTemporaryFolder($postFix = '') { if (\is_writable($this->tmpBaseDir)) { - // To create an unique directory and prevent the risk of race conditions + // To create a unique directory and prevent the risk of race conditions // or duplicated temporary files by other means such as collisions // we need to create the file using `tempnam` and append a possible // postfix to it later @@ -131,15 +133,15 @@ public function getTemporaryFolder($postFix = '') { $this->current[] = $path; return $path . '/'; - } else { - $this->log->warning( - 'Can not create a temporary folder in directory {dir}. Check it exists and has correct permissions', - [ - 'dir' => $this->tmpBaseDir, - ] - ); - return false; } + + $this->logger->warning( + 'Can not create a temporary folder in directory {dir}. Check it exists and has correct permissions', + [ + 'dir' => $this->tmpBaseDir, + ] + ); + return false; } /** @@ -152,13 +154,13 @@ public function clean() { /** * @param string[] $files */ - protected function cleanFiles($files) { + protected function cleanFiles(array $files): void { foreach ($files as $file) { if (\file_exists($file)) { try { - \OC_Helper::rmdirr($file); - } catch (\UnexpectedValueException $ex) { - $this->log->warning( + OC_Helper::rmdirr($file); + } catch (UnexpectedValueException $ex) { + $this->logger->warning( "Error deleting temporary file/folder: {file} - Reason: {error}", [ 'file' => $file, @@ -182,13 +184,13 @@ public function cleanOld() { * * @return string[] */ - protected function getOldFiles() { + protected function getOldFiles(): array { $cutOfTime = \time() - 3600; $files = []; $dh = \opendir($this->tmpBaseDir); if ($dh) { while (($file = \readdir($dh)) !== false) { - if (\substr($file, 0, 7) === self::TMP_PREFIX) { + if (\strpos($file, self::TMP_PREFIX) === 0) { $path = $this->tmpBaseDir . '/' . $file; $mtime = \filemtime($path); if ($mtime < $cutOfTime) { @@ -204,9 +206,9 @@ protected function getOldFiles() { * Get the temporary base directory configured on the server * * @return string Path to the temporary directory or null - * @throws \UnexpectedValueException + * @throws UnexpectedValueException */ - public function getTempBaseDir() { + public function getTempBaseDir(): string { if ($this->tmpBaseDir) { return $this->tmpBaseDir; } @@ -237,12 +239,12 @@ public function getTempBaseDir() { } } - $temp = \tempnam(\dirname(__FILE__), ''); + $temp = \tempnam(__DIR__, ''); if (\file_exists($temp)) { \unlink($temp); return \dirname($temp); } - throw new \UnexpectedValueException('Unable to detect system temporary directory'); + throw new UnexpectedValueException('Unable to detect system temporary directory'); } /** @@ -251,16 +253,16 @@ public function getTempBaseDir() { * @param mixed $directory * @return bool */ - private function checkTemporaryDirectory($directory) { + private function checkTemporaryDirectory($directory): bool { // suppress any possible errors caused by is_writable // checks missing or invalid path or characters, wrong permissions etc try { - if (\is_writeable($directory)) { + if (\is_writable($directory)) { return true; } - } catch (\Exception $e) { + } catch (Exception $e) { } - $this->log->warning( + $this->logger->warning( 'Temporary directory {dir} is not present or writable', ['dir' => $directory] ); @@ -272,7 +274,7 @@ private function checkTemporaryDirectory($directory) { * * @param string $directory */ - public function overrideTempBaseDir($directory) { + public function overrideTempBaseDir(string $directory): void { $this->tmpBaseDir = $directory; } } diff --git a/lib/private/legacy/files.php b/lib/private/legacy/files.php index ad94112c62cc..1e44f2452557 100644 --- a/lib/private/legacy/files.php +++ b/lib/private/legacy/files.php @@ -80,7 +80,7 @@ private static function sendHeaders($filename, $name, array $rangeArray) { \header('Accept-Ranges: bytes', true); if (\count($rangeArray) > 1) { $type = 'multipart/byteranges; boundary='.self::getBoundary(); - // no Content-Length header here + // no Content-Length header here } else { \header(\sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true); OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1); diff --git a/lib/public/DB.php b/lib/public/DB.php index 658ccfa36795..fec2b9dfa801 100644 --- a/lib/public/DB.php +++ b/lib/public/DB.php @@ -60,7 +60,7 @@ public static function prepare($query, $limit=null, $offset=null) { } /** - * Insert a row if the matching row does not exists. + * Insert a row if the matching row does not exist. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) * @param array $input data that should be inserted into the table (column name => value) diff --git a/lib/public/Files/Cache/ICache.php b/lib/public/Files/Cache/ICache.php index 6de59fddf124..f2141639725b 100644 --- a/lib/public/Files/Cache/ICache.php +++ b/lib/public/Files/Cache/ICache.php @@ -248,7 +248,7 @@ public function getIncomplete(); * get the path of a file on this storage by it's file id * * @param int $id the file id of the file or folder to search - * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache + * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exist within this cache * @since 9.0.0 */ public function getPathById($id); diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index 662156cccd85..0b444cb6df8a 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -120,7 +120,7 @@ public function executeStatement($query, array $params = [], array $types = []); public function lastInsertId($table = null); /** - * Insert a row if the matching row does not exists. + * Insert a row if the matching row does not exist. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) * @param array $input data that should be inserted into the table (column name => value) diff --git a/resources/config/ca-bundle.crt b/resources/config/ca-bundle.crt index da637630d853..d3426c320926 100644 --- a/resources/config/ca-bundle.crt +++ b/resources/config/ca-bundle.crt @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Thu Feb 23 15:38:48 2023 GMT +## Certificate data from Mozilla as of: Tue Jun 6 12:15:39 2023 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +14,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6 +## SHA256: c47475103fb05bb562bbadff0d1e72346b03236154e1448a6ca191b740f83507 ## @@ -603,26 +603,6 @@ NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- -Hongkong Post Root CA 1 -======================= ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT -DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx -NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n -IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 -ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr -auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh -qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY -V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV -HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i -h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio -l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei -IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps -T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT -c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== ------END CERTIFICATE----- - SecureSign RootCA11 =================== -----BEGIN CERTIFICATE----- @@ -1261,40 +1241,6 @@ Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -E-Tugra Certification Authority -=============================== ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w -DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls -ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw -NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx -QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl -cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD -DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd -hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K -CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g -ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ -BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 -E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz -rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq -jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 -dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK -kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO -XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 -VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo -a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc -dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV -KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT -Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 -8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G -C7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - T-TeleSec GlobalRoot Class 2 ============================ -----BEGIN CERTIFICATE----- @@ -3370,3 +3316,48 @@ BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e N9k= -----END CERTIFICATE----- + +BJCA Global Root CA1 +==================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG +EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK +Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG +A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD +DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm +CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS +sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn +P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW +yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj +eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn +MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b +OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh +GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK +H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB +AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ +dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8 +60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh +TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW +4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp +GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx +4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps +3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S +SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI= +-----END CERTIFICATE----- + +BJCA Global Root CA2 +==================== +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD +TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg +R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE +BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC +SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl +SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK +/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI +1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8 +W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g +UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- diff --git a/settings/Controller/UsersController.php b/settings/Controller/UsersController.php index 39adddd332e8..aadc712e335e 100644 --- a/settings/Controller/UsersController.php +++ b/settings/Controller/UsersController.php @@ -426,13 +426,13 @@ private function generateTokenAndSendMail($userId, $email) { * @return DataResponse */ public function create($username, $password, array $groups= [], $email='') { - if ($email !== '' && !$this->mailer->validateMailAddress($email)) { - return new DataResponse( - [ - 'message' => (string)$this->l10n->t('Invalid mail address') - ], - Http::STATUS_UNPROCESSABLE_ENTITY - ); + $resp = $this->validateString($username, 255); + if ($resp) { + return $resp; + } + $resp = $this->validateEMail($email, true); + if ($resp) { + return $resp; } $currentUser = $this->userSession->getUser(); @@ -939,16 +939,9 @@ public function setMailAddress($id, $mailAddress) { } } - if ($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) { - return new DataResponse( - [ - 'status' => 'error', - 'data' => [ - 'message' => (string)$this->l10n->t('Invalid mail address') - ] - ], - Http::STATUS_UNPROCESSABLE_ENTITY - ); + $resp = $this->validateEMail($mailAddress); + if ($resp) { + return $resp; } if (!$user) { @@ -1176,6 +1169,10 @@ public function sendEmail($userId, $mailAddress) { * @return JSONResponse */ public function setEmailAddress($id, $mailAddress) { + $resp = $this->validateEMail($mailAddress); + if ($resp) { + return $resp; + } $user = $this->userManager->get($id); '@phan-var \OC\Group\Manager $this->groupManager'; if ($this->isAdmin || @@ -1312,4 +1309,29 @@ public function setEnabled($id, $enabled) { Http::STATUS_OK ); } + + private function validateString(string $string, int $max) { + if (\strlen($string) > $max) { + return $this->buildUnprocessableEntityResponse((string)$this->l10n->t('Data too long')); + } + } + + private function validateEMail(string $email, bool $allowEmpty = false): ?DataResponse { + if ($allowEmpty && $email === '') { + return null; + } + if ($email !== '' && !$this->mailer->validateMailAddress($email)) { + return $this->buildUnprocessableEntityResponse((string)$this->l10n->t('Invalid mail address')); + } + return null; + } + + private function buildUnprocessableEntityResponse(string $message): DataResponse { + return new DataResponse( + [ + 'message' => $message + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } } diff --git a/settings/Panels/Admin/Enforce2fa.php b/settings/Panels/Admin/Enforce2fa.php new file mode 100644 index 000000000000..832a9523f5d9 --- /dev/null +++ b/settings/Panels/Admin/Enforce2fa.php @@ -0,0 +1,49 @@ + + * + */ + +namespace OC\Settings\Panels\Admin; + +use OCP\Settings\ISettings; +use OCP\Template; +use OCP\IConfig; + +class Enforce2fa implements ISettings { + /** @var IConfig */ + protected $config; + + public function __construct(IConfig $config) { + $this->config = $config; + } + + public function getPriority() { + return 50; + } + + public function getPanel() { + $enforce2faExcludedGroups = \json_decode($this->config->getAppValue('core', 'enforce_2fa_excluded_groups', '[]'), true); + $tmpl = new Template('settings', 'panels/admin/enforce2fa'); + $tmpl->assign('enforce2fa', $this->config->getAppValue('core', 'enforce_2fa', 'no') === 'yes'); + $tmpl->assign('enforce2faExcludedGroups', \implode('|', $enforce2faExcludedGroups)); + return $tmpl; + } + + public function getSectionID() { + return 'security'; + } +} diff --git a/settings/js/panels/enforce2fa.js b/settings/js/panels/enforce2fa.js new file mode 100644 index 000000000000..55c46cc16fe6 --- /dev/null +++ b/settings/js/panels/enforce2fa.js @@ -0,0 +1,19 @@ +$(document).ready(function() { + + var enforce2faGroupsList = $('#enforce_2fa_excluded_groups'); + OC.Settings.setupGroupsSelect(enforce2faGroupsList); + enforce2faGroupsList.change(function(ev) { + OC.AppConfig.setValue('core', 'enforce_2fa_excluded_groups', JSON.stringify(ev.val || [])); + }); + + $('#enforce_2fa').change(function() { + var name = $(this).attr('name'); + var value; + if (this.checked) { + value = 'yes'; + } else { + value = 'no'; + } + OC.AppConfig.setValue('core', name, value); + }); +}); diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 2de24286dc90..359f4b98ae55 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -1108,6 +1108,8 @@ $(document).ready(function () { if ($('#CheckboxLastLogin').is(':checked')) { $("#userlist .lastLogin").show(); + } else { + $("#userlist .lastLogin").hide(); } // Option to display/hide the "Last Login" column $('#CheckboxLastLogin').click(function() { diff --git a/settings/l10n/af_ZA.js b/settings/l10n/af_ZA.js index 912dd01fe353..b4c1427f91c8 100644 --- a/settings/l10n/af_ZA.js +++ b/settings/l10n/af_ZA.js @@ -11,7 +11,6 @@ OC.L10N.register( "test email settings" : "toets e-posinstellings", "Email sent" : "E-pos gestuur", "Your %s account was created" : "U %s-rekening is geskep", - "Invalid mail address" : "Ongeldige posadres", "A user with that name already exists." : "’n Gebruiker met daardie naam bestaan reeds.", "Unable to create user." : "Kan nie gebruiker skep nie.", "Unable to delete user." : "Kan nie gebruiker skrap nie.", @@ -24,6 +23,7 @@ OC.L10N.register( "Unable to change full name" : "Kan nie u volle naam verander nie", "%s email address changed successfully" : "%s e-posadres is suksesvol verander", "Unable to enable/disable user." : "Kan nie gebruiker de-/aktiveer nie.", + "Invalid mail address" : "Ongeldige posadres", "Create" : "Skep", "Change" : "Verander", "Delete" : "Skrap", diff --git a/settings/l10n/af_ZA.json b/settings/l10n/af_ZA.json index d797eef0e2dd..fb107ac95fcc 100644 --- a/settings/l10n/af_ZA.json +++ b/settings/l10n/af_ZA.json @@ -9,7 +9,6 @@ "test email settings" : "toets e-posinstellings", "Email sent" : "E-pos gestuur", "Your %s account was created" : "U %s-rekening is geskep", - "Invalid mail address" : "Ongeldige posadres", "A user with that name already exists." : "’n Gebruiker met daardie naam bestaan reeds.", "Unable to create user." : "Kan nie gebruiker skep nie.", "Unable to delete user." : "Kan nie gebruiker skrap nie.", @@ -22,6 +21,7 @@ "Unable to change full name" : "Kan nie u volle naam verander nie", "%s email address changed successfully" : "%s e-posadres is suksesvol verander", "Unable to enable/disable user." : "Kan nie gebruiker de-/aktiveer nie.", + "Invalid mail address" : "Ongeldige posadres", "Create" : "Skep", "Change" : "Verander", "Delete" : "Skrap", diff --git a/settings/l10n/ar.js b/settings/l10n/ar.js index 8a9188c0328d..ddea966f04a6 100644 --- a/settings/l10n/ar.js +++ b/settings/l10n/ar.js @@ -19,6 +19,7 @@ OC.L10N.register( "Unable to delete group." : "تعذّر حذف مجموعة.", "Saved" : "تم الحفظ", "log-level out of allowed range" : "مستوى السجل خارج النطاق المسموح به", + "Updated log level" : "مستوى السجل المحدث", "Invalid email address" : "عنوان بريد إلكتروني غير صالح", "test email settings" : "إعدادات رسائل البريد الإلكتروني الاختبار", "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "حدثت مشكلة أثناء إرسال البريد الإلكتروني. يُرجى مراجعة إعداداتك. (خطأ: %s)", @@ -27,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "لا يمكن تغيير عنوان البريد الإلكتروني لأن المستخدم غير موجود", "Couldn't change the email address because the token is invalid" : "لا يمكن تغيير عنوان البريد الإلكتروني لأن الرمز المميز غير صالح", "Your %s account was created" : "تم إنشاء حساب %s", - "Invalid mail address" : "عنوان بريد إلكتروني غير صالح", "A user with that name already exists." : "يوجد مستخدم بهذا الاسم بالفعل.", "Unable to create user." : "تعذّر إنشاء مستخدم.", "The token provided is invalid." : "الرمز المميز المقدم غير صالح.", @@ -52,6 +52,8 @@ OC.L10N.register( "%s email address changed successfully" : "تم تغيير عنوان البريد الإلكتروني لـ %s بنجاح", "Couldn't send email address change notification mail. Please contact your administrator." : "لا يمكن إرسال رسالة إشعار تغيير عنوان البريد الإلكتروني. يُرجى الاتصال بمسؤولك.", "Unable to enable/disable user." : "تعذّر تمكين/تعطيل المستخدم.", + "Data too long" : "البيانات طويلة جدا", + "Invalid mail address" : "عنوان بريد إلكتروني غير صالح", "Owner language" : "لغة المالك", "Create" : "إنشاء", "Change" : "تغيير", @@ -122,11 +124,14 @@ OC.L10N.register( "undo" : "تراجع", "You are about to delete a group. This action can't be undone and is permanent. Are you sure that you want to permanently delete {groupName}?" : "أنت على وشك حذف مجموعة. هذا الإجراء نهائي ولا يمكن التراجع عنه. هل أنت متأكد من رغبتك في حذف {groupName} نهائيًا؟", "Delete group" : "حذف مجموعة", + "Resend invitation email" : "إعادة إرسال البريد الإلكتروني للدعوة", "never" : "أبدًا", "unknown" : "غير معروف", "deleted {userName}" : "{userName} محذوف", "You are about to delete a user. This action can't be undone and is permanent. All user data, files and shares will be deleted. Are you sure that you want to permanently delete {userName}?" : "أنت على وشك حذف مستخدم. هذا الإجراء نهائي ولا يمكن التراجع عنه. وسيتم حذف جميع بيانات المستخدم وملفاته ومشاركاته. هل أنت متأكد من رغبتك في حذف {userName} نهائيًا؟", "Delete user" : "حذف المستخدم", + "The invitation email for this user has been resent" : "تمت إعادة إرسال البريد الإلكتروني للدعوة لهذا المستخدم", + "The invitation email for this user could not be resent" : "تعذر إعادة إرسال البريد الإلكتروني للدعوة لهذا المستخدم", "Group already exists" : "المجموعة موجودة مسبقاً", "add group" : "إضافة مجموعة", "Invalid quota value \"{val}\"" : "قيمة الحصة النسبية غير صالحة \"{val}\"", @@ -209,6 +214,7 @@ OC.L10N.register( "Allow users to share file via social media" : "السماح للمستخدمين بمشاركة الملف عبر وسائل التواصل الاجتماعي", "Set default expiration date for user shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي لمشاركات المستخدم", "Set default expiration date for group shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي لمشاركات المجموعة", + "Set default expiration date for federated shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي للأسهم الموحدة", "Automatically accept new incoming local user shares" : "قبول مشاركات المستخدمين المحليين الجديدة الواردة تلقائيًا", "Allow resharing" : "السماح بإعادة المشاركة", "Allow sharing with groups" : "السماح بالمشاركة مع المجموعات", @@ -232,6 +238,7 @@ OC.L10N.register( "Enterprise license key" : "مفتاح ترخيص Enterprise", "Enter a new license:" : "أدخل ترخيصًا جديدًا:", "Save" : "حفظ", + "Remove current license key" : "إزالة مفتاح الترخيص الحالي", "Everything (fatal issues, errors, warnings, info, debug)" : "كل شيء (مشكلات فادحة، وأخطاء، وتحذيرات، ومعلومات، وتصحيح الأخطاء)", "Info, warnings, errors and fatal issues" : "المعلومات، والتحذيرات، والأخطاء، والمشكلات الفادحة", "Warnings, errors and fatal issues" : "التحذيرات، والأخطاء، والمشكلات الفادحة", @@ -262,17 +269,22 @@ OC.L10N.register( "SMTP Username" : "اسم مستخدم SMTP", "SMTP Password" : "كلمة مرور SMTP", "Store credentials" : "تخزين بيانات الاعتماد", + "Test receiver email" : "اختبار البريد الإلكتروني للمستلم", "Test email settings" : "إعدادات رسائل البريد الإلكتروني الاختبار", "Send email" : "إرسال رسالة بريد إلكتروني", "Manual File Locking" : "قفل الملفات بشكل يدوي", "Default timeout for the locks if not specified (in seconds)" : "المهلة الافتراضية للأقفال في حال لم يقع تحديدها (بالثواني)", "Maximum timeout for the locks (in seconds)" : "المهلة القصوى للأقفال (بالثواني)", + "Enable manual file locking in the web interface" : "تمكين تأمين الملفات يدويا في واجهة الويب", + "Allow users in the following groups to unlock files they have access to:" : "السماح للمستخدمين في المجموعات التالية بإلغاء تأمين الملفات التي يمكنهم الوصول إليها:", + "Users in these groups can unlock files even if they are not the owner of the lock." : "يمكن للمستخدمين في هذه المجموعات إلغاء تأمين الملفات حتى لو لم يكونوا مالك القفل.", "Security & setup warnings" : "تحذيرات الأمان والضبط", "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "لا يبدو أنه تم إعداد php بشكل صحيح للاستعلام عن متغيرات بيئة النظام. ويُرجع الاختبار مع getenv(\"PATH\") استجابة فارغة فقط.", "Please check the installation documentation ↗ for php configuration notes and the php configuration of your server, especially when using php-fpm." : "يُرجى فحص مستندات التثبيت ↗ للاطلاع على ملاحظات تكوين php وتكوين php للخادم، لا سيما عند استخدام php-fpm.", "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "تم تفعيل تكوين للقراءة فقط. ويمنع ذلك ضبط بعض التكوينات عبر واجهة الويب. وبالإضافة إلى ذلك، يجب أن يكون الملف قابلًا للكتابة يدويًا لكل تحديث.", "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "تم إعداد PHP على ما يبدو لإزالة كتل المستند المضمنة. وسيجعل ذلك العديد من التطبيقات الأساسية غير قابلة للوصول.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "من المحتمل أن يحدث ذلك بسبب وجود ذاكرة تخزين مؤقت/مسرّع مثل Zend OPcache أو eAccelerator.", + "Your database does not run with \"READ COMMITTED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "لا تعمل قاعدة البيانات الخاصة بك مع مستوى عزل المعاملات \"قراءة ملتزمة\". يمكن أن يتسبب هذا في حدوث مشكلات عند تنفيذ إجراءات متعددة بالتوازي.", "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "تم تثبيت %1$s إصدار أقل %2$s، وللحصول على مزيد من الاستقرار والأداء المميز، نوصي بالتحديث إلى إصدار %1$s جديد.", "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "وحدة PHP‏ \"fileinfo\" مفقودة. نوصي بشدة بتفعيل هذه الوحدة لتحقيق أفضل النتائج مع خاصية اكتشاف نوع mime.", "Transactional file locking is disabled, this might lead to issues with race conditions. Enable 'filelocking.enabled' in config.php to avoid these problems. See the documentation ↗ for more information." : "تم تعطيل تأمين ملف المعاملات، وقد يؤدي ذلك إلى حدوث مشكلات حالات التعارض. يُرجى تمكين \"filelocking.enabled\" في config.php لتجنب هذه المشكلات. انظر المستندات ↗ لمزيد من المعلومات.", @@ -299,6 +311,7 @@ OC.L10N.register( "Desktop client" : "عميل سطح المكتب", "Android app" : "تطبيق Android", "iOS app" : "تطبيق iOS", + "If you want to support the project\n\t\t\tjoin development\n\t\t\tor\n\t\t\tspread the word!" : "إذا كنت ترغب في دعم المشروع\nانضم إلى التطوير\nأو\nانشر الكلمة!", "Show First Run Wizard again" : "عرض تشغيل المعالج مرة أخرى أولًا", "White-listed Domains" : "المجالات المدرجة في القائمة البيضاء", "No Domains." : "لا توجد مجالات.", @@ -330,6 +343,8 @@ OC.L10N.register( "New password" : "كلمة مرور جديدة", "Change password" : "تغيير كلمة المرور", "Help translate" : "ترجمة التعليمات", + "Our imprint conditions:" : "شروط بصمتنا:", + "Our Privacy Policy conditions:" : "شروط سياسة الخصوصية الخاصة بنا:", "You are using %s" : "أنت تستخدم %s", "You are using %s of %s (%s %%)" : "أنت تستخدم %s من %s (%s %%)", "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}AGPL{linkclose}." : "طوّره {communityopen}مجتمع ownCloud {linkclose}، {githubopen}كود المصدر{linkclose} مرخص بموجب {licenseopen}رخصة جنو أفيرو العمومية{linkclose}.", @@ -347,6 +362,7 @@ OC.L10N.register( "Use the credentials below to configure your app or device." : "استخدم بيانات الاعتماد أدناه لتكوين التطبيق أو الجهاز.", "Password / Token" : "كلمة المرور/الرمز المميز", "Done" : "تم", + "To access your files through WebDAV, please use the following URL:" : "للوصول إلى ملفاتك من خلال WebDAV ، يرجى استخدام عنوان URL التالي:", "Version" : "إصدار", "The activation link has expired. Click the button below to request a new one and complete the registration." : "انتهت صلاحية رابط التفعيل. انقر فوق الزر أدناه لطلب رابط جديد وأكمل التسجيل.", "Resend activation link" : "إعادة إرسال رابط التفعيل", @@ -360,6 +376,7 @@ OC.L10N.register( "Settings" : "الإعدادات", "Show enabled/disabled option" : "عرض الخيار المُمكَّن/المُعطَّل", "Show storage location" : "عرض مكان التخزين", + "Show creation time" : "إظهار وقت الإنشاء", "Show last log in" : "عرض آخر عملية تسجيل الدخول", "Show user backend" : "عرض الواجهة الخلفية للمستخدم", "Set password for new users" : "تعيين كلمة مرور لمستخدمين جدد", @@ -383,6 +400,7 @@ OC.L10N.register( "Storage Location" : "مكان التخزين", "User Backend" : "الواجهة الخلفية للمستخدم", "Last Login" : "آخر تسجيل دخول", + "Creation Time" : "وقت الإنشاء", "change full name" : "تغيير الاسم الكامل", "set new password" : "تعيين كلمة مرور جديدة", "change email address" : "تغيير عنوان البريد الإلكتروني", diff --git a/settings/l10n/ar.json b/settings/l10n/ar.json index fcd11a9a03ca..11e2217f3dce 100644 --- a/settings/l10n/ar.json +++ b/settings/l10n/ar.json @@ -17,6 +17,7 @@ "Unable to delete group." : "تعذّر حذف مجموعة.", "Saved" : "تم الحفظ", "log-level out of allowed range" : "مستوى السجل خارج النطاق المسموح به", + "Updated log level" : "مستوى السجل المحدث", "Invalid email address" : "عنوان بريد إلكتروني غير صالح", "test email settings" : "إعدادات رسائل البريد الإلكتروني الاختبار", "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "حدثت مشكلة أثناء إرسال البريد الإلكتروني. يُرجى مراجعة إعداداتك. (خطأ: %s)", @@ -25,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "لا يمكن تغيير عنوان البريد الإلكتروني لأن المستخدم غير موجود", "Couldn't change the email address because the token is invalid" : "لا يمكن تغيير عنوان البريد الإلكتروني لأن الرمز المميز غير صالح", "Your %s account was created" : "تم إنشاء حساب %s", - "Invalid mail address" : "عنوان بريد إلكتروني غير صالح", "A user with that name already exists." : "يوجد مستخدم بهذا الاسم بالفعل.", "Unable to create user." : "تعذّر إنشاء مستخدم.", "The token provided is invalid." : "الرمز المميز المقدم غير صالح.", @@ -50,6 +50,8 @@ "%s email address changed successfully" : "تم تغيير عنوان البريد الإلكتروني لـ %s بنجاح", "Couldn't send email address change notification mail. Please contact your administrator." : "لا يمكن إرسال رسالة إشعار تغيير عنوان البريد الإلكتروني. يُرجى الاتصال بمسؤولك.", "Unable to enable/disable user." : "تعذّر تمكين/تعطيل المستخدم.", + "Data too long" : "البيانات طويلة جدا", + "Invalid mail address" : "عنوان بريد إلكتروني غير صالح", "Owner language" : "لغة المالك", "Create" : "إنشاء", "Change" : "تغيير", @@ -120,11 +122,14 @@ "undo" : "تراجع", "You are about to delete a group. This action can't be undone and is permanent. Are you sure that you want to permanently delete {groupName}?" : "أنت على وشك حذف مجموعة. هذا الإجراء نهائي ولا يمكن التراجع عنه. هل أنت متأكد من رغبتك في حذف {groupName} نهائيًا؟", "Delete group" : "حذف مجموعة", + "Resend invitation email" : "إعادة إرسال البريد الإلكتروني للدعوة", "never" : "أبدًا", "unknown" : "غير معروف", "deleted {userName}" : "{userName} محذوف", "You are about to delete a user. This action can't be undone and is permanent. All user data, files and shares will be deleted. Are you sure that you want to permanently delete {userName}?" : "أنت على وشك حذف مستخدم. هذا الإجراء نهائي ولا يمكن التراجع عنه. وسيتم حذف جميع بيانات المستخدم وملفاته ومشاركاته. هل أنت متأكد من رغبتك في حذف {userName} نهائيًا؟", "Delete user" : "حذف المستخدم", + "The invitation email for this user has been resent" : "تمت إعادة إرسال البريد الإلكتروني للدعوة لهذا المستخدم", + "The invitation email for this user could not be resent" : "تعذر إعادة إرسال البريد الإلكتروني للدعوة لهذا المستخدم", "Group already exists" : "المجموعة موجودة مسبقاً", "add group" : "إضافة مجموعة", "Invalid quota value \"{val}\"" : "قيمة الحصة النسبية غير صالحة \"{val}\"", @@ -207,6 +212,7 @@ "Allow users to share file via social media" : "السماح للمستخدمين بمشاركة الملف عبر وسائل التواصل الاجتماعي", "Set default expiration date for user shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي لمشاركات المستخدم", "Set default expiration date for group shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي لمشاركات المجموعة", + "Set default expiration date for federated shares" : "تعيين تاريخ انتهاء الصلاحية الافتراضي للأسهم الموحدة", "Automatically accept new incoming local user shares" : "قبول مشاركات المستخدمين المحليين الجديدة الواردة تلقائيًا", "Allow resharing" : "السماح بإعادة المشاركة", "Allow sharing with groups" : "السماح بالمشاركة مع المجموعات", @@ -230,6 +236,7 @@ "Enterprise license key" : "مفتاح ترخيص Enterprise", "Enter a new license:" : "أدخل ترخيصًا جديدًا:", "Save" : "حفظ", + "Remove current license key" : "إزالة مفتاح الترخيص الحالي", "Everything (fatal issues, errors, warnings, info, debug)" : "كل شيء (مشكلات فادحة، وأخطاء، وتحذيرات، ومعلومات، وتصحيح الأخطاء)", "Info, warnings, errors and fatal issues" : "المعلومات، والتحذيرات، والأخطاء، والمشكلات الفادحة", "Warnings, errors and fatal issues" : "التحذيرات، والأخطاء، والمشكلات الفادحة", @@ -260,17 +267,22 @@ "SMTP Username" : "اسم مستخدم SMTP", "SMTP Password" : "كلمة مرور SMTP", "Store credentials" : "تخزين بيانات الاعتماد", + "Test receiver email" : "اختبار البريد الإلكتروني للمستلم", "Test email settings" : "إعدادات رسائل البريد الإلكتروني الاختبار", "Send email" : "إرسال رسالة بريد إلكتروني", "Manual File Locking" : "قفل الملفات بشكل يدوي", "Default timeout for the locks if not specified (in seconds)" : "المهلة الافتراضية للأقفال في حال لم يقع تحديدها (بالثواني)", "Maximum timeout for the locks (in seconds)" : "المهلة القصوى للأقفال (بالثواني)", + "Enable manual file locking in the web interface" : "تمكين تأمين الملفات يدويا في واجهة الويب", + "Allow users in the following groups to unlock files they have access to:" : "السماح للمستخدمين في المجموعات التالية بإلغاء تأمين الملفات التي يمكنهم الوصول إليها:", + "Users in these groups can unlock files even if they are not the owner of the lock." : "يمكن للمستخدمين في هذه المجموعات إلغاء تأمين الملفات حتى لو لم يكونوا مالك القفل.", "Security & setup warnings" : "تحذيرات الأمان والضبط", "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "لا يبدو أنه تم إعداد php بشكل صحيح للاستعلام عن متغيرات بيئة النظام. ويُرجع الاختبار مع getenv(\"PATH\") استجابة فارغة فقط.", "Please check the installation documentation ↗ for php configuration notes and the php configuration of your server, especially when using php-fpm." : "يُرجى فحص مستندات التثبيت ↗ للاطلاع على ملاحظات تكوين php وتكوين php للخادم، لا سيما عند استخدام php-fpm.", "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "تم تفعيل تكوين للقراءة فقط. ويمنع ذلك ضبط بعض التكوينات عبر واجهة الويب. وبالإضافة إلى ذلك، يجب أن يكون الملف قابلًا للكتابة يدويًا لكل تحديث.", "PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "تم إعداد PHP على ما يبدو لإزالة كتل المستند المضمنة. وسيجعل ذلك العديد من التطبيقات الأساسية غير قابلة للوصول.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "من المحتمل أن يحدث ذلك بسبب وجود ذاكرة تخزين مؤقت/مسرّع مثل Zend OPcache أو eAccelerator.", + "Your database does not run with \"READ COMMITTED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "لا تعمل قاعدة البيانات الخاصة بك مع مستوى عزل المعاملات \"قراءة ملتزمة\". يمكن أن يتسبب هذا في حدوث مشكلات عند تنفيذ إجراءات متعددة بالتوازي.", "%1$s below version %2$s is installed, for stability and performance reasons we recommend updating to a newer %1$s version." : "تم تثبيت %1$s إصدار أقل %2$s، وللحصول على مزيد من الاستقرار والأداء المميز، نوصي بالتحديث إلى إصدار %1$s جديد.", "The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "وحدة PHP‏ \"fileinfo\" مفقودة. نوصي بشدة بتفعيل هذه الوحدة لتحقيق أفضل النتائج مع خاصية اكتشاف نوع mime.", "Transactional file locking is disabled, this might lead to issues with race conditions. Enable 'filelocking.enabled' in config.php to avoid these problems. See the documentation ↗ for more information." : "تم تعطيل تأمين ملف المعاملات، وقد يؤدي ذلك إلى حدوث مشكلات حالات التعارض. يُرجى تمكين \"filelocking.enabled\" في config.php لتجنب هذه المشكلات. انظر المستندات ↗ لمزيد من المعلومات.", @@ -297,6 +309,7 @@ "Desktop client" : "عميل سطح المكتب", "Android app" : "تطبيق Android", "iOS app" : "تطبيق iOS", + "If you want to support the project\n\t\t\tjoin development\n\t\t\tor\n\t\t\tspread the word!" : "إذا كنت ترغب في دعم المشروع\nانضم إلى التطوير\nأو\nانشر الكلمة!", "Show First Run Wizard again" : "عرض تشغيل المعالج مرة أخرى أولًا", "White-listed Domains" : "المجالات المدرجة في القائمة البيضاء", "No Domains." : "لا توجد مجالات.", @@ -328,6 +341,8 @@ "New password" : "كلمة مرور جديدة", "Change password" : "تغيير كلمة المرور", "Help translate" : "ترجمة التعليمات", + "Our imprint conditions:" : "شروط بصمتنا:", + "Our Privacy Policy conditions:" : "شروط سياسة الخصوصية الخاصة بنا:", "You are using %s" : "أنت تستخدم %s", "You are using %s of %s (%s %%)" : "أنت تستخدم %s من %s (%s %%)", "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}AGPL{linkclose}." : "طوّره {communityopen}مجتمع ownCloud {linkclose}، {githubopen}كود المصدر{linkclose} مرخص بموجب {licenseopen}رخصة جنو أفيرو العمومية{linkclose}.", @@ -345,6 +360,7 @@ "Use the credentials below to configure your app or device." : "استخدم بيانات الاعتماد أدناه لتكوين التطبيق أو الجهاز.", "Password / Token" : "كلمة المرور/الرمز المميز", "Done" : "تم", + "To access your files through WebDAV, please use the following URL:" : "للوصول إلى ملفاتك من خلال WebDAV ، يرجى استخدام عنوان URL التالي:", "Version" : "إصدار", "The activation link has expired. Click the button below to request a new one and complete the registration." : "انتهت صلاحية رابط التفعيل. انقر فوق الزر أدناه لطلب رابط جديد وأكمل التسجيل.", "Resend activation link" : "إعادة إرسال رابط التفعيل", @@ -358,6 +374,7 @@ "Settings" : "الإعدادات", "Show enabled/disabled option" : "عرض الخيار المُمكَّن/المُعطَّل", "Show storage location" : "عرض مكان التخزين", + "Show creation time" : "إظهار وقت الإنشاء", "Show last log in" : "عرض آخر عملية تسجيل الدخول", "Show user backend" : "عرض الواجهة الخلفية للمستخدم", "Set password for new users" : "تعيين كلمة مرور لمستخدمين جدد", @@ -381,6 +398,7 @@ "Storage Location" : "مكان التخزين", "User Backend" : "الواجهة الخلفية للمستخدم", "Last Login" : "آخر تسجيل دخول", + "Creation Time" : "وقت الإنشاء", "change full name" : "تغيير الاسم الكامل", "set new password" : "تعيين كلمة مرور جديدة", "change email address" : "تغيير عنوان البريد الإلكتروني", diff --git a/settings/l10n/ast.js b/settings/l10n/ast.js index 01187c9a3738..94f997079083 100644 --- a/settings/l10n/ast.js +++ b/settings/l10n/ast.js @@ -18,7 +18,6 @@ OC.L10N.register( "Email sent" : "Corréu-e unviáu", "You need to set your user email before being able to send test emails." : "Tienes de configurar la direición de corréu-e enantes de poder unviar mensaxes de prueba.", "Your %s account was created" : "Creóse la so cuenta %s", - "Invalid mail address" : "Direición d'email inválida", "A user with that name already exists." : "Un usuariu con esi nome yá esiste.", "Unable to create user." : "Imposible crear l'usuariu.", "Unable to delete user." : "Nun pudo desaniciase l'usuariu", @@ -27,6 +26,7 @@ OC.L10N.register( "Unable to change mail address" : "Nun pue camudase la direición d'email", "Your full name has been changed." : "Camudóse'l nome completu.", "Unable to change full name" : "Nun pue camudase'l nome completu", + "Invalid mail address" : "Direición d'email inválida", "Create" : "Crear", "Delete" : "Desaniciar", "Share" : "Compartir", diff --git a/settings/l10n/ast.json b/settings/l10n/ast.json index d26266c683f2..d51572098bc2 100644 --- a/settings/l10n/ast.json +++ b/settings/l10n/ast.json @@ -16,7 +16,6 @@ "Email sent" : "Corréu-e unviáu", "You need to set your user email before being able to send test emails." : "Tienes de configurar la direición de corréu-e enantes de poder unviar mensaxes de prueba.", "Your %s account was created" : "Creóse la so cuenta %s", - "Invalid mail address" : "Direición d'email inválida", "A user with that name already exists." : "Un usuariu con esi nome yá esiste.", "Unable to create user." : "Imposible crear l'usuariu.", "Unable to delete user." : "Nun pudo desaniciase l'usuariu", @@ -25,6 +24,7 @@ "Unable to change mail address" : "Nun pue camudase la direición d'email", "Your full name has been changed." : "Camudóse'l nome completu.", "Unable to change full name" : "Nun pue camudase'l nome completu", + "Invalid mail address" : "Direición d'email inválida", "Create" : "Crear", "Delete" : "Desaniciar", "Share" : "Compartir", diff --git a/settings/l10n/az.js b/settings/l10n/az.js index 03043a507afb..d410ad9aa27a 100644 --- a/settings/l10n/az.js +++ b/settings/l10n/az.js @@ -16,7 +16,6 @@ OC.L10N.register( "Email sent" : "Məktub göndərildi", "You need to set your user email before being able to send test emails." : "Test məktubu göndərməzdən öncə, siz öz istifadəçi poçtunuzu təyin etməlisiniz.", "Your %s account was created" : "Sizin %s hesab yaradıldı", - "Invalid mail address" : "Yalnış mail ünvanı", "A user with that name already exists." : "Bu adla istifadəçi artıq mövcuddur.", "Unable to create user." : "İstifadəçi yaratmaq mümkün deyil.", "Unable to delete user." : "İstifadəçini silmək mümkün deyil.", @@ -25,6 +24,7 @@ OC.L10N.register( "Unable to change mail address" : "Mail ünvanını dəyişmək olmur", "Your full name has been changed." : "Sizin tam adınız dəyişdirildi.", "Unable to change full name" : "Tam adı dəyişmək olmur", + "Invalid mail address" : "Yalnış mail ünvanı", "Create" : "Yarat", "Delete" : "Sil", "Share" : "Paylaş", diff --git a/settings/l10n/az.json b/settings/l10n/az.json index 89497d81bd78..f8de0244f6ba 100644 --- a/settings/l10n/az.json +++ b/settings/l10n/az.json @@ -14,7 +14,6 @@ "Email sent" : "Məktub göndərildi", "You need to set your user email before being able to send test emails." : "Test məktubu göndərməzdən öncə, siz öz istifadəçi poçtunuzu təyin etməlisiniz.", "Your %s account was created" : "Sizin %s hesab yaradıldı", - "Invalid mail address" : "Yalnış mail ünvanı", "A user with that name already exists." : "Bu adla istifadəçi artıq mövcuddur.", "Unable to create user." : "İstifadəçi yaratmaq mümkün deyil.", "Unable to delete user." : "İstifadəçini silmək mümkün deyil.", @@ -23,6 +22,7 @@ "Unable to change mail address" : "Mail ünvanını dəyişmək olmur", "Your full name has been changed." : "Sizin tam adınız dəyişdirildi.", "Unable to change full name" : "Tam adı dəyişmək olmur", + "Invalid mail address" : "Yalnış mail ünvanı", "Create" : "Yarat", "Delete" : "Sil", "Share" : "Paylaş", diff --git a/settings/l10n/bg_BG.js b/settings/l10n/bg_BG.js index 547cbc0d3cd3..1edcd21299f4 100644 --- a/settings/l10n/bg_BG.js +++ b/settings/l10n/bg_BG.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Промяната на имейл адреса е невъзможна защото потребителят не съществува", "Couldn't change the email address because the token is invalid" : "Промяната на имейл адреса е невъзможна защото токенът не е валиден", "Your %s account was created" : "Вашият %s профил е създаден", - "Invalid mail address" : "Невалиден имейл адрес", "A user with that name already exists." : "Потребител с това име вече съществува.", "Unable to create user." : "Неуспешно създаване на потребител.", "The token provided is invalid." : "Предоставеният токен е невалиден.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s имейл адресът е променен успешно", "Couldn't send email address change notification mail. Please contact your administrator." : "Неуспешно изпращане на имейл с известие за промяна на имейл адреса. Моля, свържете се с вашия администратор.", "Unable to enable/disable user." : "Потребителят не може да се активира/деактивира.", + "Invalid mail address" : "Невалиден имейл адрес", "Owner language" : "Език на собственика", "Create" : "Създаване", "Change" : "Промяна", diff --git a/settings/l10n/bg_BG.json b/settings/l10n/bg_BG.json index 85173ad5ab53..f39af8c9bfd5 100644 --- a/settings/l10n/bg_BG.json +++ b/settings/l10n/bg_BG.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Промяната на имейл адреса е невъзможна защото потребителят не съществува", "Couldn't change the email address because the token is invalid" : "Промяната на имейл адреса е невъзможна защото токенът не е валиден", "Your %s account was created" : "Вашият %s профил е създаден", - "Invalid mail address" : "Невалиден имейл адрес", "A user with that name already exists." : "Потребител с това име вече съществува.", "Unable to create user." : "Неуспешно създаване на потребител.", "The token provided is invalid." : "Предоставеният токен е невалиден.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s имейл адресът е променен успешно", "Couldn't send email address change notification mail. Please contact your administrator." : "Неуспешно изпращане на имейл с известие за промяна на имейл адреса. Моля, свържете се с вашия администратор.", "Unable to enable/disable user." : "Потребителят не може да се активира/деактивира.", + "Invalid mail address" : "Невалиден имейл адрес", "Owner language" : "Език на собственика", "Create" : "Създаване", "Change" : "Промяна", diff --git a/settings/l10n/bs.js b/settings/l10n/bs.js index 998aad3aa7e5..fd3cb098625a 100644 --- a/settings/l10n/bs.js +++ b/settings/l10n/bs.js @@ -14,7 +14,6 @@ OC.L10N.register( "Email sent" : "E-pošta je poslana", "You need to set your user email before being able to send test emails." : "Prije nego li ste u mogućnosti slati testnu email trebate postaviti svoj korisnički email.", "Your %s account was created" : "Vaš %s račun je kreiran", - "Invalid mail address" : "Nevažeća adresa e-pošte", "Unable to create user." : "Nemoguće kreirati korisnika", "Unable to delete user." : "Nemoguće izbrisati korisnika", "Forbidden" : "Zabranjeno", @@ -22,6 +21,7 @@ OC.L10N.register( "Unable to change mail address" : "Nemoguće je izmjeniti adresu e-pošte", "Your full name has been changed." : "Vaše puno ime je promijenjeno.", "Unable to change full name" : "Puno ime nije moguće promijeniti", + "Invalid mail address" : "Nevažeća adresa e-pošte", "Create" : "Kreiraj", "Delete" : "Izbriši", "Share" : "Dijeli", diff --git a/settings/l10n/bs.json b/settings/l10n/bs.json index caf9d138139b..f84b20e7d99b 100644 --- a/settings/l10n/bs.json +++ b/settings/l10n/bs.json @@ -12,7 +12,6 @@ "Email sent" : "E-pošta je poslana", "You need to set your user email before being able to send test emails." : "Prije nego li ste u mogućnosti slati testnu email trebate postaviti svoj korisnički email.", "Your %s account was created" : "Vaš %s račun je kreiran", - "Invalid mail address" : "Nevažeća adresa e-pošte", "Unable to create user." : "Nemoguće kreirati korisnika", "Unable to delete user." : "Nemoguće izbrisati korisnika", "Forbidden" : "Zabranjeno", @@ -20,6 +19,7 @@ "Unable to change mail address" : "Nemoguće je izmjeniti adresu e-pošte", "Your full name has been changed." : "Vaše puno ime je promijenjeno.", "Unable to change full name" : "Puno ime nije moguće promijeniti", + "Invalid mail address" : "Nevažeća adresa e-pošte", "Create" : "Kreiraj", "Delete" : "Izbriši", "Share" : "Dijeli", diff --git a/settings/l10n/ca.js b/settings/l10n/ca.js index 5ea253ea3473..87027607a674 100644 --- a/settings/l10n/ca.js +++ b/settings/l10n/ca.js @@ -21,7 +21,6 @@ OC.L10N.register( "Email sent" : "El correu electrónic s'ha enviat", "You need to set your user email before being able to send test emails." : "Heu d'establir un nom d'usuari abans de poder enviar correus de prova.", "Your %s account was created" : "S'ha creat el seu compte %s", - "Invalid mail address" : "Adreça de correu invàlida", "A user with that name already exists." : "Ja existeix un usuari amb est nom.", "Unable to create user." : "No es pot crear el usuari.", "Failed to set password. Please contact your administrator." : "No s'ha pogut establir una contrasenya. Per favor, contacta amb l'administrador.", @@ -32,6 +31,7 @@ OC.L10N.register( "Unable to change display name" : "No s'ha pogut canviar el nom a mostrar", "Your full name has been changed." : "El vostre nom complet ha canviat.", "Unable to change full name" : "No s'ha pogut canviar el nom complet", + "Invalid mail address" : "Adreça de correu invàlida", "Create" : "Crea", "Delete" : "Esborra", "Share" : "Compartir", diff --git a/settings/l10n/ca.json b/settings/l10n/ca.json index c115513d26c4..1aaa274fdafe 100644 --- a/settings/l10n/ca.json +++ b/settings/l10n/ca.json @@ -19,7 +19,6 @@ "Email sent" : "El correu electrónic s'ha enviat", "You need to set your user email before being able to send test emails." : "Heu d'establir un nom d'usuari abans de poder enviar correus de prova.", "Your %s account was created" : "S'ha creat el seu compte %s", - "Invalid mail address" : "Adreça de correu invàlida", "A user with that name already exists." : "Ja existeix un usuari amb est nom.", "Unable to create user." : "No es pot crear el usuari.", "Failed to set password. Please contact your administrator." : "No s'ha pogut establir una contrasenya. Per favor, contacta amb l'administrador.", @@ -30,6 +29,7 @@ "Unable to change display name" : "No s'ha pogut canviar el nom a mostrar", "Your full name has been changed." : "El vostre nom complet ha canviat.", "Unable to change full name" : "No s'ha pogut canviar el nom complet", + "Invalid mail address" : "Adreça de correu invàlida", "Create" : "Crea", "Delete" : "Esborra", "Share" : "Compartir", diff --git a/settings/l10n/cs_CZ.js b/settings/l10n/cs_CZ.js index cadeb914622a..f9ebb0d914fb 100644 --- a/settings/l10n/cs_CZ.js +++ b/settings/l10n/cs_CZ.js @@ -25,7 +25,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Email nemohl být změněn. Uživatel neexistuje", "Couldn't change the email address because the token is invalid" : "Email nemohl být změněn. Token je chybný", "Your %s account was created" : "Účet %s byl vytvořen", - "Invalid mail address" : "Neplatná emailová adresa", "A user with that name already exists." : "Uživatel tohoto jména již existuje.", "Unable to create user." : "Nelze vytvořit uživatele.", "The token provided is invalid." : "Vložený token je neplatný.", @@ -50,6 +49,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s emailová adresa úspěšně změněna", "Couldn't send email address change notification mail. Please contact your administrator." : "Nelze odeslat e-mailovou adresu pro oznamování změn poštu. Obraťte se na správce.", "Unable to enable/disable user." : "Nelze povolit/zakázat uživatele.", + "Invalid mail address" : "Neplatná emailová adresa", "Owner language" : "Jazyk vlastníka", "Create" : "Vytvořit", "Change" : "Změnit", diff --git a/settings/l10n/cs_CZ.json b/settings/l10n/cs_CZ.json index 46bbbcf8e867..590ab708d694 100644 --- a/settings/l10n/cs_CZ.json +++ b/settings/l10n/cs_CZ.json @@ -23,7 +23,6 @@ "Couldn't change the email address because the user does not exist" : "Email nemohl být změněn. Uživatel neexistuje", "Couldn't change the email address because the token is invalid" : "Email nemohl být změněn. Token je chybný", "Your %s account was created" : "Účet %s byl vytvořen", - "Invalid mail address" : "Neplatná emailová adresa", "A user with that name already exists." : "Uživatel tohoto jména již existuje.", "Unable to create user." : "Nelze vytvořit uživatele.", "The token provided is invalid." : "Vložený token je neplatný.", @@ -48,6 +47,7 @@ "%s email address changed successfully" : "%s emailová adresa úspěšně změněna", "Couldn't send email address change notification mail. Please contact your administrator." : "Nelze odeslat e-mailovou adresu pro oznamování změn poštu. Obraťte se na správce.", "Unable to enable/disable user." : "Nelze povolit/zakázat uživatele.", + "Invalid mail address" : "Neplatná emailová adresa", "Owner language" : "Jazyk vlastníka", "Create" : "Vytvořit", "Change" : "Změnit", diff --git a/settings/l10n/da.js b/settings/l10n/da.js index 683f9664056b..5ef3e0408c80 100644 --- a/settings/l10n/da.js +++ b/settings/l10n/da.js @@ -23,7 +23,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Kunne ikke ændre emailadressen fordi brugeren ikke eksisterer", "Couldn't change the email address because the token is invalid" : "Kunne ikke ændre emailadresse da symboludtrykket er ugyldigt", "Your %s account was created" : "Din %s-konto blev oprettet", - "Invalid mail address" : "Ugyldig mailadresse", "A user with that name already exists." : "Dette brugernavn eksistere allerede.", "Unable to create user." : "Kan ikke oprette brugeren.", "Unable to delete user." : "Kan ikke slette brugeren.", @@ -40,6 +39,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s emailadresse succesfuldt ændret", "Couldn't send email address change notification mail. Please contact your administrator." : "Kunne ikke sende emailændringsbekræftelsesmail. Kontakt venligst din administrator.", "Unable to enable/disable user." : "Kan ikke aktivere/deaktiverer bruger.", + "Invalid mail address" : "Ugyldig mailadresse", "Create" : "Ny", "Delete" : "Slet", "Share" : "Del", diff --git a/settings/l10n/da.json b/settings/l10n/da.json index 08aca13e9bbb..532e9d3898cd 100644 --- a/settings/l10n/da.json +++ b/settings/l10n/da.json @@ -21,7 +21,6 @@ "Couldn't change the email address because the user does not exist" : "Kunne ikke ændre emailadressen fordi brugeren ikke eksisterer", "Couldn't change the email address because the token is invalid" : "Kunne ikke ændre emailadresse da symboludtrykket er ugyldigt", "Your %s account was created" : "Din %s-konto blev oprettet", - "Invalid mail address" : "Ugyldig mailadresse", "A user with that name already exists." : "Dette brugernavn eksistere allerede.", "Unable to create user." : "Kan ikke oprette brugeren.", "Unable to delete user." : "Kan ikke slette brugeren.", @@ -38,6 +37,7 @@ "%s email address changed successfully" : "%s emailadresse succesfuldt ændret", "Couldn't send email address change notification mail. Please contact your administrator." : "Kunne ikke sende emailændringsbekræftelsesmail. Kontakt venligst din administrator.", "Unable to enable/disable user." : "Kan ikke aktivere/deaktiverer bruger.", + "Invalid mail address" : "Ugyldig mailadresse", "Create" : "Ny", "Delete" : "Slet", "Share" : "Del", diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 6f90f0d84f38..1726c1cb29fa 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Dein %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktiere Deinen Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Anwenders", "Create" : "Anlegen", "Change" : "Ändern", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index a860873c237f..b209770e7edd 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Dein %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktiere Deinen Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Anwenders", "Create" : "Anlegen", "Change" : "Ändern", diff --git a/settings/l10n/de_CH.js b/settings/l10n/de_CH.js index e48537f8f269..00d3df37ff5c 100644 --- a/settings/l10n/de_CH.js +++ b/settings/l10n/de_CH.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Dein %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -51,6 +50,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktiere Deinen Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Anwenders", "Create" : "Anlegen", "Change" : "Ändern", diff --git a/settings/l10n/de_CH.json b/settings/l10n/de_CH.json index 5b7883cdc2c6..b722228f205d 100644 --- a/settings/l10n/de_CH.json +++ b/settings/l10n/de_CH.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Dein %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -49,6 +48,7 @@ "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktiere Deinen Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Anwenders", "Create" : "Anlegen", "Change" : "Ändern", diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js index ed2c7c1be763..67d08e414eee 100644 --- a/settings/l10n/de_DE.js +++ b/settings/l10n/de_DE.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Ihr %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktieren Sie Ihren Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Eigentümers", "Create" : "Erstellen", "Change" : "Ändern", diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json index 5b09b7354ec5..a275aadc22aa 100644 --- a/settings/l10n/de_DE.json +++ b/settings/l10n/de_DE.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Die E-Mail Adresse konnte nicht geändert werden, da der Benutzer nicht existiert", "Couldn't change the email address because the token is invalid" : "Die E-Mail Adresse konnte nicht geändert werden, da der Token ungültig ist", "Your %s account was created" : "Ihr %s-Konto wurde erstellt", - "Invalid mail address" : "Ungültige E-Mail-Adresse", "A user with that name already exists." : "Ein Benutzer mit diesem Namen existiert bereits.", "Unable to create user." : "Benutzer konnte nicht erstellt werden.", "The token provided is invalid." : "Der Token ist ungültig", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s E-Mail Adresse wurde erfolgreich geändert", "Couldn't send email address change notification mail. Please contact your administrator." : "Die Benachrichtigung zur Änderung der E-Mail Adresse konnte nicht versendet werden. Bitte kontaktieren Sie Ihren Administrator.", "Unable to enable/disable user." : "Benutzer konnte nicht de-/aktiviert werden.", + "Invalid mail address" : "Ungültige E-Mail-Adresse", "Owner language" : "Sprache des Eigentümers", "Create" : "Erstellen", "Change" : "Ändern", diff --git a/settings/l10n/el.js b/settings/l10n/el.js index 280ba3c3035e..755bb427c272 100644 --- a/settings/l10n/el.js +++ b/settings/l10n/el.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Αδυναμία αλλαγής διεύθυνσης ηλεκτρονικού ταχυδρομείου διότι δεν υπάρχει ο χρήστης", "Couldn't change the email address because the token is invalid" : "Αδυναμία αλλαγής διεύθυνσης ηλεκτρονικού ταχυδρομείου λόγω μη έγκυρου διακριτικού", "Your %s account was created" : "Ο λογαριασμός %s δημιουργήθηκε", - "Invalid mail address" : "Μη έγκυρη διεύθυνση ταχυδρομείου", "A user with that name already exists." : "Υπάρχει ήδη χρήστης με το ίδιο όνομα.", "Unable to create user." : "Αδυναμία δημιουργίας χρήστη.", "The token provided is invalid." : "Δόθηκε μη έγκυρο διακριτικό.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "ο %s άλλαξε την διεύθυνση ηλεκτρονικής αλληλογραφίας επιτυχώς", "Couldn't send email address change notification mail. Please contact your administrator." : "Αδυναμία αποστολής μηνύματος ειδοποίησης αλλαγής διεύθυνσης ηλεκτρονικής αλληλογραφίας. Παρακαλούμε επικοινωνήστε με τον διαχειριστή.", "Unable to enable/disable user." : "Αδυναμία ενεργοποίησης/απενεργοποίησης χρήστη.", + "Invalid mail address" : "Μη έγκυρη διεύθυνση ταχυδρομείου", "Owner language" : "Γλώσσα ιδιοκτήτη", "Create" : "Δημιουργία", "Change" : "Αλλαγή", diff --git a/settings/l10n/el.json b/settings/l10n/el.json index 53b484dacbbb..2da1d16a5158 100644 --- a/settings/l10n/el.json +++ b/settings/l10n/el.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Αδυναμία αλλαγής διεύθυνσης ηλεκτρονικού ταχυδρομείου διότι δεν υπάρχει ο χρήστης", "Couldn't change the email address because the token is invalid" : "Αδυναμία αλλαγής διεύθυνσης ηλεκτρονικού ταχυδρομείου λόγω μη έγκυρου διακριτικού", "Your %s account was created" : "Ο λογαριασμός %s δημιουργήθηκε", - "Invalid mail address" : "Μη έγκυρη διεύθυνση ταχυδρομείου", "A user with that name already exists." : "Υπάρχει ήδη χρήστης με το ίδιο όνομα.", "Unable to create user." : "Αδυναμία δημιουργίας χρήστη.", "The token provided is invalid." : "Δόθηκε μη έγκυρο διακριτικό.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "ο %s άλλαξε την διεύθυνση ηλεκτρονικής αλληλογραφίας επιτυχώς", "Couldn't send email address change notification mail. Please contact your administrator." : "Αδυναμία αποστολής μηνύματος ειδοποίησης αλλαγής διεύθυνσης ηλεκτρονικής αλληλογραφίας. Παρακαλούμε επικοινωνήστε με τον διαχειριστή.", "Unable to enable/disable user." : "Αδυναμία ενεργοποίησης/απενεργοποίησης χρήστη.", + "Invalid mail address" : "Μη έγκυρη διεύθυνση ταχυδρομείου", "Owner language" : "Γλώσσα ιδιοκτήτη", "Create" : "Δημιουργία", "Change" : "Αλλαγή", diff --git a/settings/l10n/en_GB.js b/settings/l10n/en_GB.js index 205b793ce48d..f61bdc6ab19d 100644 --- a/settings/l10n/en_GB.js +++ b/settings/l10n/en_GB.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Couldn't change the email address because the user does not exist", "Couldn't change the email address because the token is invalid" : "Couldn't change the email address because the token is invalid", "Your %s account was created" : "Your %s account was created", - "Invalid mail address" : "Invalid mail address", "A user with that name already exists." : "A user with that name already exists.", "Unable to create user." : "Unable to create user.", "The token provided is invalid." : "The token provided is invalid.", @@ -53,6 +52,8 @@ OC.L10N.register( "%s email address changed successfully" : "%s email address changed successfully", "Couldn't send email address change notification mail. Please contact your administrator." : "Couldn't send email address change notification mail. Please contact your administrator.", "Unable to enable/disable user." : "Unable to enable/disable user.", + "Data too long" : "Data too long", + "Invalid mail address" : "Invalid mail address", "Owner language" : "Owner language", "Create" : "Create", "Change" : "Change", @@ -196,6 +197,16 @@ OC.L10N.register( "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one.", "Start migration" : "Start migration", + "Two-factor Authentication" : "Two-factor Authentication", + "This section requires a two-factor authentication app to be installed in ownCloud" : "This section requires a two-factor authentication app to be installed in ownCloud", + "Enforce two-factor authentication" : "Enforce two-factor authentication", + "Before enforcing the two-factor authentication, check the following requirements:" : "Before enforcing the two-factor authentication, check the following requirements:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "At least one two-factor authentication app is installed and enabled in ownCloud.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps", + "Enforce two-factor authentication to all the users" : "Enforce two-factor authentication to all the users", + "Exclude the following groups from enforcing two-factor authentication" : "Exclude the following groups from enforcing two-factor authentication", + "Note: Users in these groups can use two-factor authentication on their own" : "Note: Users in these groups can use two-factor authentication on their own", "Sharing" : "Sharing", "Allow apps to use the Share API" : "Allow apps to use the Share API", "Allow users to share via link" : "Allow users to share via link", diff --git a/settings/l10n/en_GB.json b/settings/l10n/en_GB.json index 9a6f8ad1f9d0..3c82854560a9 100644 --- a/settings/l10n/en_GB.json +++ b/settings/l10n/en_GB.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Couldn't change the email address because the user does not exist", "Couldn't change the email address because the token is invalid" : "Couldn't change the email address because the token is invalid", "Your %s account was created" : "Your %s account was created", - "Invalid mail address" : "Invalid mail address", "A user with that name already exists." : "A user with that name already exists.", "Unable to create user." : "Unable to create user.", "The token provided is invalid." : "The token provided is invalid.", @@ -51,6 +50,8 @@ "%s email address changed successfully" : "%s email address changed successfully", "Couldn't send email address change notification mail. Please contact your administrator." : "Couldn't send email address change notification mail. Please contact your administrator.", "Unable to enable/disable user." : "Unable to enable/disable user.", + "Data too long" : "Data too long", + "Invalid mail address" : "Invalid mail address", "Owner language" : "Owner language", "Create" : "Create", "Change" : "Change", @@ -194,6 +195,16 @@ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one.", "Start migration" : "Start migration", + "Two-factor Authentication" : "Two-factor Authentication", + "This section requires a two-factor authentication app to be installed in ownCloud" : "This section requires a two-factor authentication app to be installed in ownCloud", + "Enforce two-factor authentication" : "Enforce two-factor authentication", + "Before enforcing the two-factor authentication, check the following requirements:" : "Before enforcing the two-factor authentication, check the following requirements:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "At least one two-factor authentication app is installed and enabled in ownCloud.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps", + "Enforce two-factor authentication to all the users" : "Enforce two-factor authentication to all the users", + "Exclude the following groups from enforcing two-factor authentication" : "Exclude the following groups from enforcing two-factor authentication", + "Note: Users in these groups can use two-factor authentication on their own" : "Note: Users in these groups can use two-factor authentication on their own", "Sharing" : "Sharing", "Allow apps to use the Share API" : "Allow apps to use the Share API", "Allow users to share via link" : "Allow users to share via link", diff --git a/settings/l10n/es.js b/settings/l10n/es.js index c0409da21a25..566382bf1060 100644 --- a/settings/l10n/es.js +++ b/settings/l10n/es.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "No puedo cambiar la dirección de e-mail por que el usuario no existe.", "Couldn't change the email address because the token is invalid" : "No puedo cambiar la dirección de e-mail por que el token no es válido.", "Your %s account was created" : "Se ha creado su cuenta de %s", - "Invalid mail address" : "Dirección de correo no válida", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se pudo crear el usuario.", "The token provided is invalid." : "El token suministrado no es correcto.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "e-mail %s cambiado satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "No puedo mandar el e-mail de confirmación de cambio de dirección, por favor contacte con el administrador.", "Unable to enable/disable user." : "No es posible habilitar / deshabilitar el usuario", + "Invalid mail address" : "Dirección de correo no válida", "Owner language" : "Idioma del propietario", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/es.json b/settings/l10n/es.json index db602f912054..819deb827acc 100644 --- a/settings/l10n/es.json +++ b/settings/l10n/es.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "No puedo cambiar la dirección de e-mail por que el usuario no existe.", "Couldn't change the email address because the token is invalid" : "No puedo cambiar la dirección de e-mail por que el token no es válido.", "Your %s account was created" : "Se ha creado su cuenta de %s", - "Invalid mail address" : "Dirección de correo no válida", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se pudo crear el usuario.", "The token provided is invalid." : "El token suministrado no es correcto.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "e-mail %s cambiado satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "No puedo mandar el e-mail de confirmación de cambio de dirección, por favor contacte con el administrador.", "Unable to enable/disable user." : "No es posible habilitar / deshabilitar el usuario", + "Invalid mail address" : "Dirección de correo no válida", "Owner language" : "Idioma del propietario", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/es_AR.js b/settings/l10n/es_AR.js index 1f5c6ce0f76d..d30c061220f6 100644 --- a/settings/l10n/es_AR.js +++ b/settings/l10n/es_AR.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "No fue posible modificar la dirección de correo debido a que el usuario no existe", "Couldn't change the email address because the token is invalid" : "No fue posible modificar la dirección de correo debido a que el token es inválido", "Your %s account was created" : "Tu cuenta %s fue creada", - "Invalid mail address" : "Dirección de correo inválida", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se puede crear el usuario.", "The token provided is invalid." : "El token ingresado es inválido.", @@ -51,6 +50,7 @@ OC.L10N.register( "%s email address changed successfully" : "La dirección de correo %s ha sido modificada satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "No se pudo enviar el mensaje de modificación de dirección de correo. Por favor contacte al administrador.", "Unable to enable/disable user." : "No se puede activar/desactivar al usuario.", + "Invalid mail address" : "Dirección de correo inválida", "Owner language" : "Lenguaje del dueño", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/es_AR.json b/settings/l10n/es_AR.json index cc5729f0868a..bcc098598510 100644 --- a/settings/l10n/es_AR.json +++ b/settings/l10n/es_AR.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "No fue posible modificar la dirección de correo debido a que el usuario no existe", "Couldn't change the email address because the token is invalid" : "No fue posible modificar la dirección de correo debido a que el token es inválido", "Your %s account was created" : "Tu cuenta %s fue creada", - "Invalid mail address" : "Dirección de correo inválida", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se puede crear el usuario.", "The token provided is invalid." : "El token ingresado es inválido.", @@ -49,6 +48,7 @@ "%s email address changed successfully" : "La dirección de correo %s ha sido modificada satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "No se pudo enviar el mensaje de modificación de dirección de correo. Por favor contacte al administrador.", "Unable to enable/disable user." : "No se puede activar/desactivar al usuario.", + "Invalid mail address" : "Dirección de correo inválida", "Owner language" : "Lenguaje del dueño", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/es_MX.js b/settings/l10n/es_MX.js index 6772486cb0a4..1f407955763d 100644 --- a/settings/l10n/es_MX.js +++ b/settings/l10n/es_MX.js @@ -14,7 +14,6 @@ OC.L10N.register( "test email settings" : "probar configuración de correo", "Email sent" : "Correo electrónico enviado", "You need to set your user email before being able to send test emails." : "Necesitas establecer tu correo de usuario antes de poder enviar correos de prueba.", - "Invalid mail address" : "Dirección de correo electrónico inválido.", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se pudo crear usuario.", "Unable to delete user." : "No se pudo eliminar usuario.", @@ -23,6 +22,7 @@ OC.L10N.register( "Unable to change mail address" : "No se pudo cambiar la dirección de correo electrónico", "Your full name has been changed." : "Se ha cambiado su nombre completo.", "Unable to change full name" : "No se puede cambiar el nombre completo", + "Invalid mail address" : "Dirección de correo electrónico inválido.", "Create" : "Crear", "Delete" : "Eliminar", "Share" : "Compartir", diff --git a/settings/l10n/es_MX.json b/settings/l10n/es_MX.json index e696376d1999..d1d02304c189 100644 --- a/settings/l10n/es_MX.json +++ b/settings/l10n/es_MX.json @@ -12,7 +12,6 @@ "test email settings" : "probar configuración de correo", "Email sent" : "Correo electrónico enviado", "You need to set your user email before being able to send test emails." : "Necesitas establecer tu correo de usuario antes de poder enviar correos de prueba.", - "Invalid mail address" : "Dirección de correo electrónico inválido.", "A user with that name already exists." : "Ya existe un usuario con ese nombre.", "Unable to create user." : "No se pudo crear usuario.", "Unable to delete user." : "No se pudo eliminar usuario.", @@ -21,6 +20,7 @@ "Unable to change mail address" : "No se pudo cambiar la dirección de correo electrónico", "Your full name has been changed." : "Se ha cambiado su nombre completo.", "Unable to change full name" : "No se puede cambiar el nombre completo", + "Invalid mail address" : "Dirección de correo electrónico inválido.", "Create" : "Crear", "Delete" : "Eliminar", "Share" : "Compartir", diff --git a/settings/l10n/et_EE.js b/settings/l10n/et_EE.js index 97bd1976f1e1..1b6db627ad75 100644 --- a/settings/l10n/et_EE.js +++ b/settings/l10n/et_EE.js @@ -17,7 +17,6 @@ OC.L10N.register( "Email sent" : "E-kiri on saadetud", "You need to set your user email before being able to send test emails." : "Pead seadistama oma e-postienne kui on võimalik saata test-kirju.", "Your %s account was created" : "Sinu %s konto on loodud", - "Invalid mail address" : "Vigane e-posti aadress", "A user with that name already exists." : "Selle nimega kasutaja on juba olemas.", "Unable to create user." : "Kasutaja loomine ebaõnnestus.", "The token provided is invalid." : "Kontrollkood on vigane.", @@ -28,6 +27,7 @@ OC.L10N.register( "Unable to change display name" : "Ei saa muuta näidatavat nime", "Your full name has been changed." : "Sinu täispikk nimi on muudetud.", "Unable to change full name" : "Täispika nime muutmine ebaõnnestus", + "Invalid mail address" : "Vigane e-posti aadress", "Owner language" : "Omaniku keel", "Create" : "Lisa", "Change" : "Muuda", diff --git a/settings/l10n/et_EE.json b/settings/l10n/et_EE.json index 103fc839d380..586d1d525291 100644 --- a/settings/l10n/et_EE.json +++ b/settings/l10n/et_EE.json @@ -15,7 +15,6 @@ "Email sent" : "E-kiri on saadetud", "You need to set your user email before being able to send test emails." : "Pead seadistama oma e-postienne kui on võimalik saata test-kirju.", "Your %s account was created" : "Sinu %s konto on loodud", - "Invalid mail address" : "Vigane e-posti aadress", "A user with that name already exists." : "Selle nimega kasutaja on juba olemas.", "Unable to create user." : "Kasutaja loomine ebaõnnestus.", "The token provided is invalid." : "Kontrollkood on vigane.", @@ -26,6 +25,7 @@ "Unable to change display name" : "Ei saa muuta näidatavat nime", "Your full name has been changed." : "Sinu täispikk nimi on muudetud.", "Unable to change full name" : "Täispika nime muutmine ebaõnnestus", + "Invalid mail address" : "Vigane e-posti aadress", "Owner language" : "Omaniku keel", "Create" : "Lisa", "Change" : "Muuda", diff --git a/settings/l10n/eu.js b/settings/l10n/eu.js index 2465ae1aef7c..5ebdd1879b2c 100644 --- a/settings/l10n/eu.js +++ b/settings/l10n/eu.js @@ -20,7 +20,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Ezin izan da helbide elektronikoa aldatu erabiltzailea ez delako existitzen", "Couldn't change the email address because the token is invalid" : "Ezin izan da helbide elektronikoa aldatu token-a baliogabea delako", "Your %s account was created" : "Zure %s kontua sortu da", - "Invalid mail address" : "Posta helbide baliogabea", "A user with that name already exists." : "Izen bereko erabiltzailea dagoeneko existitzen da", "Unable to create user." : "Ezin izan da erabiltzailea sortu.", "The token provided is invalid." : "Emandako tokena baliogabea da.", @@ -45,6 +44,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s helbide elektronikoa behar bezala aldatu da", "Couldn't send email address change notification mail. Please contact your administrator." : "Ezin izan da helbide elektronikoa berrezartzeko mezu elektronikoa bidali. Mesedez harremanetan jarri zure kudeatzailearekin.", "Unable to enable/disable user." : "Ezin izan da erabiltzailea gaitu/ezgaitu", + "Invalid mail address" : "Posta helbide baliogabea", "Create" : "Sortu", "Change" : "Aldatu", "Delete" : "Ezabatu", diff --git a/settings/l10n/eu.json b/settings/l10n/eu.json index 78889142a1b0..9e1d5b8fbe89 100644 --- a/settings/l10n/eu.json +++ b/settings/l10n/eu.json @@ -18,7 +18,6 @@ "Couldn't change the email address because the user does not exist" : "Ezin izan da helbide elektronikoa aldatu erabiltzailea ez delako existitzen", "Couldn't change the email address because the token is invalid" : "Ezin izan da helbide elektronikoa aldatu token-a baliogabea delako", "Your %s account was created" : "Zure %s kontua sortu da", - "Invalid mail address" : "Posta helbide baliogabea", "A user with that name already exists." : "Izen bereko erabiltzailea dagoeneko existitzen da", "Unable to create user." : "Ezin izan da erabiltzailea sortu.", "The token provided is invalid." : "Emandako tokena baliogabea da.", @@ -43,6 +42,7 @@ "%s email address changed successfully" : "%s helbide elektronikoa behar bezala aldatu da", "Couldn't send email address change notification mail. Please contact your administrator." : "Ezin izan da helbide elektronikoa berrezartzeko mezu elektronikoa bidali. Mesedez harremanetan jarri zure kudeatzailearekin.", "Unable to enable/disable user." : "Ezin izan da erabiltzailea gaitu/ezgaitu", + "Invalid mail address" : "Posta helbide baliogabea", "Create" : "Sortu", "Change" : "Aldatu", "Delete" : "Ezabatu", diff --git a/settings/l10n/fa.js b/settings/l10n/fa.js index a5f0e29ec1c7..6b56d4e754f0 100644 --- a/settings/l10n/fa.js +++ b/settings/l10n/fa.js @@ -23,7 +23,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "آدرس ایمیل تغییر نمی کند زیرا کاربر موجود نیست", "Couldn't change the email address because the token is invalid" : "آدرس ایمیل تغییر نمی کند زیرا نشانه معتبر نیست", "Your %s account was created" : "حساب کاربری شما %s ایجاد شد", - "Invalid mail address" : "آدرس ایمیل نامعتبر است", "A user with that name already exists." : "کاربری با همین نام در حال حاضر وجود دارد.", "Unable to create user." : "ایجاد کاربر امکان‌پذیر نیست.", "Unable to delete user." : "حذف کاربر امکان پذیر نیست.", @@ -40,6 +39,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s آدرس ایمیل با موفقیت تغییر کرد", "Couldn't send email address change notification mail. Please contact your administrator." : "ایمیل اعلان تغییر آدرس ایمیل ارسال نمی شود. لطفا با مدیر خود تماس بگیرید.", "Unable to enable/disable user." : "فعال سازی/غیر فعال سازی کاربر ممکن نیست.", + "Invalid mail address" : "آدرس ایمیل نامعتبر است", "Create" : "ایجاد کردن", "Change" : "تغییر", "Delete" : "حذف", diff --git a/settings/l10n/fa.json b/settings/l10n/fa.json index fb8cb9316d78..abf4ee6ad9c3 100644 --- a/settings/l10n/fa.json +++ b/settings/l10n/fa.json @@ -21,7 +21,6 @@ "Couldn't change the email address because the user does not exist" : "آدرس ایمیل تغییر نمی کند زیرا کاربر موجود نیست", "Couldn't change the email address because the token is invalid" : "آدرس ایمیل تغییر نمی کند زیرا نشانه معتبر نیست", "Your %s account was created" : "حساب کاربری شما %s ایجاد شد", - "Invalid mail address" : "آدرس ایمیل نامعتبر است", "A user with that name already exists." : "کاربری با همین نام در حال حاضر وجود دارد.", "Unable to create user." : "ایجاد کاربر امکان‌پذیر نیست.", "Unable to delete user." : "حذف کاربر امکان پذیر نیست.", @@ -38,6 +37,7 @@ "%s email address changed successfully" : "%s آدرس ایمیل با موفقیت تغییر کرد", "Couldn't send email address change notification mail. Please contact your administrator." : "ایمیل اعلان تغییر آدرس ایمیل ارسال نمی شود. لطفا با مدیر خود تماس بگیرید.", "Unable to enable/disable user." : "فعال سازی/غیر فعال سازی کاربر ممکن نیست.", + "Invalid mail address" : "آدرس ایمیل نامعتبر است", "Create" : "ایجاد کردن", "Change" : "تغییر", "Delete" : "حذف", diff --git a/settings/l10n/fi_FI.js b/settings/l10n/fi_FI.js index 5dbe2963974a..49514b0ea8b7 100644 --- a/settings/l10n/fi_FI.js +++ b/settings/l10n/fi_FI.js @@ -19,7 +19,6 @@ OC.L10N.register( "Email sent" : "Sähköposti lähetetty", "You need to set your user email before being able to send test emails." : "Aseta sähköpostiosoite, jotta voit testata sähköpostin toimivuutta.", "Your %s account was created" : "%s-tilisi luotiin", - "Invalid mail address" : "Virheellinen sähköpostiosoite", "A user with that name already exists." : "Käyttäjä samalla nimellä on jo olemassa.", "Unable to create user." : "Käyttäjän luominen ei onnistunut.", "Unable to delete user." : "Käyttäjän poistaminen ei onnistunut.", @@ -35,6 +34,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s sähköpostiosoite vaihdettu onnistuneesti", "Couldn't send email address change notification mail. Please contact your administrator." : "Ei voitu lähettää sähköpostiosoitteen vaihtamisen ilmoitusta. Ole hyvä ja ota yhteyttä järjestelmänvalvojaan.", "Unable to enable/disable user." : "Ei voitu ottaa käyttöön tai poistaa käytöstä käyttäjää", + "Invalid mail address" : "Virheellinen sähköpostiosoite", "Create" : "Luo", "Change" : "Muuta", "Delete" : "Poista", diff --git a/settings/l10n/fi_FI.json b/settings/l10n/fi_FI.json index adfdb4116243..0e46ef7fc995 100644 --- a/settings/l10n/fi_FI.json +++ b/settings/l10n/fi_FI.json @@ -17,7 +17,6 @@ "Email sent" : "Sähköposti lähetetty", "You need to set your user email before being able to send test emails." : "Aseta sähköpostiosoite, jotta voit testata sähköpostin toimivuutta.", "Your %s account was created" : "%s-tilisi luotiin", - "Invalid mail address" : "Virheellinen sähköpostiosoite", "A user with that name already exists." : "Käyttäjä samalla nimellä on jo olemassa.", "Unable to create user." : "Käyttäjän luominen ei onnistunut.", "Unable to delete user." : "Käyttäjän poistaminen ei onnistunut.", @@ -33,6 +32,7 @@ "%s email address changed successfully" : "%s sähköpostiosoite vaihdettu onnistuneesti", "Couldn't send email address change notification mail. Please contact your administrator." : "Ei voitu lähettää sähköpostiosoitteen vaihtamisen ilmoitusta. Ole hyvä ja ota yhteyttä järjestelmänvalvojaan.", "Unable to enable/disable user." : "Ei voitu ottaa käyttöön tai poistaa käytöstä käyttäjää", + "Invalid mail address" : "Virheellinen sähköpostiosoite", "Create" : "Luo", "Change" : "Muuta", "Delete" : "Poista", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index 2e0c8e573307..36140556340e 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -27,7 +27,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Le courriel n'a pas pu être mise à jour car l'utilisateur n'existe pas", "Couldn't change the email address because the token is invalid" : "Le courriel n'a pas pu être mise à jour car le jeton est invalide", "Your %s account was created" : "Votre compte %s a été créé", - "Invalid mail address" : "Adresse e-mail non valide", "A user with that name already exists." : "Un utilisateur avec ce nom existe déjà.", "Unable to create user." : "Impossible de créer l'utilisateur.", "The token provided is invalid." : "Le jeton fourni n'est pas valide.", @@ -52,6 +51,7 @@ OC.L10N.register( "%s email address changed successfully" : "l'adresse de courriel %s a été modifiée avec succès", "Couldn't send email address change notification mail. Please contact your administrator." : "Impossible d'envoyer un courriel de notification de changement d'adresse. Veuillez contacter votre administrateur.", "Unable to enable/disable user." : "Impossible d'activer/désactiver l'utilisateur.", + "Invalid mail address" : "Adresse e-mail non valide", "Owner language" : "Langue du propriétaire", "Create" : "Créer", "Change" : "Modification", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index a4fc02ecb4fa..62c33eae80eb 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -25,7 +25,6 @@ "Couldn't change the email address because the user does not exist" : "Le courriel n'a pas pu être mise à jour car l'utilisateur n'existe pas", "Couldn't change the email address because the token is invalid" : "Le courriel n'a pas pu être mise à jour car le jeton est invalide", "Your %s account was created" : "Votre compte %s a été créé", - "Invalid mail address" : "Adresse e-mail non valide", "A user with that name already exists." : "Un utilisateur avec ce nom existe déjà.", "Unable to create user." : "Impossible de créer l'utilisateur.", "The token provided is invalid." : "Le jeton fourni n'est pas valide.", @@ -50,6 +49,7 @@ "%s email address changed successfully" : "l'adresse de courriel %s a été modifiée avec succès", "Couldn't send email address change notification mail. Please contact your administrator." : "Impossible d'envoyer un courriel de notification de changement d'adresse. Veuillez contacter votre administrateur.", "Unable to enable/disable user." : "Impossible d'activer/désactiver l'utilisateur.", + "Invalid mail address" : "Adresse e-mail non valide", "Owner language" : "Langue du propriétaire", "Create" : "Créer", "Change" : "Modification", diff --git a/settings/l10n/gl.js b/settings/l10n/gl.js index 3f7d5a82e7e9..0d201cd43470 100644 --- a/settings/l10n/gl.js +++ b/settings/l10n/gl.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Non é posíbel cambiar o enderezo do correo xa que o usuario non existe", "Couldn't change the email address because the token is invalid" : "Non é posíbel cambiar o enderezo do correo xa que o testemuño non é válido", "Your %s account was created" : "Foi creada a conta %s", - "Invalid mail address" : "Enderezo de correo incorrecto", "A user with that name already exists." : "Xa existe un usuario con ese nome.", "Unable to create user." : "Non é posíbel crear o usuario.", "The token provided is invalid." : "O testemuño fornecido non é válido.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "O enderezo de correo %s foi cambiado satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "Non é posíbel enviar o correo de notificación do cambio de enderezo. Póñase en contacto co administrador.", "Unable to enable/disable user." : "Non é posíbel activar/desactivar o usuario.", + "Invalid mail address" : "Enderezo de correo incorrecto", "Owner language" : "Idioma do propietario", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/gl.json b/settings/l10n/gl.json index 864e092d10fe..21d4439c7e80 100644 --- a/settings/l10n/gl.json +++ b/settings/l10n/gl.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Non é posíbel cambiar o enderezo do correo xa que o usuario non existe", "Couldn't change the email address because the token is invalid" : "Non é posíbel cambiar o enderezo do correo xa que o testemuño non é válido", "Your %s account was created" : "Foi creada a conta %s", - "Invalid mail address" : "Enderezo de correo incorrecto", "A user with that name already exists." : "Xa existe un usuario con ese nome.", "Unable to create user." : "Non é posíbel crear o usuario.", "The token provided is invalid." : "O testemuño fornecido non é válido.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "O enderezo de correo %s foi cambiado satisfactoriamente", "Couldn't send email address change notification mail. Please contact your administrator." : "Non é posíbel enviar o correo de notificación do cambio de enderezo. Póñase en contacto co administrador.", "Unable to enable/disable user." : "Non é posíbel activar/desactivar o usuario.", + "Invalid mail address" : "Enderezo de correo incorrecto", "Owner language" : "Idioma do propietario", "Create" : "Crear", "Change" : "Cambiar", diff --git a/settings/l10n/he.js b/settings/l10n/he.js index 976685170667..a1698fc7c261 100644 --- a/settings/l10n/he.js +++ b/settings/l10n/he.js @@ -27,7 +27,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "לא ניתן היה לשנות את כתובת הדואר האלקטרוני כיוון שהמשתמש אינו קיים", "Couldn't change the email address because the token is invalid" : "לא ניתן היה לשנות את כתובת הדואר האלקטרוני כיוון שחתימת הייצוג אינה חוקית", "Your %s account was created" : "חשבון %s שלך נוצר", - "Invalid mail address" : "כתובת דואר אלקטרוני לא חוקית", "A user with that name already exists." : "משתמש בשם זה כבר קיים.", "Unable to create user." : "לא ניתן ליצור משתמש.", "The token provided is invalid." : "חתימת הייצוג שסופקה אינה חוקית.", @@ -52,6 +51,7 @@ OC.L10N.register( "%s email address changed successfully" : "כתובת הדואר האלקטרוני %s הוחלפה בהצלחה", "Couldn't send email address change notification mail. Please contact your administrator." : "לא ניתן היה לשלוח הודעת אימות לכתובת הדואר האלקטרוני החדשה. יש ליצור קשר עם מנהל המערכת שלך.", "Unable to enable/disable user." : "לא ניתן היה לנטרל / לבטל ניטרול משתמש.", + "Invalid mail address" : "כתובת דואר אלקטרוני לא חוקית", "Owner language" : "שפת בעל התוכן", "Create" : "יצירה", "Change" : "שינוי", diff --git a/settings/l10n/he.json b/settings/l10n/he.json index f273b6df96e0..1b73589d1680 100644 --- a/settings/l10n/he.json +++ b/settings/l10n/he.json @@ -25,7 +25,6 @@ "Couldn't change the email address because the user does not exist" : "לא ניתן היה לשנות את כתובת הדואר האלקטרוני כיוון שהמשתמש אינו קיים", "Couldn't change the email address because the token is invalid" : "לא ניתן היה לשנות את כתובת הדואר האלקטרוני כיוון שחתימת הייצוג אינה חוקית", "Your %s account was created" : "חשבון %s שלך נוצר", - "Invalid mail address" : "כתובת דואר אלקטרוני לא חוקית", "A user with that name already exists." : "משתמש בשם זה כבר קיים.", "Unable to create user." : "לא ניתן ליצור משתמש.", "The token provided is invalid." : "חתימת הייצוג שסופקה אינה חוקית.", @@ -50,6 +49,7 @@ "%s email address changed successfully" : "כתובת הדואר האלקטרוני %s הוחלפה בהצלחה", "Couldn't send email address change notification mail. Please contact your administrator." : "לא ניתן היה לשלוח הודעת אימות לכתובת הדואר האלקטרוני החדשה. יש ליצור קשר עם מנהל המערכת שלך.", "Unable to enable/disable user." : "לא ניתן היה לנטרל / לבטל ניטרול משתמש.", + "Invalid mail address" : "כתובת דואר אלקטרוני לא חוקית", "Owner language" : "שפת בעל התוכן", "Create" : "יצירה", "Change" : "שינוי", diff --git a/settings/l10n/hu_HU.js b/settings/l10n/hu_HU.js index 4ee93d3d0fbb..de1ae4d91d45 100644 --- a/settings/l10n/hu_HU.js +++ b/settings/l10n/hu_HU.js @@ -25,7 +25,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Az email címet men lehet megváltoztatni mert a felhasználó nem létezik", "Couldn't change the email address because the token is invalid" : "Nem sikerült megváltoztatni az e-mail címet, mert a token érvénytelen", "Your %s account was created" : "%s fiók létrehozva", - "Invalid mail address" : "Érvénytelen e-mail cím", "A user with that name already exists." : "Ilyen névvel már létezik felhasználó!", "Unable to create user." : "Nem lehet létrehozni a felhasználót.", "Unable to delete user." : "Nem lehet törölni a felhasználót.", @@ -43,6 +42,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s az email cím megváltoztatása sikeres", "Couldn't send email address change notification mail. Please contact your administrator." : "Nem sikerült elküldeni az e-mail cím módosítási értesítést. Kérjük, lépjen kapcsolatba a rendszergazdájával.", "Unable to enable/disable user." : "A felhasználó engedélyezése / tiltása nem lehetséges.", + "Invalid mail address" : "Érvénytelen e-mail cím", "Create" : "Létrehozás", "Change" : "Változás", "Delete" : "Törlés", diff --git a/settings/l10n/hu_HU.json b/settings/l10n/hu_HU.json index 0258eb39d45a..e7778281a60e 100644 --- a/settings/l10n/hu_HU.json +++ b/settings/l10n/hu_HU.json @@ -23,7 +23,6 @@ "Couldn't change the email address because the user does not exist" : "Az email címet men lehet megváltoztatni mert a felhasználó nem létezik", "Couldn't change the email address because the token is invalid" : "Nem sikerült megváltoztatni az e-mail címet, mert a token érvénytelen", "Your %s account was created" : "%s fiók létrehozva", - "Invalid mail address" : "Érvénytelen e-mail cím", "A user with that name already exists." : "Ilyen névvel már létezik felhasználó!", "Unable to create user." : "Nem lehet létrehozni a felhasználót.", "Unable to delete user." : "Nem lehet törölni a felhasználót.", @@ -41,6 +40,7 @@ "%s email address changed successfully" : "%s az email cím megváltoztatása sikeres", "Couldn't send email address change notification mail. Please contact your administrator." : "Nem sikerült elküldeni az e-mail cím módosítási értesítést. Kérjük, lépjen kapcsolatba a rendszergazdájával.", "Unable to enable/disable user." : "A felhasználó engedélyezése / tiltása nem lehetséges.", + "Invalid mail address" : "Érvénytelen e-mail cím", "Create" : "Létrehozás", "Change" : "Változás", "Delete" : "Törlés", diff --git a/settings/l10n/hy.js b/settings/l10n/hy.js index ca9bf9740d08..7d1066ec228b 100644 --- a/settings/l10n/hy.js +++ b/settings/l10n/hy.js @@ -5,12 +5,12 @@ OC.L10N.register( "Unable to delete group." : "Չկարողացա ջնջել խումբը", "Saved" : "Պահված", "Email sent" : "Էլ. նամակը ուղարկվեց", - "Invalid mail address" : "Անվավեր էլ. հասցե", "Unable to delete user." : "Չկարողացա ջնջել օգտատիրոջը", "Forbidden" : "Արգելված", "Invalid user" : "Անվավեր օգտատեր", "Unable to change mail address" : "Չկարողացա փոխել էլ. հասցեն", "Unable to change full name" : "Չկարողացա փոխել լրիվ անունը", + "Invalid mail address" : "Անվավեր էլ. հասցե", "Create" : "Ստեղծել", "Delete" : "Ջնջել", "Share" : "Կիսվել", diff --git a/settings/l10n/hy.json b/settings/l10n/hy.json index 6e398d16f907..630be385776a 100644 --- a/settings/l10n/hy.json +++ b/settings/l10n/hy.json @@ -3,12 +3,12 @@ "Unable to delete group." : "Չկարողացա ջնջել խումբը", "Saved" : "Պահված", "Email sent" : "Էլ. նամակը ուղարկվեց", - "Invalid mail address" : "Անվավեր էլ. հասցե", "Unable to delete user." : "Չկարողացա ջնջել օգտատիրոջը", "Forbidden" : "Արգելված", "Invalid user" : "Անվավեր օգտատեր", "Unable to change mail address" : "Չկարողացա փոխել էլ. հասցեն", "Unable to change full name" : "Չկարողացա փոխել լրիվ անունը", + "Invalid mail address" : "Անվավեր էլ. հասցե", "Create" : "Ստեղծել", "Delete" : "Ջնջել", "Share" : "Կիսվել", diff --git a/settings/l10n/id.js b/settings/l10n/id.js index 87b43f4f371c..819ea66b02c9 100644 --- a/settings/l10n/id.js +++ b/settings/l10n/id.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Alamat surel tidak dapat diganti karena penggunanya tidak ada", "Couldn't change the email address because the token is invalid" : "Alamat surel tidak dapat diganti karena token tidak sah", "Your %s account was created" : "Akun %s Anda telah dibuat", - "Invalid mail address" : "Alamat email salah", "A user with that name already exists." : "Pengguna dengan nama tersebut sudah ada.", "Unable to create user." : "Tidak dapat membuat pengguna.", "The token provided is invalid." : "Token tidak sah.", @@ -48,6 +47,7 @@ OC.L10N.register( "Unable to change full name" : "Tidak dapat mengubah nama lengkap", "%s email address confirm" : "%s alamat surel konfirmasi", "%s email address changed successfully" : "%s alamat surel berhasil diganti", + "Invalid mail address" : "Alamat email salah", "Create" : "Buat", "Delete" : "Hapus", "Share" : "Bagikan", diff --git a/settings/l10n/id.json b/settings/l10n/id.json index 9388987967fe..2bfe7ba445d3 100644 --- a/settings/l10n/id.json +++ b/settings/l10n/id.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "Alamat surel tidak dapat diganti karena penggunanya tidak ada", "Couldn't change the email address because the token is invalid" : "Alamat surel tidak dapat diganti karena token tidak sah", "Your %s account was created" : "Akun %s Anda telah dibuat", - "Invalid mail address" : "Alamat email salah", "A user with that name already exists." : "Pengguna dengan nama tersebut sudah ada.", "Unable to create user." : "Tidak dapat membuat pengguna.", "The token provided is invalid." : "Token tidak sah.", @@ -46,6 +45,7 @@ "Unable to change full name" : "Tidak dapat mengubah nama lengkap", "%s email address confirm" : "%s alamat surel konfirmasi", "%s email address changed successfully" : "%s alamat surel berhasil diganti", + "Invalid mail address" : "Alamat email salah", "Create" : "Buat", "Delete" : "Hapus", "Share" : "Bagikan", diff --git a/settings/l10n/is.js b/settings/l10n/is.js index b3e8a10ac805..abf78df9d73d 100644 --- a/settings/l10n/is.js +++ b/settings/l10n/is.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Gat ekki breytt tölvupóstfanginu vegna þess að notandinn er ekki til", "Couldn't change the email address because the token is invalid" : "Gat ekki breytt tölvupóstfanginu vegna þess að teiknið er ógilt", "Your %s account was created" : "%s notandaaðgangurinn þinn var búinn til", - "Invalid mail address" : "Ógilt tölvupóstfang", "A user with that name already exists." : "Nú þegar til notandi með þetta nafn.", "Unable to create user." : "Gat ekki búið til notanda.", "The token provided is invalid." : "Teiknið sem þú gafst upp er ógilt.", @@ -45,6 +44,7 @@ OC.L10N.register( "%s email address changed successfully" : "Tókst að breyta tölvupóstfangi %s", "Couldn't send email address change notification mail. Please contact your administrator." : "Gat ekki sent póst um breytingu á tölvupóstfangi. Hafðu samband við kerfisstjóra.", "Unable to enable/disable user." : "Get ekki virkjað/afvirkjað notanda.", + "Invalid mail address" : "Ógilt tölvupóstfang", "Owner language" : "Tungumál eiganda", "Create" : "Búa til", "Change" : "Skipta um", diff --git a/settings/l10n/is.json b/settings/l10n/is.json index 5a1cd5064d79..3e3f963b824d 100644 --- a/settings/l10n/is.json +++ b/settings/l10n/is.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "Gat ekki breytt tölvupóstfanginu vegna þess að notandinn er ekki til", "Couldn't change the email address because the token is invalid" : "Gat ekki breytt tölvupóstfanginu vegna þess að teiknið er ógilt", "Your %s account was created" : "%s notandaaðgangurinn þinn var búinn til", - "Invalid mail address" : "Ógilt tölvupóstfang", "A user with that name already exists." : "Nú þegar til notandi með þetta nafn.", "Unable to create user." : "Gat ekki búið til notanda.", "The token provided is invalid." : "Teiknið sem þú gafst upp er ógilt.", @@ -43,6 +42,7 @@ "%s email address changed successfully" : "Tókst að breyta tölvupóstfangi %s", "Couldn't send email address change notification mail. Please contact your administrator." : "Gat ekki sent póst um breytingu á tölvupóstfangi. Hafðu samband við kerfisstjóra.", "Unable to enable/disable user." : "Get ekki virkjað/afvirkjað notanda.", + "Invalid mail address" : "Ógilt tölvupóstfang", "Owner language" : "Tungumál eiganda", "Create" : "Búa til", "Change" : "Skipta um", diff --git a/settings/l10n/it.js b/settings/l10n/it.js index 3bf63a9a99bc..f26592e255b8 100644 --- a/settings/l10n/it.js +++ b/settings/l10n/it.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Impossibile cambiare indirizzo mail in quanto l'utente non esiste", "Couldn't change the email address because the token is invalid" : "Impossibile cambiare indirizzo email in quanto il token è invalido", "Your %s account was created" : "Il tuo account %s è stato creato", - "Invalid mail address" : "Indirizzo email non valido", "A user with that name already exists." : "Un utente con quel nome esiste già.", "Unable to create user." : "Impossibile creare l'utente.", "The token provided is invalid." : "Il token fornito non è valido.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%sindirizzo di email cambiato con successo", "Couldn't send email address change notification mail. Please contact your administrator." : "Impossibile inviare email di conferma per cambio indirizzo. Contatta l'amministratore.", "Unable to enable/disable user." : "Impossibile abilitare/disabilitare l'utente.", + "Invalid mail address" : "Indirizzo email non valido", "Owner language" : "Lingua del proprietario", "Create" : "Crea", "Change" : "Cambia", diff --git a/settings/l10n/it.json b/settings/l10n/it.json index d43023919a0f..e21400b4c3fd 100644 --- a/settings/l10n/it.json +++ b/settings/l10n/it.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Impossibile cambiare indirizzo mail in quanto l'utente non esiste", "Couldn't change the email address because the token is invalid" : "Impossibile cambiare indirizzo email in quanto il token è invalido", "Your %s account was created" : "Il tuo account %s è stato creato", - "Invalid mail address" : "Indirizzo email non valido", "A user with that name already exists." : "Un utente con quel nome esiste già.", "Unable to create user." : "Impossibile creare l'utente.", "The token provided is invalid." : "Il token fornito non è valido.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%sindirizzo di email cambiato con successo", "Couldn't send email address change notification mail. Please contact your administrator." : "Impossibile inviare email di conferma per cambio indirizzo. Contatta l'amministratore.", "Unable to enable/disable user." : "Impossibile abilitare/disabilitare l'utente.", + "Invalid mail address" : "Indirizzo email non valido", "Owner language" : "Lingua del proprietario", "Create" : "Crea", "Change" : "Cambia", diff --git a/settings/l10n/ja.js b/settings/l10n/ja.js index 508e78022a44..169de8246382 100644 --- a/settings/l10n/ja.js +++ b/settings/l10n/ja.js @@ -27,7 +27,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "ユーザが存在しない為、emailアドレスを変更出来ませんでした。", "Couldn't change the email address because the token is invalid" : "無効なトークンを利用している為、emailアドレスが変更出来ませんでした。", "Your %s account was created" : "アカウント %s を作成しました", - "Invalid mail address" : "無効なメールアドレスです", "A user with that name already exists." : "そのユーザー名はすでに存在します。", "Unable to create user." : "ユーザーを追加できません。", "Failed to set password. Please contact the administrator." : "パスワードの設定に失敗しました。管理者に問い合わせてください。", @@ -48,6 +47,7 @@ OC.L10N.register( "%s email address changed successfully" : "%sメールアドレスを変更しました", "Couldn't send email address change notification mail. Please contact your administrator." : "メールアドレスの変更を通知するメールを送ることができませんでした。\n管理者に問い合わせてください。", "Unable to enable/disable user." : "ユーザの有効化/無効化に失敗しました。", + "Invalid mail address" : "無効なメールアドレスです", "Owner language" : "所有者の言語", "Create" : "作成", "Change" : "更新", diff --git a/settings/l10n/ja.json b/settings/l10n/ja.json index 2868719ca5c7..cf104a7d960f 100644 --- a/settings/l10n/ja.json +++ b/settings/l10n/ja.json @@ -25,7 +25,6 @@ "Couldn't change the email address because the user does not exist" : "ユーザが存在しない為、emailアドレスを変更出来ませんでした。", "Couldn't change the email address because the token is invalid" : "無効なトークンを利用している為、emailアドレスが変更出来ませんでした。", "Your %s account was created" : "アカウント %s を作成しました", - "Invalid mail address" : "無効なメールアドレスです", "A user with that name already exists." : "そのユーザー名はすでに存在します。", "Unable to create user." : "ユーザーを追加できません。", "Failed to set password. Please contact the administrator." : "パスワードの設定に失敗しました。管理者に問い合わせてください。", @@ -46,6 +45,7 @@ "%s email address changed successfully" : "%sメールアドレスを変更しました", "Couldn't send email address change notification mail. Please contact your administrator." : "メールアドレスの変更を通知するメールを送ることができませんでした。\n管理者に問い合わせてください。", "Unable to enable/disable user." : "ユーザの有効化/無効化に失敗しました。", + "Invalid mail address" : "無効なメールアドレスです", "Owner language" : "所有者の言語", "Create" : "作成", "Change" : "更新", diff --git a/settings/l10n/ka_GE.js b/settings/l10n/ka_GE.js index 6384df9dddf4..600c9c9876a3 100644 --- a/settings/l10n/ka_GE.js +++ b/settings/l10n/ka_GE.js @@ -17,6 +17,7 @@ OC.L10N.register( "Updating...." : "მიმდინარეობს განახლება....", "Error while updating app" : "შეცდომა აპლიკაციის განახლების დროს", "Updated" : "განახლებულია", + "Select a profile picture" : "აირჩიეთ პროფილის სურათი", "Groups" : "ჯგუფები", "undo" : "დაბრუნება", "Delete group" : "ჯგუფის წაშლა", @@ -27,6 +28,7 @@ OC.L10N.register( "disabled" : "გათიშულია", "A valid username must be provided" : "უნდა მიუთითოთ არსებული მომხმარებლის სახელი", "A valid password must be provided" : "უნდა მიუთითოთ არსებული პაროლი", + "Cheers!" : "გამარჯვებები!", "Language" : "ენა", "Cron" : "Cron–ი", "Execute one task with each page loaded" : "გაუშვი თითო მოქმედება ყველა ჩატვირთულ გვერდზე", @@ -45,6 +47,9 @@ OC.L10N.register( "Get the apps to sync your files" : "აპლიკაცია ფაილების სინქრონიზაციისთვის", "Show First Run Wizard again" : "მაჩვენე თავიდან გაშვებული ვიზარდი", "Add" : "დამატება", + "Profile picture" : "პროფილის სურათი", + "Upload new" : "ატვირთე ახალი", + "Remove image" : "სურათის მოშორება", "Cancel" : "უარყოფა", "Email" : "იმეილი", "Your email address" : "თქვენი იმეილ მისამართი", diff --git a/settings/l10n/ka_GE.json b/settings/l10n/ka_GE.json index 9aa838795f90..6cd342601c1e 100644 --- a/settings/l10n/ka_GE.json +++ b/settings/l10n/ka_GE.json @@ -15,6 +15,7 @@ "Updating...." : "მიმდინარეობს განახლება....", "Error while updating app" : "შეცდომა აპლიკაციის განახლების დროს", "Updated" : "განახლებულია", + "Select a profile picture" : "აირჩიეთ პროფილის სურათი", "Groups" : "ჯგუფები", "undo" : "დაბრუნება", "Delete group" : "ჯგუფის წაშლა", @@ -25,6 +26,7 @@ "disabled" : "გათიშულია", "A valid username must be provided" : "უნდა მიუთითოთ არსებული მომხმარებლის სახელი", "A valid password must be provided" : "უნდა მიუთითოთ არსებული პაროლი", + "Cheers!" : "გამარჯვებები!", "Language" : "ენა", "Cron" : "Cron–ი", "Execute one task with each page loaded" : "გაუშვი თითო მოქმედება ყველა ჩატვირთულ გვერდზე", @@ -43,6 +45,9 @@ "Get the apps to sync your files" : "აპლიკაცია ფაილების სინქრონიზაციისთვის", "Show First Run Wizard again" : "მაჩვენე თავიდან გაშვებული ვიზარდი", "Add" : "დამატება", + "Profile picture" : "პროფილის სურათი", + "Upload new" : "ატვირთე ახალი", + "Remove image" : "სურათის მოშორება", "Cancel" : "უარყოფა", "Email" : "იმეილი", "Your email address" : "თქვენი იმეილ მისამართი", diff --git a/settings/l10n/kn.js b/settings/l10n/kn.js index 648f0e17f41c..81bc34a538df 100644 --- a/settings/l10n/kn.js +++ b/settings/l10n/kn.js @@ -13,7 +13,6 @@ OC.L10N.register( "Email sent" : "ಇ-ಅಂಚೆ ಕಳುಹಿಸಲಾಗಿದೆ", "You need to set your user email before being able to send test emails." : "ನೀವು ಪರೀಕ್ಷಾ ಇ-ಅಂಚೆಯನ್ನು ಕಳುಹಿಸುವ ಮುನ್ನ ನಿಮ್ಮ ಬಳಕೆದಾರ ಇ-ಅಂಚೆಯನ್ನು ಹೊಂದಿಸಬೇಕಾಗುತ್ತದೆ.", "Your %s account was created" : "ನಿಮ್ಮ%s ಖಾತೆಯನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ", - "Invalid mail address" : "ಅಮಾನ್ಯ ಇ-ಅಂಚೆ ವಿಳಾಸ", "Unable to create user." : "ಬಳಕೆದಾರನ ಖಾತೆ ರಚಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ.", "Unable to delete user." : "ಬಳಕೆದಾರನ ಹೆಸರುನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ.", "Forbidden" : "ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", @@ -21,6 +20,7 @@ OC.L10N.register( "Unable to change mail address" : "ಇ-ಅಂಚೆ ವಿಳಾಸ ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ", "Your full name has been changed." : "ನಿಮ್ಮ ಪೂರ್ಣ ಹೆಸರನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ.", "Unable to change full name" : "ಪೂರ್ಣ ಹೆಸರನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ", + "Invalid mail address" : "ಅಮಾನ್ಯ ಇ-ಅಂಚೆ ವಿಳಾಸ", "Create" : "ಸೃಷ್ಟಿಸಿ", "Delete" : "ಅಳಿಸಿ", "Share" : "ಹಂಚಿಕೊಳ್ಳಿ", diff --git a/settings/l10n/kn.json b/settings/l10n/kn.json index 1aea4659998b..2e73fb339c5f 100644 --- a/settings/l10n/kn.json +++ b/settings/l10n/kn.json @@ -11,7 +11,6 @@ "Email sent" : "ಇ-ಅಂಚೆ ಕಳುಹಿಸಲಾಗಿದೆ", "You need to set your user email before being able to send test emails." : "ನೀವು ಪರೀಕ್ಷಾ ಇ-ಅಂಚೆಯನ್ನು ಕಳುಹಿಸುವ ಮುನ್ನ ನಿಮ್ಮ ಬಳಕೆದಾರ ಇ-ಅಂಚೆಯನ್ನು ಹೊಂದಿಸಬೇಕಾಗುತ್ತದೆ.", "Your %s account was created" : "ನಿಮ್ಮ%s ಖಾತೆಯನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ", - "Invalid mail address" : "ಅಮಾನ್ಯ ಇ-ಅಂಚೆ ವಿಳಾಸ", "Unable to create user." : "ಬಳಕೆದಾರನ ಖಾತೆ ರಚಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ.", "Unable to delete user." : "ಬಳಕೆದಾರನ ಹೆಸರುನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ.", "Forbidden" : "ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", @@ -19,6 +18,7 @@ "Unable to change mail address" : "ಇ-ಅಂಚೆ ವಿಳಾಸ ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ", "Your full name has been changed." : "ನಿಮ್ಮ ಪೂರ್ಣ ಹೆಸರನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ.", "Unable to change full name" : "ಪೂರ್ಣ ಹೆಸರನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ", + "Invalid mail address" : "ಅಮಾನ್ಯ ಇ-ಅಂಚೆ ವಿಳಾಸ", "Create" : "ಸೃಷ್ಟಿಸಿ", "Delete" : "ಅಳಿಸಿ", "Share" : "ಹಂಚಿಕೊಳ್ಳಿ", diff --git a/settings/l10n/ko.js b/settings/l10n/ko.js index 27b4cb1cf3cf..ac6e680cbe76 100644 --- a/settings/l10n/ko.js +++ b/settings/l10n/ko.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "사용자가 존재하지 않기 때문에 이메일 주소를 변경할 수 없음", "Couldn't change the email address because the token is invalid" : "토큰이 잘못되었기 때문에 이메일 주소를 변경할 수 없음", "Your %s account was created" : "%s 계정을 등록했습니다", - "Invalid mail address" : "잘못된 이메일 주소", "A user with that name already exists." : "같은 이름의 사용자가 이미 존재합니다.", "Unable to create user." : "사용자를 만들 수 없습니다.", "The token provided is invalid." : "제공된 토큰이 유효하지 않습니다.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s 이메일 주소가 성공적으로 변경됨", "Couldn't send email address change notification mail. Please contact your administrator." : "아메일 주소 변경 알림 메일을 보낼 수 없습니다. 관리자에게 문의하십시오.", "Unable to enable/disable user." : "사용자를 활성화/비활성화할 수 없습니다.", + "Invalid mail address" : "잘못된 이메일 주소", "Owner language" : "주사용 언어", "Create" : "만들기", "Change" : "변경", diff --git a/settings/l10n/ko.json b/settings/l10n/ko.json index c3f4757c98d2..2f159c40f7d1 100644 --- a/settings/l10n/ko.json +++ b/settings/l10n/ko.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "사용자가 존재하지 않기 때문에 이메일 주소를 변경할 수 없음", "Couldn't change the email address because the token is invalid" : "토큰이 잘못되었기 때문에 이메일 주소를 변경할 수 없음", "Your %s account was created" : "%s 계정을 등록했습니다", - "Invalid mail address" : "잘못된 이메일 주소", "A user with that name already exists." : "같은 이름의 사용자가 이미 존재합니다.", "Unable to create user." : "사용자를 만들 수 없습니다.", "The token provided is invalid." : "제공된 토큰이 유효하지 않습니다.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s 이메일 주소가 성공적으로 변경됨", "Couldn't send email address change notification mail. Please contact your administrator." : "아메일 주소 변경 알림 메일을 보낼 수 없습니다. 관리자에게 문의하십시오.", "Unable to enable/disable user." : "사용자를 활성화/비활성화할 수 없습니다.", + "Invalid mail address" : "잘못된 이메일 주소", "Owner language" : "주사용 언어", "Create" : "만들기", "Change" : "변경", diff --git a/settings/l10n/lb.js b/settings/l10n/lb.js index 745c174fd64f..b1e5928936a7 100644 --- a/settings/l10n/lb.js +++ b/settings/l10n/lb.js @@ -15,7 +15,6 @@ OC.L10N.register( "Email sent" : "Email geschéckt", "You need to set your user email before being able to send test emails." : "Du muss deng Email-Adress konfiguréieren éiers de Test-Maile schécke kanns.", "Your %s account was created" : "Däin %s Kont gouf erschaf", - "Invalid mail address" : "Ongëlteg Email Adress", "A user with that name already exists." : "E Benotzer mat dësem Numm existéiert schonn.", "Unable to create user." : "Onméiglech de Benotzer ze erschafen.", "Unable to delete user." : "Onmeiglech fir de User zu läschen.", @@ -25,6 +24,7 @@ OC.L10N.register( "Unable to change display name" : "Unmeiglech den Nickname ze änneren.", "Your full name has been changed." : "Äre ganzen Numm ass geännert ginn.", "Unable to change full name" : "Onméiglech de ganzen Numm ze änneren.", + "Invalid mail address" : "Ongëlteg Email Adress", "Create" : "Erstellen", "Delete" : "Läschen", "Share" : "Deelen", diff --git a/settings/l10n/lb.json b/settings/l10n/lb.json index 1fe8ee6d8a32..10461f3792cc 100644 --- a/settings/l10n/lb.json +++ b/settings/l10n/lb.json @@ -13,7 +13,6 @@ "Email sent" : "Email geschéckt", "You need to set your user email before being able to send test emails." : "Du muss deng Email-Adress konfiguréieren éiers de Test-Maile schécke kanns.", "Your %s account was created" : "Däin %s Kont gouf erschaf", - "Invalid mail address" : "Ongëlteg Email Adress", "A user with that name already exists." : "E Benotzer mat dësem Numm existéiert schonn.", "Unable to create user." : "Onméiglech de Benotzer ze erschafen.", "Unable to delete user." : "Onmeiglech fir de User zu läschen.", @@ -23,6 +22,7 @@ "Unable to change display name" : "Unmeiglech den Nickname ze änneren.", "Your full name has been changed." : "Äre ganzen Numm ass geännert ginn.", "Unable to change full name" : "Onméiglech de ganzen Numm ze änneren.", + "Invalid mail address" : "Ongëlteg Email Adress", "Create" : "Erstellen", "Delete" : "Läschen", "Share" : "Deelen", diff --git a/settings/l10n/lt_LT.js b/settings/l10n/lt_LT.js index 31caa96f87f7..60cfbf1787a8 100644 --- a/settings/l10n/lt_LT.js +++ b/settings/l10n/lt_LT.js @@ -24,7 +24,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Negalima pakeisti El. pašto adreso, kadangi naudotojas neegzistuoja", "Couldn't change the email address because the token is invalid" : "Nepavyko pakeisti el. pašto adreso nes tokenas negalioja", "Your %s account was created" : "Tavo paskyra %s sukurta", - "Invalid mail address" : "Neteisingas pašto adresas", "A user with that name already exists." : "Naudotojas tokiu vardu jau egzistuoja.", "Unable to create user." : "Nepavyko sukurti naudotojo.", "Unable to delete user." : "Nepavyko ištrinti naudotojo.", @@ -37,6 +36,7 @@ OC.L10N.register( "Your full name has been changed." : "Pilnas vardas pakeistas.", "Unable to change full name" : "Nepavyko pakeisti pilno vardo", "%s email address confirm" : "%sel. pašto adresas patvirtinimui", + "Invalid mail address" : "Neteisingas pašto adresas", "Create" : "Sukurti", "Change" : "Keisti", "Delete" : "Ištrinti", diff --git a/settings/l10n/lt_LT.json b/settings/l10n/lt_LT.json index a80e1c7ddd18..e4d1c633bc2f 100644 --- a/settings/l10n/lt_LT.json +++ b/settings/l10n/lt_LT.json @@ -22,7 +22,6 @@ "Couldn't change the email address because the user does not exist" : "Negalima pakeisti El. pašto adreso, kadangi naudotojas neegzistuoja", "Couldn't change the email address because the token is invalid" : "Nepavyko pakeisti el. pašto adreso nes tokenas negalioja", "Your %s account was created" : "Tavo paskyra %s sukurta", - "Invalid mail address" : "Neteisingas pašto adresas", "A user with that name already exists." : "Naudotojas tokiu vardu jau egzistuoja.", "Unable to create user." : "Nepavyko sukurti naudotojo.", "Unable to delete user." : "Nepavyko ištrinti naudotojo.", @@ -35,6 +34,7 @@ "Your full name has been changed." : "Pilnas vardas pakeistas.", "Unable to change full name" : "Nepavyko pakeisti pilno vardo", "%s email address confirm" : "%sel. pašto adresas patvirtinimui", + "Invalid mail address" : "Neteisingas pašto adresas", "Create" : "Sukurti", "Change" : "Keisti", "Delete" : "Ištrinti", diff --git a/settings/l10n/lv.js b/settings/l10n/lv.js index 8ced5cc9f376..4bd74d23ec1a 100644 --- a/settings/l10n/lv.js +++ b/settings/l10n/lv.js @@ -20,7 +20,6 @@ OC.L10N.register( "You need to set your user email before being able to send test emails." : "Nepieciešams norādīt sava lietotāja e-pasta adresi, lai nosūtīta testa e-pastus.", "Couldn't change the email address because the user does not exist" : "Neizdevās nomainīt e-pasta adresi, jo lietotājs neeksistē", "Your %s account was created" : "Konts %s ir izveidots", - "Invalid mail address" : "Nepareiza e-pasta adrese", "A user with that name already exists." : "Jau pastāv lietotājs ar šo vārdu.", "Unable to create user." : "Nevar izveidot lietotāju.", "Can't send email to the user. Contact your administrator." : "Neizdevās nosūtīt e-pastu lietotājam. Lūdzu, sazinieties ar administratoru.", @@ -38,6 +37,7 @@ OC.L10N.register( "Unable to change full name" : "Nav iespējams nomainīt jūsu pilno vārdu", "%s email address changed successfully" : "%s e-pasta adrese ir veiksmīgi nomainīta", "Unable to enable/disable user." : "Nevar iespējot/atspējot lietotāju.", + "Invalid mail address" : "Nepareiza e-pasta adrese", "Create" : "Izveidot", "Change" : "Izmainīt", "Delete" : "Dzēst", diff --git a/settings/l10n/lv.json b/settings/l10n/lv.json index c8cb40930e5b..28664cc6cc3c 100644 --- a/settings/l10n/lv.json +++ b/settings/l10n/lv.json @@ -18,7 +18,6 @@ "You need to set your user email before being able to send test emails." : "Nepieciešams norādīt sava lietotāja e-pasta adresi, lai nosūtīta testa e-pastus.", "Couldn't change the email address because the user does not exist" : "Neizdevās nomainīt e-pasta adresi, jo lietotājs neeksistē", "Your %s account was created" : "Konts %s ir izveidots", - "Invalid mail address" : "Nepareiza e-pasta adrese", "A user with that name already exists." : "Jau pastāv lietotājs ar šo vārdu.", "Unable to create user." : "Nevar izveidot lietotāju.", "Can't send email to the user. Contact your administrator." : "Neizdevās nosūtīt e-pastu lietotājam. Lūdzu, sazinieties ar administratoru.", @@ -36,6 +35,7 @@ "Unable to change full name" : "Nav iespējams nomainīt jūsu pilno vārdu", "%s email address changed successfully" : "%s e-pasta adrese ir veiksmīgi nomainīta", "Unable to enable/disable user." : "Nevar iespējot/atspējot lietotāju.", + "Invalid mail address" : "Nepareiza e-pasta adrese", "Create" : "Izveidot", "Change" : "Izmainīt", "Delete" : "Dzēst", diff --git a/settings/l10n/mk.js b/settings/l10n/mk.js index 2dff8b58a97a..5cefddb59f6a 100644 --- a/settings/l10n/mk.js +++ b/settings/l10n/mk.js @@ -24,7 +24,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Неможе да се промени Email адресата бидејќи корисникот не постои", "Couldn't change the email address because the token is invalid" : "Неможе да се промени Email адресата бидејќи токенот е неважечки", "Your %s account was created" : "Вашата %s сметка е креирана", - "Invalid mail address" : "Невалидна Email адреса", "A user with that name already exists." : "Корисник со ова име веќе постои.", "Unable to create user." : "Неможе да додадам корисник.", "The token provided is invalid." : "Токенот е неважечки.", @@ -49,6 +48,7 @@ OC.L10N.register( "%s email address changed successfully" : "Email адресата%s е успешно променета", "Couldn't send email address change notification mail. Please contact your administrator." : "Неможе да се испрати известување за промена на Email адреса. Контактирајте го администраторот.", "Unable to enable/disable user." : "Не може да се овозможи/оневозможи корисникот.", + "Invalid mail address" : "Невалидна Email адреса", "Owner language" : "Јазикот на сопственикот", "Create" : "Создај", "Change" : "Промени", diff --git a/settings/l10n/mk.json b/settings/l10n/mk.json index b99ebe0fb61c..25cdf592e669 100644 --- a/settings/l10n/mk.json +++ b/settings/l10n/mk.json @@ -22,7 +22,6 @@ "Couldn't change the email address because the user does not exist" : "Неможе да се промени Email адресата бидејќи корисникот не постои", "Couldn't change the email address because the token is invalid" : "Неможе да се промени Email адресата бидејќи токенот е неважечки", "Your %s account was created" : "Вашата %s сметка е креирана", - "Invalid mail address" : "Невалидна Email адреса", "A user with that name already exists." : "Корисник со ова име веќе постои.", "Unable to create user." : "Неможе да додадам корисник.", "The token provided is invalid." : "Токенот е неважечки.", @@ -47,6 +46,7 @@ "%s email address changed successfully" : "Email адресата%s е успешно променета", "Couldn't send email address change notification mail. Please contact your administrator." : "Неможе да се испрати известување за промена на Email адреса. Контактирајте го администраторот.", "Unable to enable/disable user." : "Не може да се овозможи/оневозможи корисникот.", + "Invalid mail address" : "Невалидна Email адреса", "Owner language" : "Јазикот на сопственикот", "Create" : "Создај", "Change" : "Промени", diff --git a/settings/l10n/nb_NO.js b/settings/l10n/nb_NO.js index 12e329369129..efb77461da92 100644 --- a/settings/l10n/nb_NO.js +++ b/settings/l10n/nb_NO.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Kunne ikke endre epost-adressen fordi brukeren ikke finnes", "Couldn't change the email address because the token is invalid" : "Kunne ikke endre epost-adressen fordi symbolet er ugyldig", "Your %s account was created" : "%s-kontoen din ble opprettet", - "Invalid mail address" : "Ugyldig e-postadresse", "A user with that name already exists." : "Det finnes allerede en bruker med det navnet.", "Unable to create user." : "Kan ikke opprette bruker.", "The token provided is invalid." : "Token er ugyldig", @@ -51,6 +50,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s epost-adresse endret", "Couldn't send email address change notification mail. Please contact your administrator." : "Klarte ikke å sende varsel-epost om endring av epost-adresse. Kontakt administratoren.", "Unable to enable/disable user." : "Kan ikke aktivere/deaktivere bruker.", + "Invalid mail address" : "Ugyldig e-postadresse", "Owner language" : "Eierspråk", "Create" : "Opprett", "Change" : "Endre", diff --git a/settings/l10n/nb_NO.json b/settings/l10n/nb_NO.json index 6f0decf72f51..dcf263e2639a 100644 --- a/settings/l10n/nb_NO.json +++ b/settings/l10n/nb_NO.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "Kunne ikke endre epost-adressen fordi brukeren ikke finnes", "Couldn't change the email address because the token is invalid" : "Kunne ikke endre epost-adressen fordi symbolet er ugyldig", "Your %s account was created" : "%s-kontoen din ble opprettet", - "Invalid mail address" : "Ugyldig e-postadresse", "A user with that name already exists." : "Det finnes allerede en bruker med det navnet.", "Unable to create user." : "Kan ikke opprette bruker.", "The token provided is invalid." : "Token er ugyldig", @@ -49,6 +48,7 @@ "%s email address changed successfully" : "%s epost-adresse endret", "Couldn't send email address change notification mail. Please contact your administrator." : "Klarte ikke å sende varsel-epost om endring av epost-adresse. Kontakt administratoren.", "Unable to enable/disable user." : "Kan ikke aktivere/deaktivere bruker.", + "Invalid mail address" : "Ugyldig e-postadresse", "Owner language" : "Eierspråk", "Create" : "Opprett", "Change" : "Endre", diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js index c804df5d8585..9b244d1a09c8 100644 --- a/settings/l10n/nl.js +++ b/settings/l10n/nl.js @@ -23,7 +23,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Kon het e-mailadres niet wijzigen omdat de gebruiker niet bestaat", "Couldn't change the email address because the token is invalid" : "Kon het e-mailadres niet wijzigen omdat het token ongeldig is", "Your %s account was created" : "Uw %s account is aangemaakt", - "Invalid mail address" : "Ongeldig e-mailadres", "A user with that name already exists." : "Er bestaat al een gebruiker met die naam.", "Unable to create user." : "Kan gebruiker niet aanmaken.", "The token provided is invalid." : "Het doorgegeven token is ongeldig.", @@ -48,6 +47,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s e-mailadres succesvol gewijzigd.", "Couldn't send email address change notification mail. Please contact your administrator." : "Kon meldingssbericht voor wijziging e-mailadres niet versturen. Neem contact op met uw beheerder.", "Unable to enable/disable user." : "Kan gebruiker niet activeren/deactiveren.", + "Invalid mail address" : "Ongeldig e-mailadres", "Create" : "Aanmaken", "Change" : "Wijzigen", "Delete" : "Verwijder", diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json index 76202354abbe..c61ec5d62579 100644 --- a/settings/l10n/nl.json +++ b/settings/l10n/nl.json @@ -21,7 +21,6 @@ "Couldn't change the email address because the user does not exist" : "Kon het e-mailadres niet wijzigen omdat de gebruiker niet bestaat", "Couldn't change the email address because the token is invalid" : "Kon het e-mailadres niet wijzigen omdat het token ongeldig is", "Your %s account was created" : "Uw %s account is aangemaakt", - "Invalid mail address" : "Ongeldig e-mailadres", "A user with that name already exists." : "Er bestaat al een gebruiker met die naam.", "Unable to create user." : "Kan gebruiker niet aanmaken.", "The token provided is invalid." : "Het doorgegeven token is ongeldig.", @@ -46,6 +45,7 @@ "%s email address changed successfully" : "%s e-mailadres succesvol gewijzigd.", "Couldn't send email address change notification mail. Please contact your administrator." : "Kon meldingssbericht voor wijziging e-mailadres niet versturen. Neem contact op met uw beheerder.", "Unable to enable/disable user." : "Kan gebruiker niet activeren/deactiveren.", + "Invalid mail address" : "Ongeldig e-mailadres", "Create" : "Aanmaken", "Change" : "Wijzigen", "Delete" : "Verwijder", diff --git a/settings/l10n/oc.js b/settings/l10n/oc.js index 31d306c8c340..406e4e6d6a37 100644 --- a/settings/l10n/oc.js +++ b/settings/l10n/oc.js @@ -18,7 +18,6 @@ OC.L10N.register( "Email sent" : "Email mandat", "You need to set your user email before being able to send test emails." : "Vos cal especificar vòstra adreça email dins los paramètres personals abans de poder mandar d'emails de tèst.", "Your %s account was created" : "Vòstre compte %s es estat creat.", - "Invalid mail address" : "Adreça email invalida", "A user with that name already exists." : "Un utilizaire amb aqueste nom existís ja.", "Unable to create user." : "Impossible de crear l'utilizaire.", "Unable to delete user." : "Impossible de suprimir l'utilizaire.", @@ -27,6 +26,7 @@ OC.L10N.register( "Unable to change mail address" : "Impossible de modificar l'adreça de corrièl", "Your full name has been changed." : "Vòstre nom complet es estat modificat.", "Unable to change full name" : "Impossible de cambiar lo nom complet", + "Invalid mail address" : "Adreça email invalida", "Create" : "Crear", "Delete" : "Suprimir", "Share" : "Partejar", diff --git a/settings/l10n/oc.json b/settings/l10n/oc.json index f3427e2e7bc9..ae7252dbe5af 100644 --- a/settings/l10n/oc.json +++ b/settings/l10n/oc.json @@ -16,7 +16,6 @@ "Email sent" : "Email mandat", "You need to set your user email before being able to send test emails." : "Vos cal especificar vòstra adreça email dins los paramètres personals abans de poder mandar d'emails de tèst.", "Your %s account was created" : "Vòstre compte %s es estat creat.", - "Invalid mail address" : "Adreça email invalida", "A user with that name already exists." : "Un utilizaire amb aqueste nom existís ja.", "Unable to create user." : "Impossible de crear l'utilizaire.", "Unable to delete user." : "Impossible de suprimir l'utilizaire.", @@ -25,6 +24,7 @@ "Unable to change mail address" : "Impossible de modificar l'adreça de corrièl", "Your full name has been changed." : "Vòstre nom complet es estat modificat.", "Unable to change full name" : "Impossible de cambiar lo nom complet", + "Invalid mail address" : "Adreça email invalida", "Create" : "Crear", "Delete" : "Suprimir", "Share" : "Partejar", diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index 7d556cd3b84e..f456d85c6fa7 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -26,7 +26,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Nie można zmienić adresu email ponieważ użytkownik nie istnieje.", "Couldn't change the email address because the token is invalid" : "Nie można zmienić adresu email ponieważ podano nieprawidłowy token.", "Your %s account was created" : "Utworzono konto %s", - "Invalid mail address" : "Nieprawidłowy adres email", "A user with that name already exists." : "Użytkownik z taką nazwą już istnieje.", "Unable to create user." : "Nie można utworzyć użytkownika.", "The token provided is invalid." : "Podany token jest nieprawidłowy.", @@ -51,6 +50,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s adres email zmieniony pomyślnie.", "Couldn't send email address change notification mail. Please contact your administrator." : "Nie można wysłać wiadomości potwierdzającej zmianę maila. Proszę skontaktować się z administratorem.", "Unable to enable/disable user." : "Nie można odblokować/zablokować użytkownika.", + "Invalid mail address" : "Nieprawidłowy adres email", "Owner language" : "Język posiadacza", "Create" : "Utwórz", "Change" : "Zmień", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index 468aaa7c327d..908d08b32320 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -24,7 +24,6 @@ "Couldn't change the email address because the user does not exist" : "Nie można zmienić adresu email ponieważ użytkownik nie istnieje.", "Couldn't change the email address because the token is invalid" : "Nie można zmienić adresu email ponieważ podano nieprawidłowy token.", "Your %s account was created" : "Utworzono konto %s", - "Invalid mail address" : "Nieprawidłowy adres email", "A user with that name already exists." : "Użytkownik z taką nazwą już istnieje.", "Unable to create user." : "Nie można utworzyć użytkownika.", "The token provided is invalid." : "Podany token jest nieprawidłowy.", @@ -49,6 +48,7 @@ "%s email address changed successfully" : "%s adres email zmieniony pomyślnie.", "Couldn't send email address change notification mail. Please contact your administrator." : "Nie można wysłać wiadomości potwierdzającej zmianę maila. Proszę skontaktować się z administratorem.", "Unable to enable/disable user." : "Nie można odblokować/zablokować użytkownika.", + "Invalid mail address" : "Nieprawidłowy adres email", "Owner language" : "Język posiadacza", "Create" : "Utwórz", "Change" : "Zmień", diff --git a/settings/l10n/pt_BR.js b/settings/l10n/pt_BR.js index 7d215f39d934..7789083dd637 100644 --- a/settings/l10n/pt_BR.js +++ b/settings/l10n/pt_BR.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Não foi possível alterar o endereço de e-mail porque o usuário não existe", "Couldn't change the email address because the token is invalid" : "Não foi possível alterar o endereço de e-mail porque o token é inválido", "Your %s account was created" : "Sua conta %s foi criada", - "Invalid mail address" : "Endereço de e-mail inválido", "A user with that name already exists." : "Um usuário com esse nome já existe.", "Unable to create user." : "Não é possível criar usuário.", "The token provided is invalid." : "O token fornecido é inválido.", @@ -53,6 +52,8 @@ OC.L10N.register( "%s email address changed successfully" : "O endereço de e-mail %s foi alterado com êxito", "Couldn't send email address change notification mail. Please contact your administrator." : "Não foi possível enviar email de notificação de alteração de endereço. Entre em contato com o administrador.", "Unable to enable/disable user." : "Não foi possível habilitar/desabilitar usuário", + "Data too long" : "Dados muito longos", + "Invalid mail address" : "Endereço de e-mail inválido", "Owner language" : "Idioma do proprietário", "Create" : "Criar", "Change" : "Substituir ", @@ -196,6 +197,16 @@ OC.L10N.register( "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Você precisa migrar suas chaves de criptografia a partir da antiga criptografia (ownCloud <= 8,0) para a nova. Ative o \"módulo de criptografia padrão\" e execute 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Você precisa migrar suas chaves de criptografia a partir da antiga criptografia (ownCloud <= 8,0) para a nova.", "Start migration" : "Iniciar migração", + "Two-factor Authentication" : "Autenticação de dois fatores", + "This section requires a two-factor authentication app to be installed in ownCloud" : "Esta seção requer que um aplicativo de autenticação de dois fatores seja instalado no ownCloud", + "Enforce two-factor authentication" : "Aplicar a autenticação de dois fatores", + "Before enforcing the two-factor authentication, check the following requirements:" : "Antes de aplicar a autenticação de dois fatores, verifique os seguintes requisitos:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "Pelo menos um aplicativo de autenticação de dois fatores está instalado e ativado no ownCloud.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "Os usuários podem configurar pelo menos um aplicativo de dois fatores na página do desafio. Alguns aplicativos podem não estar preparados para isso", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "O aplicativo \"twofactor_totp\" atende a esses requisitos e pode ser usado como um substituto para que os usuários possam inserir suas contas para configurar outros aplicativos de autenticação de dois fatores", + "Enforce two-factor authentication to all the users" : "Aplicar a autenticação de dois fatores a todos os usuários", + "Exclude the following groups from enforcing two-factor authentication" : "Exclude the following groups from enforcing two-factor authentication", + "Note: Users in these groups can use two-factor authentication on their own" : "Note: Users in these groups can use two-factor authentication on their own", "Sharing" : "Compartilhamento", "Allow apps to use the Share API" : "Permitir que aplicativos usem a API de Compartilhamento", "Allow users to share via link" : "Permitir que os usuários compartilhem por link", diff --git a/settings/l10n/pt_BR.json b/settings/l10n/pt_BR.json index 3f0251edd3dc..026867720094 100644 --- a/settings/l10n/pt_BR.json +++ b/settings/l10n/pt_BR.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Não foi possível alterar o endereço de e-mail porque o usuário não existe", "Couldn't change the email address because the token is invalid" : "Não foi possível alterar o endereço de e-mail porque o token é inválido", "Your %s account was created" : "Sua conta %s foi criada", - "Invalid mail address" : "Endereço de e-mail inválido", "A user with that name already exists." : "Um usuário com esse nome já existe.", "Unable to create user." : "Não é possível criar usuário.", "The token provided is invalid." : "O token fornecido é inválido.", @@ -51,6 +50,8 @@ "%s email address changed successfully" : "O endereço de e-mail %s foi alterado com êxito", "Couldn't send email address change notification mail. Please contact your administrator." : "Não foi possível enviar email de notificação de alteração de endereço. Entre em contato com o administrador.", "Unable to enable/disable user." : "Não foi possível habilitar/desabilitar usuário", + "Data too long" : "Dados muito longos", + "Invalid mail address" : "Endereço de e-mail inválido", "Owner language" : "Idioma do proprietário", "Create" : "Criar", "Change" : "Substituir ", @@ -194,6 +195,16 @@ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Você precisa migrar suas chaves de criptografia a partir da antiga criptografia (ownCloud <= 8,0) para a nova. Ative o \"módulo de criptografia padrão\" e execute 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Você precisa migrar suas chaves de criptografia a partir da antiga criptografia (ownCloud <= 8,0) para a nova.", "Start migration" : "Iniciar migração", + "Two-factor Authentication" : "Autenticação de dois fatores", + "This section requires a two-factor authentication app to be installed in ownCloud" : "Esta seção requer que um aplicativo de autenticação de dois fatores seja instalado no ownCloud", + "Enforce two-factor authentication" : "Aplicar a autenticação de dois fatores", + "Before enforcing the two-factor authentication, check the following requirements:" : "Antes de aplicar a autenticação de dois fatores, verifique os seguintes requisitos:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "Pelo menos um aplicativo de autenticação de dois fatores está instalado e ativado no ownCloud.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "Os usuários podem configurar pelo menos um aplicativo de dois fatores na página do desafio. Alguns aplicativos podem não estar preparados para isso", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "O aplicativo \"twofactor_totp\" atende a esses requisitos e pode ser usado como um substituto para que os usuários possam inserir suas contas para configurar outros aplicativos de autenticação de dois fatores", + "Enforce two-factor authentication to all the users" : "Aplicar a autenticação de dois fatores a todos os usuários", + "Exclude the following groups from enforcing two-factor authentication" : "Exclude the following groups from enforcing two-factor authentication", + "Note: Users in these groups can use two-factor authentication on their own" : "Note: Users in these groups can use two-factor authentication on their own", "Sharing" : "Compartilhamento", "Allow apps to use the Share API" : "Permitir que aplicativos usem a API de Compartilhamento", "Allow users to share via link" : "Permitir que os usuários compartilhem por link", diff --git a/settings/l10n/pt_PT.js b/settings/l10n/pt_PT.js index 8c454ee4f37c..f3a67b6f7cf4 100644 --- a/settings/l10n/pt_PT.js +++ b/settings/l10n/pt_PT.js @@ -23,7 +23,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Não foi possível alterar o endereço de correio eletrónico porque o utilizador não existe", "Couldn't change the email address because the token is invalid" : "Não foi possível alterar o endereço de correio eletrónico porque a senha é inválida", "Your %s account was created" : "A sua conta %s foi criada", - "Invalid mail address" : "Endereço de e-mail inválido", "A user with that name already exists." : "Já existe um utilizador com esse nome.", "Unable to create user." : "Não é possível criar o utilizador.", "Unable to delete user." : "Não é possível eliminar o utilizador.", @@ -41,6 +40,7 @@ OC.L10N.register( "%s email address changed successfully" : "O endereço de e-mail de %s foi alterado com sucesso", "Couldn't send email address change notification mail. Please contact your administrator." : "Não foi possível enviar a mensagem de notificação da alteração do endereço de e-mail. Por favor, contacte o seu administrador.", "Unable to enable/disable user." : "Não é possível ativar/desativar o utilizador.", + "Invalid mail address" : "Endereço de e-mail inválido", "Create" : "Criar", "Change" : "Alterar", "Delete" : "Eliminar", diff --git a/settings/l10n/pt_PT.json b/settings/l10n/pt_PT.json index fbd7998b6646..ab3988eee5d9 100644 --- a/settings/l10n/pt_PT.json +++ b/settings/l10n/pt_PT.json @@ -21,7 +21,6 @@ "Couldn't change the email address because the user does not exist" : "Não foi possível alterar o endereço de correio eletrónico porque o utilizador não existe", "Couldn't change the email address because the token is invalid" : "Não foi possível alterar o endereço de correio eletrónico porque a senha é inválida", "Your %s account was created" : "A sua conta %s foi criada", - "Invalid mail address" : "Endereço de e-mail inválido", "A user with that name already exists." : "Já existe um utilizador com esse nome.", "Unable to create user." : "Não é possível criar o utilizador.", "Unable to delete user." : "Não é possível eliminar o utilizador.", @@ -39,6 +38,7 @@ "%s email address changed successfully" : "O endereço de e-mail de %s foi alterado com sucesso", "Couldn't send email address change notification mail. Please contact your administrator." : "Não foi possível enviar a mensagem de notificação da alteração do endereço de e-mail. Por favor, contacte o seu administrador.", "Unable to enable/disable user." : "Não é possível ativar/desativar o utilizador.", + "Invalid mail address" : "Endereço de e-mail inválido", "Create" : "Criar", "Change" : "Alterar", "Delete" : "Eliminar", diff --git a/settings/l10n/ro.js b/settings/l10n/ro.js index ace146483f4d..0c17b01e640b 100644 --- a/settings/l10n/ro.js +++ b/settings/l10n/ro.js @@ -20,7 +20,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Nu am putut modifica adresa de e-mail deoarece utilizatorul nu există", "Couldn't change the email address because the token is invalid" : "Nu am putut modifica adresa de e-mail, deoarece tokenul nu este valid", "Your %s account was created" : "Contul tău %s a fost creat", - "Invalid mail address" : "Adresa mail invalidă", "A user with that name already exists." : "Există deja un utilizator cu acest nume.", "Unable to create user." : "Imposibil de creat utilizatorul.", "Unable to delete user." : "Imposibil de șters utilizatorul.", @@ -37,6 +36,7 @@ OC.L10N.register( "%s email address changed successfully" : "adresa e-mail %s a fost schimbată cu succes", "Couldn't send email address change notification mail. Please contact your administrator." : "Nu am putut trimite e-mail de notificare a schimbării adresei de e-mail. Contactează administratorul tău.", "Unable to enable/disable user." : "Imposibil de activat/dezactivat utilizator.", + "Invalid mail address" : "Adresa mail invalidă", "Create" : "Crează", "Delete" : "Șterge", "Share" : "Partajează", diff --git a/settings/l10n/ro.json b/settings/l10n/ro.json index d9220d081392..af4b177cf976 100644 --- a/settings/l10n/ro.json +++ b/settings/l10n/ro.json @@ -18,7 +18,6 @@ "Couldn't change the email address because the user does not exist" : "Nu am putut modifica adresa de e-mail deoarece utilizatorul nu există", "Couldn't change the email address because the token is invalid" : "Nu am putut modifica adresa de e-mail, deoarece tokenul nu este valid", "Your %s account was created" : "Contul tău %s a fost creat", - "Invalid mail address" : "Adresa mail invalidă", "A user with that name already exists." : "Există deja un utilizator cu acest nume.", "Unable to create user." : "Imposibil de creat utilizatorul.", "Unable to delete user." : "Imposibil de șters utilizatorul.", @@ -35,6 +34,7 @@ "%s email address changed successfully" : "adresa e-mail %s a fost schimbată cu succes", "Couldn't send email address change notification mail. Please contact your administrator." : "Nu am putut trimite e-mail de notificare a schimbării adresei de e-mail. Contactează administratorul tău.", "Unable to enable/disable user." : "Imposibil de activat/dezactivat utilizator.", + "Invalid mail address" : "Adresa mail invalidă", "Create" : "Crează", "Delete" : "Șterge", "Share" : "Partajează", diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index ff4005540941..4e70f6b75c6e 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Не удалось изменить адрес почты, так как пользователь не существует", "Couldn't change the email address because the token is invalid" : "Не удалось изменить адрес почты, так как токен неправильный", "Your %s account was created" : "Учетная запись %s создана", - "Invalid mail address" : "Некорректный адрес электронной почты", "A user with that name already exists." : "Пользователь с таким именем уже существует.", "Unable to create user." : "Невозможно создать пользователя.", "The token provided is invalid." : "Предоставленный токен неверен.", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "Адрес почты для %s изменён успешно", "Couldn't send email address change notification mail. Please contact your administrator." : "Не удалось отправить сообщение с уведомлением об изменении адреса почты. Пожалуйста, свяжитесь со своим администратором.", "Unable to enable/disable user." : "Невозможно включить/выключить пользователя.", + "Invalid mail address" : "Некорректный адрес электронной почты", "Owner language" : "Язык владельца", "Create" : "Создать", "Change" : "Изменения", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 6cd3e7b09e72..5656361d73dd 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Не удалось изменить адрес почты, так как пользователь не существует", "Couldn't change the email address because the token is invalid" : "Не удалось изменить адрес почты, так как токен неправильный", "Your %s account was created" : "Учетная запись %s создана", - "Invalid mail address" : "Некорректный адрес электронной почты", "A user with that name already exists." : "Пользователь с таким именем уже существует.", "Unable to create user." : "Невозможно создать пользователя.", "The token provided is invalid." : "Предоставленный токен неверен.", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "Адрес почты для %s изменён успешно", "Couldn't send email address change notification mail. Please contact your administrator." : "Не удалось отправить сообщение с уведомлением об изменении адреса почты. Пожалуйста, свяжитесь со своим администратором.", "Unable to enable/disable user." : "Невозможно включить/выключить пользователя.", + "Invalid mail address" : "Некорректный адрес электронной почты", "Owner language" : "Язык владельца", "Create" : "Создать", "Change" : "Изменения", diff --git a/settings/l10n/sk_SK.js b/settings/l10n/sk_SK.js index 229a5abc0af2..518976cf27ea 100644 --- a/settings/l10n/sk_SK.js +++ b/settings/l10n/sk_SK.js @@ -17,7 +17,6 @@ OC.L10N.register( "Email sent" : "Email odoslaný", "You need to set your user email before being able to send test emails." : "Musíte nastaviť svoj po​​užívateľský email, než budete môcť odoslať testovací email.", "Your %s account was created" : "Váš účet %s bol vytvorený", - "Invalid mail address" : "Neplatná emailová adresa", "A user with that name already exists." : "Používateľ s týmto menom už existuje.", "Unable to create user." : "Nie je možné vytvoriť používateľa.", "Unable to delete user." : "Nie je možné zmazať používateľa.", @@ -27,6 +26,7 @@ OC.L10N.register( "Unable to change display name" : "Nemožno zmeniť zobrazované meno", "Your full name has been changed." : "Vaše meno a priezvisko bolo zmenené.", "Unable to change full name" : "Nemožno zmeniť meno a priezvisko", + "Invalid mail address" : "Neplatná emailová adresa", "Create" : "Vytvoriť", "Delete" : "Zmazať", "Share" : "Zdieľať", diff --git a/settings/l10n/sk_SK.json b/settings/l10n/sk_SK.json index bd4085ee1874..af134e45669d 100644 --- a/settings/l10n/sk_SK.json +++ b/settings/l10n/sk_SK.json @@ -15,7 +15,6 @@ "Email sent" : "Email odoslaný", "You need to set your user email before being able to send test emails." : "Musíte nastaviť svoj po​​užívateľský email, než budete môcť odoslať testovací email.", "Your %s account was created" : "Váš účet %s bol vytvorený", - "Invalid mail address" : "Neplatná emailová adresa", "A user with that name already exists." : "Používateľ s týmto menom už existuje.", "Unable to create user." : "Nie je možné vytvoriť používateľa.", "Unable to delete user." : "Nie je možné zmazať používateľa.", @@ -25,6 +24,7 @@ "Unable to change display name" : "Nemožno zmeniť zobrazované meno", "Your full name has been changed." : "Vaše meno a priezvisko bolo zmenené.", "Unable to change full name" : "Nemožno zmeniť meno a priezvisko", + "Invalid mail address" : "Neplatná emailová adresa", "Create" : "Vytvoriť", "Delete" : "Zmazať", "Share" : "Zdieľať", diff --git a/settings/l10n/sl.js b/settings/l10n/sl.js index c90723954203..e9ce61544593 100644 --- a/settings/l10n/sl.js +++ b/settings/l10n/sl.js @@ -22,7 +22,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Elektronskega naslova ni mogoče spremeniti, ker uporabnik s tem naslovom ne obstaja", "Couldn't change the email address because the token is invalid" : "Ni mogoče spremeniti naslova elektronske pošte, ker je žeton neveljaven.", "Your %s account was created" : "Račun %s je uspešno ustvarjen.", - "Invalid mail address" : "Neveljaven elektronski naslov", "A user with that name already exists." : "Uporabnik s tem imenom že obstaja.", "Unable to create user." : "Ni mogoče ustvariti uporabnika.", "Unable to delete user." : "Ni mogoče izbrisati uporabnika", @@ -34,6 +33,7 @@ OC.L10N.register( "Your full name has been changed." : "Vaše polno ime je spremenjeno.", "Unable to change full name" : "Ni mogoče spremeniti polnega imena", "Unable to enable/disable user." : "Ni mogoče omogočiti/onemogočiti dostopa uporabnika.", + "Invalid mail address" : "Neveljaven elektronski naslov", "Create" : "Ustvari", "Delete" : "Izbriši", "Share" : "Souporaba", diff --git a/settings/l10n/sl.json b/settings/l10n/sl.json index c5e03ce6c19c..08cfd2c011a9 100644 --- a/settings/l10n/sl.json +++ b/settings/l10n/sl.json @@ -20,7 +20,6 @@ "Couldn't change the email address because the user does not exist" : "Elektronskega naslova ni mogoče spremeniti, ker uporabnik s tem naslovom ne obstaja", "Couldn't change the email address because the token is invalid" : "Ni mogoče spremeniti naslova elektronske pošte, ker je žeton neveljaven.", "Your %s account was created" : "Račun %s je uspešno ustvarjen.", - "Invalid mail address" : "Neveljaven elektronski naslov", "A user with that name already exists." : "Uporabnik s tem imenom že obstaja.", "Unable to create user." : "Ni mogoče ustvariti uporabnika.", "Unable to delete user." : "Ni mogoče izbrisati uporabnika", @@ -32,6 +31,7 @@ "Your full name has been changed." : "Vaše polno ime je spremenjeno.", "Unable to change full name" : "Ni mogoče spremeniti polnega imena", "Unable to enable/disable user." : "Ni mogoče omogočiti/onemogočiti dostopa uporabnika.", + "Invalid mail address" : "Neveljaven elektronski naslov", "Create" : "Ustvari", "Delete" : "Izbriši", "Share" : "Souporaba", diff --git a/settings/l10n/sq.js b/settings/l10n/sq.js index 6f4c8bc1f953..3fc3c3922201 100644 --- a/settings/l10n/sq.js +++ b/settings/l10n/sq.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "S’u ndryshua dot adresa email, ngaqë përdoruesi s’ekziston", "Couldn't change the email address because the token is invalid" : "S’u ndryshua dot adresa email, ngaqë token-i është i pavlefshëm", "Your %s account was created" : "Llogaria juaj %s u krijua", - "Invalid mail address" : "Adresë email e pavlefshme", "A user with that name already exists." : "Ka tashmë një përdorues me këtë emër.", "Unable to create user." : "S’arrihet të krijohet përdoruesi.", "The token provided is invalid." : "Token-i i dhënë është i pavlefshëm.", @@ -53,6 +52,8 @@ OC.L10N.register( "%s email address changed successfully" : "Adresa email %s u ndryshua me sukses", "Couldn't send email address change notification mail. Please contact your administrator." : "S’u dërgua dot email njoftimi ndryshimi adrese email. Ju lutemi, lidhuni me përgjegjësin tuaj.", "Unable to enable/disable user." : "S’arrihet të aktivizohet/çaktivizohet përdoruesi.", + "Data too long" : "Të dhëna shumë të gjata", + "Invalid mail address" : "Adresë email e pavlefshme", "Owner language" : "Gjuha e të zotit", "Create" : "Krijoje", "Change" : "Ndryshoje", @@ -196,6 +197,16 @@ OC.L10N.register( "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Lypset të migroni kyçet tuaj të fshehtëzimit nga fshehtëzimi i vjetër (ownCloud <= 8.0) te i riu. Ju lutemi, aktivizoni “Modul parazgjedhje fshehtëzimesh” dhe ekzekutoni 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Lypset të migroni kyçet tuaj të fshehtëzimit nga fshehtëzimi i vjetër (ownCloud <= 8.0) te i riu.", "Start migration" : "Fillo migrimin", + "Two-factor Authentication" : "Mirëfilltësim Dyfaktorësh", + "This section requires a two-factor authentication app to be installed in ownCloud" : "Kjo ndarje lyp të instaluar në ownCloud një aplikacion mirëfilltësimi dyfaktorësh", + "Enforce two-factor authentication" : "Zbato me detyrim mirëfilltësim dyfaktorësh", + "Before enforcing the two-factor authentication, check the following requirements:" : "Para zbatimit me detyrim të mirëfilltësimit dyfaktorësh, kontrollo për domosdoshmëritë vijuese:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "Në ownCloud të jetë instaluar dhe aktivizuar të paktën një aplikacion mirëfilltësimi dyfaktorësh.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "Përdoruesi mundet të ujdisë të paktën një aplikacion mirëfilltësimi dyfaktorësh që nga faqja e kërkesë. Disa aplikacione mund të mos jenë përgatitur për këtë", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "Aplikacion “twofactor_totp” plotëson këto domosdoshmëri dhe mund të përdoret si rrugëdalje, që kështu përdoruesit të hyjnë në llogaritë e tyre për të formësuar aplikacione të tjera mirëfilltësimi dyfaktorësh", + "Enforce two-factor authentication to all the users" : "Zbato me detyrim mirëfilltësim dyfaktorësh për krejt përdoruesit", + "Exclude the following groups from enforcing two-factor authentication" : "Përjashto nga zbatimi i detyruar i mirëfilltësimit dyfaktorësh grupet vijuese", + "Note: Users in these groups can use two-factor authentication on their own" : "Shënim: Përdoruesit në këto grupe mund të përdorin mirëfilltësim të tyrin dyfaktorësh", "Sharing" : "Ndarje me të tjerët", "Allow apps to use the Share API" : "Lejoni aplikacionet të përdorin API Share", "Allow users to share via link" : "Lejoji përdoruesit të ndajnë me të tjerët përmes lidhjesh", @@ -268,6 +279,7 @@ OC.L10N.register( "SMTP Username" : "Emër përdoruesi SMTP", "SMTP Password" : "Fjalëkalim SMTP", "Store credentials" : "Depozitoji kredencialet", + "Test receiver email" : "Provoni email marrësi", "Test email settings" : "Testoni rregullimet e email-it", "Send email" : "Dërgo email", "Manual File Locking" : "Kyçje Dorazi Kartelash", diff --git a/settings/l10n/sq.json b/settings/l10n/sq.json index e1d9f06b21d2..3037f9e07670 100644 --- a/settings/l10n/sq.json +++ b/settings/l10n/sq.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "S’u ndryshua dot adresa email, ngaqë përdoruesi s’ekziston", "Couldn't change the email address because the token is invalid" : "S’u ndryshua dot adresa email, ngaqë token-i është i pavlefshëm", "Your %s account was created" : "Llogaria juaj %s u krijua", - "Invalid mail address" : "Adresë email e pavlefshme", "A user with that name already exists." : "Ka tashmë një përdorues me këtë emër.", "Unable to create user." : "S’arrihet të krijohet përdoruesi.", "The token provided is invalid." : "Token-i i dhënë është i pavlefshëm.", @@ -51,6 +50,8 @@ "%s email address changed successfully" : "Adresa email %s u ndryshua me sukses", "Couldn't send email address change notification mail. Please contact your administrator." : "S’u dërgua dot email njoftimi ndryshimi adrese email. Ju lutemi, lidhuni me përgjegjësin tuaj.", "Unable to enable/disable user." : "S’arrihet të aktivizohet/çaktivizohet përdoruesi.", + "Data too long" : "Të dhëna shumë të gjata", + "Invalid mail address" : "Adresë email e pavlefshme", "Owner language" : "Gjuha e të zotit", "Create" : "Krijoje", "Change" : "Ndryshoje", @@ -194,6 +195,16 @@ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Lypset të migroni kyçet tuaj të fshehtëzimit nga fshehtëzimi i vjetër (ownCloud <= 8.0) te i riu. Ju lutemi, aktivizoni “Modul parazgjedhje fshehtëzimesh” dhe ekzekutoni 'occ encryption:migrate'", "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Lypset të migroni kyçet tuaj të fshehtëzimit nga fshehtëzimi i vjetër (ownCloud <= 8.0) te i riu.", "Start migration" : "Fillo migrimin", + "Two-factor Authentication" : "Mirëfilltësim Dyfaktorësh", + "This section requires a two-factor authentication app to be installed in ownCloud" : "Kjo ndarje lyp të instaluar në ownCloud një aplikacion mirëfilltësimi dyfaktorësh", + "Enforce two-factor authentication" : "Zbato me detyrim mirëfilltësim dyfaktorësh", + "Before enforcing the two-factor authentication, check the following requirements:" : "Para zbatimit me detyrim të mirëfilltësimit dyfaktorësh, kontrollo për domosdoshmëritë vijuese:", + "At least one two-factor authentication app is installed and enabled in ownCloud." : "Në ownCloud të jetë instaluar dhe aktivizuar të paktën një aplikacion mirëfilltësimi dyfaktorësh.", + "The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this" : "Përdoruesi mundet të ujdisë të paktën një aplikacion mirëfilltësimi dyfaktorësh që nga faqja e kërkesë. Disa aplikacione mund të mos jenë përgatitur për këtë", + "The \"twofactor_totp\" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps" : "Aplikacion “twofactor_totp” plotëson këto domosdoshmëri dhe mund të përdoret si rrugëdalje, që kështu përdoruesit të hyjnë në llogaritë e tyre për të formësuar aplikacione të tjera mirëfilltësimi dyfaktorësh", + "Enforce two-factor authentication to all the users" : "Zbato me detyrim mirëfilltësim dyfaktorësh për krejt përdoruesit", + "Exclude the following groups from enforcing two-factor authentication" : "Përjashto nga zbatimi i detyruar i mirëfilltësimit dyfaktorësh grupet vijuese", + "Note: Users in these groups can use two-factor authentication on their own" : "Shënim: Përdoruesit në këto grupe mund të përdorin mirëfilltësim të tyrin dyfaktorësh", "Sharing" : "Ndarje me të tjerët", "Allow apps to use the Share API" : "Lejoni aplikacionet të përdorin API Share", "Allow users to share via link" : "Lejoji përdoruesit të ndajnë me të tjerët përmes lidhjesh", @@ -266,6 +277,7 @@ "SMTP Username" : "Emër përdoruesi SMTP", "SMTP Password" : "Fjalëkalim SMTP", "Store credentials" : "Depozitoji kredencialet", + "Test receiver email" : "Provoni email marrësi", "Test email settings" : "Testoni rregullimet e email-it", "Send email" : "Dërgo email", "Manual File Locking" : "Kyçje Dorazi Kartelash", diff --git a/settings/l10n/sr.js b/settings/l10n/sr.js index cccbe91d456f..bb63ac17d072 100644 --- a/settings/l10n/sr.js +++ b/settings/l10n/sr.js @@ -17,7 +17,6 @@ OC.L10N.register( "Email sent" : "Порука је послата", "You need to set your user email before being able to send test emails." : "Морате поставити адресу е-поште пре слања тестне поруке.", "Your %s account was created" : "Ваш %s налог је направљен", - "Invalid mail address" : "Неисправна е-адреса", "A user with that name already exists." : "Корисник са тим именом већ постоји.", "Unable to create user." : "Не могу да направим корисника.", "Unable to delete user." : "Не могу да обришем корисника.", @@ -27,6 +26,7 @@ OC.L10N.register( "Unable to change display name" : "Не могу да променим име за приказ", "Your full name has been changed." : "Ваше пуно име је промењено.", "Unable to change full name" : "Не могу да променим пуно име", + "Invalid mail address" : "Неисправна е-адреса", "Create" : "Направи", "Delete" : "Обриши", "Share" : "Дељење", diff --git a/settings/l10n/sr.json b/settings/l10n/sr.json index dad27e14cb57..19be4a4fcc96 100644 --- a/settings/l10n/sr.json +++ b/settings/l10n/sr.json @@ -15,7 +15,6 @@ "Email sent" : "Порука је послата", "You need to set your user email before being able to send test emails." : "Морате поставити адресу е-поште пре слања тестне поруке.", "Your %s account was created" : "Ваш %s налог је направљен", - "Invalid mail address" : "Неисправна е-адреса", "A user with that name already exists." : "Корисник са тим именом већ постоји.", "Unable to create user." : "Не могу да направим корисника.", "Unable to delete user." : "Не могу да обришем корисника.", @@ -25,6 +24,7 @@ "Unable to change display name" : "Не могу да променим име за приказ", "Your full name has been changed." : "Ваше пуно име је промењено.", "Unable to change full name" : "Не могу да променим пуно име", + "Invalid mail address" : "Неисправна е-адреса", "Create" : "Направи", "Delete" : "Обриши", "Share" : "Дељење", diff --git a/settings/l10n/sv.js b/settings/l10n/sv.js index c19ae4b5ec09..9adca8921917 100644 --- a/settings/l10n/sv.js +++ b/settings/l10n/sv.js @@ -19,7 +19,6 @@ OC.L10N.register( "Email sent" : "E-post skickad", "You need to set your user email before being able to send test emails." : "Du behöver ställa in din användares e-postadress före du kan skicka test e-post.", "Your %s account was created" : "Ditt %s konto skapades", - "Invalid mail address" : "Ogiltig e-postadress", "A user with that name already exists." : "En användare med det namnet existerar redan.", "Unable to create user." : "Kan inte skapa användare.", "Unable to delete user." : "Kan inte radera användare.", @@ -32,6 +31,7 @@ OC.L10N.register( "%s email address confirm" : "%s e-postadress att bekräfta", "%s email address changed successfully" : "%s e-postadress ändrades", "Unable to enable/disable user." : "Kunde inte aktivera/avaktivera användaren.", + "Invalid mail address" : "Ogiltig e-postadress", "Create" : "Skapa", "Delete" : "Radera", "Share" : "Dela", diff --git a/settings/l10n/sv.json b/settings/l10n/sv.json index 0edf1a9eac76..ebfa7d9f3b99 100644 --- a/settings/l10n/sv.json +++ b/settings/l10n/sv.json @@ -17,7 +17,6 @@ "Email sent" : "E-post skickad", "You need to set your user email before being able to send test emails." : "Du behöver ställa in din användares e-postadress före du kan skicka test e-post.", "Your %s account was created" : "Ditt %s konto skapades", - "Invalid mail address" : "Ogiltig e-postadress", "A user with that name already exists." : "En användare med det namnet existerar redan.", "Unable to create user." : "Kan inte skapa användare.", "Unable to delete user." : "Kan inte radera användare.", @@ -30,6 +29,7 @@ "%s email address confirm" : "%s e-postadress att bekräfta", "%s email address changed successfully" : "%s e-postadress ändrades", "Unable to enable/disable user." : "Kunde inte aktivera/avaktivera användaren.", + "Invalid mail address" : "Ogiltig e-postadress", "Create" : "Skapa", "Delete" : "Radera", "Share" : "Dela", diff --git a/settings/l10n/th_TH.js b/settings/l10n/th_TH.js index db6e19d88225..e7648bbceae5 100644 --- a/settings/l10n/th_TH.js +++ b/settings/l10n/th_TH.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "ไม่สามารถเปลี่ยนที่อยู่อีเมลได้เนื่องจากไม่มีผู้ใช้นี้อยู่", "Couldn't change the email address because the token is invalid" : "ไม่สามารถเปลี่ยนที่อยู่อีเมลเนื่องจากโทเค็นไม่ถูกต้อง", "Your %s account was created" : "บัญชี %s ของคุณถูกสร้างขึ้น", - "Invalid mail address" : "ที่อยู่อีเมลไม่ถูกต้อง", "A user with that name already exists." : "มีชื้อผู้ใช้นี้อยู่แล้ว", "Unable to create user." : "ไม่สามารถสร้างผู้ใช้", "The token provided is invalid." : "ระบุโทเค็นไม่ถูกต้อง", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "เปลี่ยนที่อยู่อีเมล %s เรียบร้อยแล้ว", "Couldn't send email address change notification mail. Please contact your administrator." : "ไม่สามารถส่งอีเมลแจ้งเตือนการเปลี่ยนแปลงที่อยู่อีเมล โปรดติดต่อผู้ดูแลระบบของคุณ", "Unable to enable/disable user." : "ไม่สามารถ เปิด/ปิด การใช้งานผู้ใช้", + "Invalid mail address" : "ที่อยู่อีเมลไม่ถูกต้อง", "Owner language" : "เจ้าของภาษา", "Create" : "สร้าง", "Change" : "เปลี่ยนแปลง", diff --git a/settings/l10n/th_TH.json b/settings/l10n/th_TH.json index 9c070bf7de62..83059d5f2551 100644 --- a/settings/l10n/th_TH.json +++ b/settings/l10n/th_TH.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "ไม่สามารถเปลี่ยนที่อยู่อีเมลได้เนื่องจากไม่มีผู้ใช้นี้อยู่", "Couldn't change the email address because the token is invalid" : "ไม่สามารถเปลี่ยนที่อยู่อีเมลเนื่องจากโทเค็นไม่ถูกต้อง", "Your %s account was created" : "บัญชี %s ของคุณถูกสร้างขึ้น", - "Invalid mail address" : "ที่อยู่อีเมลไม่ถูกต้อง", "A user with that name already exists." : "มีชื้อผู้ใช้นี้อยู่แล้ว", "Unable to create user." : "ไม่สามารถสร้างผู้ใช้", "The token provided is invalid." : "ระบุโทเค็นไม่ถูกต้อง", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "เปลี่ยนที่อยู่อีเมล %s เรียบร้อยแล้ว", "Couldn't send email address change notification mail. Please contact your administrator." : "ไม่สามารถส่งอีเมลแจ้งเตือนการเปลี่ยนแปลงที่อยู่อีเมล โปรดติดต่อผู้ดูแลระบบของคุณ", "Unable to enable/disable user." : "ไม่สามารถ เปิด/ปิด การใช้งานผู้ใช้", + "Invalid mail address" : "ที่อยู่อีเมลไม่ถูกต้อง", "Owner language" : "เจ้าของภาษา", "Create" : "สร้าง", "Change" : "เปลี่ยนแปลง", diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js index e2ea3704e50a..8efd9f317b2c 100644 --- a/settings/l10n/tr.js +++ b/settings/l10n/tr.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "Kullanıcı olmadığı için e-posta adresi değiştirilemedi", "Couldn't change the email address because the token is invalid" : "Belirteç geçersiz olduğundan e-posta adresi değiştirilemedi", "Your %s account was created" : "%s hesabınız oluşturuldu", - "Invalid mail address" : "Geçersiz posta adresi", "A user with that name already exists." : "Bu isimde bir kullanıcı adı zaten mevcut.", "Unable to create user." : "Kullanıcı oluşturma başarısız.", "The token provided is invalid." : "Sağlanan belirteç geçersiz.", @@ -53,6 +52,8 @@ OC.L10N.register( "%s email address changed successfully" : "%s e-posta adresi başarıyla değiştirildi", "Couldn't send email address change notification mail. Please contact your administrator." : "E-posta adresi değişikliği bildirim e-postası gönderilemedi. Lütfen yöneticinize başvurun.", "Unable to enable/disable user." : "Kullanıcıyı etkinleştirme/devre dışı bırakma başarısız.", + "Data too long" : "Veri çok uzun", + "Invalid mail address" : "Geçersiz posta adresi", "Owner language" : "Sahip dili", "Create" : "Oluştur", "Change" : "Değiştir", diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json index d41201dab5ed..3342396a2a7f 100644 --- a/settings/l10n/tr.json +++ b/settings/l10n/tr.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "Kullanıcı olmadığı için e-posta adresi değiştirilemedi", "Couldn't change the email address because the token is invalid" : "Belirteç geçersiz olduğundan e-posta adresi değiştirilemedi", "Your %s account was created" : "%s hesabınız oluşturuldu", - "Invalid mail address" : "Geçersiz posta adresi", "A user with that name already exists." : "Bu isimde bir kullanıcı adı zaten mevcut.", "Unable to create user." : "Kullanıcı oluşturma başarısız.", "The token provided is invalid." : "Sağlanan belirteç geçersiz.", @@ -51,6 +50,8 @@ "%s email address changed successfully" : "%s e-posta adresi başarıyla değiştirildi", "Couldn't send email address change notification mail. Please contact your administrator." : "E-posta adresi değişikliği bildirim e-postası gönderilemedi. Lütfen yöneticinize başvurun.", "Unable to enable/disable user." : "Kullanıcıyı etkinleştirme/devre dışı bırakma başarısız.", + "Data too long" : "Veri çok uzun", + "Invalid mail address" : "Geçersiz posta adresi", "Owner language" : "Sahip dili", "Create" : "Oluştur", "Change" : "Değiştir", diff --git a/settings/l10n/uk.js b/settings/l10n/uk.js index bdb355152547..d3dadd470646 100644 --- a/settings/l10n/uk.js +++ b/settings/l10n/uk.js @@ -22,7 +22,6 @@ OC.L10N.register( "Email sent" : "Лист надіслано", "You need to set your user email before being able to send test emails." : "Перед надсиланням тестових листів ви повинні вказати свою email адресу.", "Your %s account was created" : "Ваш %s аккаунт створений", - "Invalid mail address" : "Неправильна email адреса", "A user with that name already exists." : "Користувач з таким іменем вже існує.", "Unable to create user." : "Неможливо створити користувача.", "Unable to delete user." : "Неможливо видалити користувача.", @@ -32,6 +31,7 @@ OC.L10N.register( "Unable to change display name" : "Не вдалося змінити ім'я", "Your full name has been changed." : "Ваше повне ім'я було змінено", "Unable to change full name" : "Неможливо змінити повне ім'я", + "Invalid mail address" : "Неправильна email адреса", "Owner language" : "Мова власника", "Create" : "Створити", "Change" : "Змінити", diff --git a/settings/l10n/uk.json b/settings/l10n/uk.json index eaad63ae4483..aec0955e3080 100644 --- a/settings/l10n/uk.json +++ b/settings/l10n/uk.json @@ -20,7 +20,6 @@ "Email sent" : "Лист надіслано", "You need to set your user email before being able to send test emails." : "Перед надсиланням тестових листів ви повинні вказати свою email адресу.", "Your %s account was created" : "Ваш %s аккаунт створений", - "Invalid mail address" : "Неправильна email адреса", "A user with that name already exists." : "Користувач з таким іменем вже існує.", "Unable to create user." : "Неможливо створити користувача.", "Unable to delete user." : "Неможливо видалити користувача.", @@ -30,6 +29,7 @@ "Unable to change display name" : "Не вдалося змінити ім'я", "Your full name has been changed." : "Ваше повне ім'я було змінено", "Unable to change full name" : "Неможливо змінити повне ім'я", + "Invalid mail address" : "Неправильна email адреса", "Owner language" : "Мова власника", "Create" : "Створити", "Change" : "Змінити", diff --git a/settings/l10n/zh_CN.js b/settings/l10n/zh_CN.js index 8f78d62a968f..438f676c8fc4 100644 --- a/settings/l10n/zh_CN.js +++ b/settings/l10n/zh_CN.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "由于用户不存在,无法更改电子邮件地址", "Couldn't change the email address because the token is invalid" : "无法更改电子邮件地址,因为该令牌无效", "Your %s account was created" : "你的帐户 %s 已创建", - "Invalid mail address" : "无效的电子邮件地址", "A user with that name already exists." : "使用该名称的用户已存在。", "Unable to create user." : "无法创建用户。", "The token provided is invalid." : "无效的令牌", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s 电子邮件地址更改成功。", "Couldn't send email address change notification mail. Please contact your administrator." : "无法发送电子邮件地址更改通知邮件。请与管理员联系。", "Unable to enable/disable user." : "无法启用/禁用用户。", + "Invalid mail address" : "无效的电子邮件地址", "Owner language" : "拥有者语言", "Create" : "创建", "Change" : "更改", diff --git a/settings/l10n/zh_CN.json b/settings/l10n/zh_CN.json index 274a3715d59b..f0c5501d4b2b 100644 --- a/settings/l10n/zh_CN.json +++ b/settings/l10n/zh_CN.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "由于用户不存在,无法更改电子邮件地址", "Couldn't change the email address because the token is invalid" : "无法更改电子邮件地址,因为该令牌无效", "Your %s account was created" : "你的帐户 %s 已创建", - "Invalid mail address" : "无效的电子邮件地址", "A user with that name already exists." : "使用该名称的用户已存在。", "Unable to create user." : "无法创建用户。", "The token provided is invalid." : "无效的令牌", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s 电子邮件地址更改成功。", "Couldn't send email address change notification mail. Please contact your administrator." : "无法发送电子邮件地址更改通知邮件。请与管理员联系。", "Unable to enable/disable user." : "无法启用/禁用用户。", + "Invalid mail address" : "无效的电子邮件地址", "Owner language" : "拥有者语言", "Create" : "创建", "Change" : "更改", diff --git a/settings/l10n/zh_TW.js b/settings/l10n/zh_TW.js index f3dabc75debb..90743d34042f 100644 --- a/settings/l10n/zh_TW.js +++ b/settings/l10n/zh_TW.js @@ -28,7 +28,6 @@ OC.L10N.register( "Couldn't change the email address because the user does not exist" : "無法變更電子郵件位址因為使用者不存在", "Couldn't change the email address because the token is invalid" : "無法變更電子郵件位址因為認證標記失效", "Your %s account was created" : "您的 %s 帳號已經建立", - "Invalid mail address" : "無效的 email 地址", "A user with that name already exists." : "同名的使用者已經存在", "Unable to create user." : "無法建立使用者", "The token provided is invalid." : "提供的令牌無效的。", @@ -53,6 +52,7 @@ OC.L10N.register( "%s email address changed successfully" : "%s電子郵件位址已經被成功變更", "Couldn't send email address change notification mail. Please contact your administrator." : "無法發送電子電子郵件位址更改通知郵件。 請與您的管理員聯繫。", "Unable to enable/disable user." : "無法啟用/停用使用者。", + "Invalid mail address" : "無效的 email 地址", "Owner language" : "所有者語言", "Create" : "建立", "Change" : "更改", diff --git a/settings/l10n/zh_TW.json b/settings/l10n/zh_TW.json index db960c18e255..e3f79c356a0a 100644 --- a/settings/l10n/zh_TW.json +++ b/settings/l10n/zh_TW.json @@ -26,7 +26,6 @@ "Couldn't change the email address because the user does not exist" : "無法變更電子郵件位址因為使用者不存在", "Couldn't change the email address because the token is invalid" : "無法變更電子郵件位址因為認證標記失效", "Your %s account was created" : "您的 %s 帳號已經建立", - "Invalid mail address" : "無效的 email 地址", "A user with that name already exists." : "同名的使用者已經存在", "Unable to create user." : "無法建立使用者", "The token provided is invalid." : "提供的令牌無效的。", @@ -51,6 +50,7 @@ "%s email address changed successfully" : "%s電子郵件位址已經被成功變更", "Couldn't send email address change notification mail. Please contact your administrator." : "無法發送電子電子郵件位址更改通知郵件。 請與您的管理員聯繫。", "Unable to enable/disable user." : "無法啟用/停用使用者。", + "Invalid mail address" : "無效的 email 地址", "Owner language" : "所有者語言", "Create" : "建立", "Change" : "更改", diff --git a/settings/templates/panels/admin/enforce2fa.php b/settings/templates/panels/admin/enforce2fa.php new file mode 100644 index 000000000000..7d71f96a6dda --- /dev/null +++ b/settings/templates/panels/admin/enforce2fa.php @@ -0,0 +1,33 @@ + +
+

t('Two-factor Authentication'));?>

+

+ t('This section requires a two-factor authentication app to be installed in ownCloud')); ?> +

+

t('Enforce two-factor authentication')); ?>

+

t('Before enforcing the two-factor authentication, check the following requirements:')); ?>

+
    +
  • t('At least one two-factor authentication app is installed and enabled in ownCloud.')); ?>
  • +
  • t('The users can setup at least one two-factor app from the challenge page. Some apps might not be prepared for this')); ?>
  • +
+

t('The "twofactor_totp" app fulfills those requirements, and might be used as a fallback so the users can enter their accounts in order to configure other two-factor authentication apps')); ?>

+
+

+ /> + +

+
+

+ t('Exclude the following groups from enforcing two-factor authentication')); ?> +
+ + +
+ t('Note: Users in these groups can use two-factor authentication on their own')); ?> +
+

+
diff --git a/sonar-project.properties b/sonar-project.properties index 2cae88ff0c49..90d5e6750db1 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ # Organization and project keys are displayed in the right sidebar of the project homepage sonar.organization=owncloud-1 sonar.projectKey=owncloud_core -sonar.projectVersion=10.12.1 +sonar.projectVersion=10.13.0 sonar.host.url=https://sonarcloud.io # ===================================================== diff --git a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php index 061e2a932710..5adf8a4ccbe1 100644 --- a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php +++ b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php @@ -26,6 +26,7 @@ use OC\Files\View; use OCP\IConfig; use OCP\IUserManager; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -71,7 +72,9 @@ public function setUp(): void { $this->outputInterface = $this->createMock('Symfony\Component\Console\Output\OutputInterface'); $this->userInterface = $this->createMock('\OCP\UserInterface'); - $outputFormatterInterface = $this->createMock('Symfony\Component\Console\Formatter\OutputFormatterInterface'); + $outputFormatterInterface = $this->createMock(OutputFormatterInterface::class); + $outputFormatterInterface->expects($this->any())->method('isDecorated') + ->willReturn(false); $this->outputInterface->expects($this->any())->method('getFormatter') ->willReturn($outputFormatterInterface); diff --git a/tests/Core/Command/User/ReportTest.php b/tests/Core/Command/User/ReportTest.php index 51bfc8785bd1..184ea1f68be1 100644 --- a/tests/Core/Command/User/ReportTest.php +++ b/tests/Core/Command/User/ReportTest.php @@ -23,11 +23,9 @@ namespace Tests\Core\Command\User; use OC\Core\Command\User\Report; -use OC\Files\View; use OC\Helper\UserTypeHelper; use OCP\IUserManager; -use OCP\User\Constants; -use Symfony\Component\Console\Application; +use OCP\IUser; use Symfony\Component\Console\Tester\CommandTester; use Test\TestCase; @@ -43,101 +41,158 @@ class ReportTest extends TestCase { /** @var IUserManager */ private $userManager; + /** @var UserTypeHelper */ + private $userTypeHelper; + + private $isObjectStorage = false; + protected function setUp(): void { parent::setUp(); - $userTypeHelper = new UserTypeHelper(); + $this->userManager = $this->createMock(IUserManager::class); + $this->userTypeHelper = $this->createMock(UserTypeHelper::class); - $userManager = \OC::$server->getUserManager(); - $this->userManager = $userManager; - - $command = new Report($userManager, $userTypeHelper); - $command->setApplication(new Application()); + $command = new Report($this->userManager, $this->userTypeHelper); $this->commandTester = new CommandTester($command); - - $view = new View(''); - list($storage) = $view->resolvePath(''); - /** @var $storage Storage */ - - /** - * Create some folders in the 'datadirectory' - * which should not be counted as user directories - */ - foreach (Constants::DIRECTORIES_THAT_ARE_NOT_USERS as $nonUserFolder) { - $storage->mkdir($nonUserFolder); - } - - // Login to create user directory - $this->loginAsUser('admin'); } protected function tearDown(): void { parent::tearDown(); - $this->restoreService('AllConfig'); - $this->restoreService('AppManager'); + if ($this->isObjectStorage) { + $this->restoreService('AllConfig'); + $this->restoreService('AppManager'); + $this->isObjectStorage = false; + } } - public function objectStorageProvider() { - return [ - [true], - [false], + private function getAllUsers() { + $uids = [ + 'user001' => ['home' => '/tmp'], + 'user002' => ['home' => '/tmp'], + 'user003' => ['home' => '/tmp'], + 'user004' => ['home' => '/tmp'], + 'user005' => ['home' => '/tmp'], + 'user006' => ['home' => '/tmp'], ]; - } - /** - * @param bool $objectStorageUsed - * @dataProvider objectStorageProvider - * @return void - */ - public function testCommandInput($objectStorageUsed) { - if ($objectStorageUsed) { - $this->overwriteConfigWithObjectStorage(); - $this->overwriteAppManagerWithObjectStorage(); + $users = []; + foreach ($uids as $uid => $data) { + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn($uid); + if ($this->isObjectStorage) { + $user->method('getHome')->willReturn('/some/missing/home/dir'); + } else { + // there is a "is_dir" check, so the directory must exists in the FS + // we'll use the "/tmp" directory + $user->method('getHome')->willReturn($data['home']); + } + $users[] = $user; } + return $users; + } + + public function testCommandInputObjectStorage() { + $this->prepareForObjectStorage(); + + $this->userTypeHelper->method('isGuestUser') + ->will($this->returnValueMap([ + ['user001', false], + ['user002', false], + ['user003', false], + ['user004', false], + ['user005', true], + ['user006', true], + ])); + + $this->userManager->method('countUsers')->willReturn([ + 'OC\User\Database' => 2, + 'Custom\Class' => 4, + ]); + $this->userManager->method('callForSeenUsers') + ->will($this->returnCallback(function ($seenUserCallbck) { + $allUsers = $this->getAllUsers(); + foreach ($allUsers as $user) { + $seenUserCallbck($user); + } + })); + $this->userManager->method('callForAllUsers') + ->will($this->returnCallback(function ($allUserCallback) { + $allUsers = $this->getAllUsers(); + foreach ($allUsers as $user) { + $allUserCallback($user); + } + })); $this->commandTester->execute([]); $output = $this->commandTester->getDisplay(); - $view = new View(''); - $storage = $view->getMount('/')->getStorage(); - $isLocalStorage = $storage->isLocal(); - - if ($isLocalStorage) { - $expectedOutput = <<assertStringContainsString('We detected that the instance is running on a S3 primary object storage, user directories count might not be accurate', $output); + $this->assertStringContainsString($expectedOutput, $output); + } + + public function testCommandInput() { + $this->userTypeHelper->method('isGuestUser') + ->will($this->returnValueMap([ + ['user001', false], + ['user002', false], + ['user003', false], + ['user004', false], + ['user005', true], + ['user006', true], + ])); + + $this->userManager->method('countUsers')->willReturn([ + 'OC\User\Database' => 2, + 'Custom\Class' => 4, + ]); + $this->userManager->method('callForSeenUsers') + ->will($this->returnCallback(function ($seenUserCallbck) { + $allUsers = $this->getAllUsers(); + foreach ($allUsers as $user) { + $seenUserCallbck($user); + } + })); + $this->userManager->method('callForAllUsers') + ->will($this->returnCallback(function ($allUserCallback) { + $allUsers = $this->getAllUsers(); + foreach ($allUsers as $user) { + $allUserCallback($user); + } + })); + + $this->commandTester->execute([]); + $output = $this->commandTester->getDisplay(); + + $expectedOutput = <<assertStringContainsString($expectedOutput, $output); - - if ($objectStorageUsed) { - $this->assertStringContainsString('We detected that the instance is running on a S3 primary object storage, user directories count might not be accurate', $output); - } } private function overwriteConfigWithObjectStorage() { @@ -157,4 +212,10 @@ private function overwriteAppManagerWithObjectStorage() { $this->overwriteService('AppManager', $config); } + + private function prepareForObjectStorage() { + $this->overwriteConfigWithObjectStorage(); + $this->overwriteAppManagerWithObjectStorage(); + $this->isObjectStorage = true; + } } diff --git a/tests/Core/Command/User/SettingTest.php b/tests/Core/Command/User/SettingTest.php index ad4c872a6580..e24ccdd1b32e 100644 --- a/tests/Core/Command/User/SettingTest.php +++ b/tests/Core/Command/User/SettingTest.php @@ -86,7 +86,7 @@ public function dataCheckInput() { [['ignore-missing-user', false]], [], null, - 'The user "username" does not exists.', + 'The user "username" does not exist.', ], [ diff --git a/tests/Core/Controller/RolesControllerTest.php b/tests/Core/Controller/RolesControllerTest.php index afea0309e6ce..962cb68ebf1f 100644 --- a/tests/Core/Controller/RolesControllerTest.php +++ b/tests/Core/Controller/RolesControllerTest.php @@ -47,6 +47,7 @@ public function testGetAvatarNoAvatar() { 'id' => 'test.tester', 'displayName' => 'A tester which tests ....' ]); + return $event; }); $result = $controller->getRoles(); diff --git a/tests/Settings/Controller/UsersControllerTest.php b/tests/Settings/Controller/UsersControllerTest.php index 6f6fe197c882..dab39e4f45a4 100644 --- a/tests/Settings/Controller/UsersControllerTest.php +++ b/tests/Settings/Controller/UsersControllerTest.php @@ -42,6 +42,7 @@ use OC\Group\Manager; use Symfony\Component\EventDispatcher\EventDispatcher; use Test\TestCase; +use Test\Traits\UserTrait; use function vsprintf; use OCP\IAvatar; use OC\Group\Group; @@ -52,6 +53,8 @@ * @package Tests\Settings\Controller */ class UsersControllerTest extends TestCase { + use UserTrait; + /** @var IAppContainer */ private $container; @@ -1995,7 +1998,7 @@ public function dataforemailaddress(): array { * @throws Exception */ public function testSetSelfEmailAddress($userName, $userPassword, $loginUser, $setUser, $emailAddress): void { - OC::$server->getUserManager()->createUser($userName, $userPassword); + $this->createUser($userName, $userPassword); $appName = "settings"; $irequest = $this->createMock(IRequest::class); @@ -2035,6 +2038,8 @@ public function testSetSelfEmailAddress($userName, $userPassword, $loginUser, $s $eventDispatcher ); + $iMailer->method('validateMailAddress')->willReturn(true); + self::loginAsUser($loginUser); $iUser = $this->createMock(IUser::class); diff --git a/tests/Settings/Panels/Admin/Enforce2faTest.php b/tests/Settings/Panels/Admin/Enforce2faTest.php new file mode 100644 index 000000000000..a469c22369ef --- /dev/null +++ b/tests/Settings/Panels/Admin/Enforce2faTest.php @@ -0,0 +1,61 @@ + + * + */ + +namespace Tests\Settings\Panels\Admin; + +use OC\Settings\Panels\Admin\Enforce2fa; +use OCP\IConfig; + +/** + * @package Tests\Settings\Panels\Admin + */ +class Enforce2faTest extends \Test\TestCase { + /** @var IConfig */ + private $config; + /** @var Enforce2fa */ + private $panel; + + protected function setUp(): void { + parent::setUp(); + $this->config = $this->createMock(IConfig::class); + + $this->panel = new Enforce2fa($this->config); + } + + public function testGetSection() { + $this->assertSame('security', $this->panel->getSectionID()); + } + + public function testGetPriority() { + $this->assertSame(50, $this->panel->getPriority()); + } + + public function testGetPanel() { + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '["group1", "group2"]'], + ])); + + $tmplHtml = $this->panel->getPanel()->fetchPage(); + $this->assertMatchesRegularExpression('/assertMatchesRegularExpression('/ */ -class AppConfigHelper extends \PHPUnit\Framework\Assert { +class AppConfigHelper extends Assert { /** * @param string|null $baseUrl * @param string|null $user @@ -41,12 +44,12 @@ class AppConfigHelper extends \PHPUnit\Framework\Assert { * @param string|null $testingParameter the parameter name as understood by * "testing" * @param boolean $testingState the on|off state the parameter must be set to for the test - * @param string|null $savedCapabilitiesXml the original capabilities in XML format + * @param SimpleXMLElement $savedCapabilitiesXml the original capabilities in XML format * @param string|null $xRequestId * @param int|null $ocsApiVersion (1|2) * * @return array of the original state of the capability set - * @throws Exception + * @throws GuzzleException */ public static function setCapability( ?string $baseUrl, @@ -56,10 +59,10 @@ public static function setCapability( ?string $capabilitiesParameter, ?string $testingApp, ?string $testingParameter, - ?bool $testingState, - $savedCapabilitiesXml, + ?bool $testingState, + SimpleXMLElement $savedCapabilitiesXml, ?string $xRequestId = '', - ?int $ocsApiVersion = 1 + ?int $ocsApiVersion = 1 ):array { $originalState = self::wasCapabilitySet( $capabilitiesApp, @@ -153,8 +156,8 @@ public static function setCapabilities( * @return string */ public static function getParameterValueFromXml( - $xml, - $capabilitiesApp, + ?SimpleXMLElement $xml, + ?string $capabilitiesApp, ?string $capabilitiesPath ):string { $pathToElement = \explode('@@@', $capabilitiesPath); @@ -178,7 +181,7 @@ public static function getParameterValueFromXml( public static function wasCapabilitySet( ?string $capabilitiesApp, ?string $capabilitiesParameter, - $savedCapabilitiesXml + ?SimpleXMLElement $savedCapabilitiesXml ):bool { return (bool) self::getParameterValueFromXml( $savedCapabilitiesXml, @@ -209,6 +212,7 @@ public static function getOCSResponse(?ResponseInterface $response):\SimpleXMLEl * @param string|null $xRequestId * * @return ResponseInterface + * @throws GuzzleException */ public static function getCapabilities( ?string $baseUrl, @@ -258,7 +262,7 @@ public static function getCapabilitiesXml(?ResponseInterface $response):\SimpleX * @param int|null $ocsApiVersion (1|2) * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function modifyAppConfig( ?string $baseUrl, @@ -276,7 +280,7 @@ public static function modifyAppConfig( $user, $password, 'post', - "/apps/testing/api/v1/app/{$app}/{$parameter}", + "/apps/testing/api/v1/app/$app/$parameter", $xRequestId, $body, $ocsApiVersion @@ -310,7 +314,7 @@ public static function modifyAppConfig( * @param int|null $ocsApiVersion (1|2) * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function modifyAppConfigs( ?string $baseUrl, @@ -323,7 +327,7 @@ public static function modifyAppConfigs( if (\is_array($appParameterValues)) { foreach ($appParameterValues as $key => $value) { if (isset($value['value']) && \is_array($value['value'])) { - $appParameterValues[$key]['value'] = \implode("", $appParameterValues[$key]['value']); + $appParameterValues[$key]['value'] = \implode("", $value['value']); } } } @@ -368,7 +372,7 @@ public static function modifyAppConfigs( * @param int|null $ocsApiVersion (1|2) * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function deleteAppConfig( ?string $baseUrl, @@ -385,7 +389,7 @@ public static function deleteAppConfig( $user, $password, 'delete', - "/apps/testing/api/v1/app/{$app}/{$parameter}", + "/apps/testing/api/v1/app/$app/$parameter", $xRequestId, $body, $ocsApiVersion @@ -419,7 +423,7 @@ public static function deleteAppConfig( * @param int|null $ocsApiVersion (1|2) * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function deleteAppConfigs( ?string $baseUrl, @@ -469,7 +473,7 @@ public static function deleteAppConfigs( * @param int|null $ocsApiVersion (1|2) * * @return array with 'configkey', 'value' and 'appid' - * @throws Exception + * @throws Exception|GuzzleException */ public static function getAppConfigs( ?string $baseUrl, @@ -484,7 +488,7 @@ public static function getAppConfigs( $user, $password, 'get', - "/apps/testing/api/v1/app/{$app}", + "/apps/testing/api/v1/app/$app", $xRequestId, null, $ocsApiVersion @@ -509,8 +513,7 @@ public static function getAppConfigs( } $responseXml = HttpRequestHelper::getResponseXml($response, __METHOD__)->data[0]; - $response = \json_decode(\json_encode($responseXml), true)['element']; - return $response; + return \json_decode(\json_encode($responseXml), true)['element']; } /** @@ -523,7 +526,7 @@ public static function getAppConfigs( * @param int|null $ocsApiVersion (1|2) * * @return array with 'configkey', 'value' and 'appid' - * @throws Exception + * @throws Exception|GuzzleException */ public static function getAppConfig( ?string $baseUrl, @@ -539,7 +542,7 @@ public static function getAppConfig( $user, $password, 'get', - "/apps/testing/api/v1/app/{$app}/{$parameter}", + "/apps/testing/api/v1/app/$app/$parameter", $xRequestId, null, $ocsApiVersion @@ -564,7 +567,6 @@ public static function getAppConfig( } $responseXml = HttpRequestHelper::getResponseXml($response, __METHOD__)->data[0]; - $response = \json_decode(\json_encode($responseXml), true)['element']; - return $response; + return \json_decode(\json_encode($responseXml), true)['element']; } } diff --git a/tests/TestHelpers/Asserts/WebDav.php b/tests/TestHelpers/Asserts/WebDav.php index 2ca6e14d8d9a..ff3ba5a0a3a8 100644 --- a/tests/TestHelpers/Asserts/WebDav.php +++ b/tests/TestHelpers/Asserts/WebDav.php @@ -22,6 +22,7 @@ namespace TestHelpers\Asserts; use Exception; +use PHPUnit\Framework\Assert; use SimpleXMLElement; use TestHelpers\DownloadHelper; use TestHelpers\SetupHelper; @@ -29,7 +30,7 @@ /** * WebDAV related asserts */ -class WebDav extends \PHPUnit\Framework\Assert { +class WebDav extends Assert { /** * * @param string|null $element exception|message|reason @@ -59,6 +60,8 @@ public static function assertDavResponseElementIs( $result = $responseXml['value'][1]['value']; } elseif ($element === "reason") { $result = $responseXml['value'][3]['value']; + } else { + self::fail(__METHOD__ . " element must be one of exception, response or reason. But '$element' was passed in."); } self::assertEquals( @@ -155,7 +158,7 @@ public static function assertContentOfRemoteAndLocalFileIsSame( * otherwise check that the file contents are different * * @return void - * @throws Exception + * @throws Exception|\GuzzleHttp\Exception\GuzzleException */ public static function assertContentOfDAVFileAndSkeletonFileOnSUT( ?string $baseUrl, diff --git a/tests/TestHelpers/DeleteHelper.php b/tests/TestHelpers/DeleteHelper.php index b55724805854..3d79d7930dd2 100644 --- a/tests/TestHelpers/DeleteHelper.php +++ b/tests/TestHelpers/DeleteHelper.php @@ -21,6 +21,7 @@ */ namespace TestHelpers; +use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Message\ResponseInterface; /** @@ -34,9 +35,9 @@ class DeleteHelper { * * @param string|null $baseUrl URL of owncloud * e.g. http://localhost:8080 - * should include the subfolder - * if owncloud runs in a subfolder - * e.g. http://localhost:8080/owncloud-core + * should include the subfolder + * if owncloud runs in a subfolder + * e.g. http://localhost:8080/owncloud-core * @param string|null $user * @param string|null $password * @param string|null $fileName @@ -47,6 +48,7 @@ class DeleteHelper { * @param Client|null $client * * @return ResponseInterface + * @throws GuzzleException */ public static function delete( ?string $baseUrl, diff --git a/tests/TestHelpers/DownloadHelper.php b/tests/TestHelpers/DownloadHelper.php index 4fbf4700b88c..2fe4685d336c 100644 --- a/tests/TestHelpers/DownloadHelper.php +++ b/tests/TestHelpers/DownloadHelper.php @@ -21,6 +21,7 @@ */ namespace TestHelpers; +use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Message\ResponseInterface; /** @@ -33,10 +34,10 @@ class DownloadHelper { /** * * @param string|null $baseUrl URL of owncloud - * e.g. http://localhost:8080 - * should include the subfolder - * if owncloud runs in a subfolder - * e.g. http://localhost:8080/owncloud-core + * e.g. http://localhost:8080 + * should include the subfolder + * if owncloud runs in a subfolder + * e.g. http://localhost:8080/owncloud-core * @param string|null $user * @param string|null $password * @param string|null $fileName @@ -46,6 +47,7 @@ class DownloadHelper { * @param string|null $sourceIpAddress * * @return ResponseInterface + * @throws GuzzleException */ public static function download( ?string $baseUrl, diff --git a/tests/TestHelpers/EmailHelper.php b/tests/TestHelpers/EmailHelper.php index ffd0c27b3f87..7bff21c27008 100644 --- a/tests/TestHelpers/EmailHelper.php +++ b/tests/TestHelpers/EmailHelper.php @@ -154,7 +154,7 @@ public static function getBodyOfAnEmailById(string $mailBox, string $mailboxId, * @param int|null $waitTimeSec Time to wait for the email if the email has been delivered * * @return boolean - * @throws Exception + * @throws Exception|GuzzleException */ public static function isEmailReceived( string $emailAddress, diff --git a/tests/TestHelpers/HttpRequestHelper.php b/tests/TestHelpers/HttpRequestHelper.php index 84a0037a2771..536bb2ff576f 100644 --- a/tests/TestHelpers/HttpRequestHelper.php +++ b/tests/TestHelpers/HttpRequestHelper.php @@ -44,7 +44,7 @@ class HttpRequestHelper { /** * Some systems-under-test do async post-processing of operations like upload, - * move etc. If a client does a request on the resource before the post-processing + * move, etc. If a client does a request on the resource before the post-processing * is finished, then the server should return HTTP_TOO_EARLY "425". Clients are * expected to retry the request "some time later" (tm). * @@ -101,9 +101,6 @@ public static function sendRequest( $timeout ); } - /** - * @var RequestInterface $request - */ $request = self::createRequest( $url, $xRequestId, @@ -136,7 +133,7 @@ public static function sendRequest( // The exceptions that might happen here include: // ConnectException - in that case there is no response. Don't catch the exception. // RequestException - if there is something in the response then pass it back. - // otherwise re-throw the exception. + // Otherwise re-throw the exception. // GuzzleException - something else unexpected happened. Don't catch the exception. try { $response = $client->send($request); @@ -248,8 +245,7 @@ public static function sendBatchRequest( ?array $requests, ?Client $client ):array { - $results = Pool::batch($client, $requests); - return $results; + return Pool::batch($client, $requests); } /** @@ -287,12 +283,11 @@ public static function createClient( $options['stream'] = $stream; $options['verify'] = false; $options['timeout'] = $timeout; - $client = new Client($options); - return $client; + return new Client($options); } /** - * Create an http request based on given parameters. + * Create an HTTP request based on given parameters. * This creates a RequestInterface object that can be used with a client to send a request. * This enables us to create multiple requests in advance so that we can send them to the server at once in parallel. * @@ -320,7 +315,7 @@ public static function createRequest( $headers['X-Request-ID'] = $xRequestId; } if (\is_array($body)) { - // when creating the client, it is possible to set 'form_params' and + // When creating the client, it is possible to set 'form_params' and // the Client constructor sorts out doing this http_build_query stuff. // But 'new Request' does not have the flexibility to do that. // So we need to do it here. @@ -521,7 +516,7 @@ public static function delete( * @throws Exception */ public static function getResponseXml(ResponseInterface $response, ?string $exceptionText = ''):SimpleXMLElement { - // rewind just to make sure we can re-parse it in case it was parsed already... + // rewind just to make sure we can reparse it in case it was parsed already... $response->getBody()->rewind(); $contents = $response->getBody()->getContents(); try { diff --git a/tests/TestHelpers/IpHelper.php b/tests/TestHelpers/IpHelper.php index 47fb0dc2169b..4ccd2d7a1204 100644 --- a/tests/TestHelpers/IpHelper.php +++ b/tests/TestHelpers/IpHelper.php @@ -25,14 +25,13 @@ use InvalidArgumentException; /** - * Helper to to get run-time IP addresses and make IP calculations + * Helper to get run-time IP addresses and make IP calculations * * @author Phillip Davis * */ class IpHelper { public const IPV6_LOOPBACK_ADDRESS = '::1'; - public const IPV6_LOOPBACK_ADDRESS_SUBNET = '::0'; public const IPV4_LOOPBACK_ADDRESS_TOP = '127.'; public const IPV6_LINK_LOCAL_ADDRESS_TOP = 'fe80'; // The docker bridged device does not work as a routable IP address @@ -217,7 +216,7 @@ private static function loopbackIpv6Address():string { /** * get a loopback address for the given IP address family * - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * * @return string IP loopback address * @throws Exception @@ -239,7 +238,7 @@ private static function loopbackIpAddress(?string $ipAddressFamily):string { * calculate the base address of the subnet with the given CIDR * that contains the loopback address of the given IP address family * - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * * @return string IP of loopback subnet base address * @throws Exception @@ -302,7 +301,7 @@ private static function routableIpv6Address():string { * get a non-loopback address on the local system for the given IP address family * i.e. a "real" routable IP address on some network interface * - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * * @return string IP address * @throws Exception @@ -350,7 +349,7 @@ private static function routableIpv6AddressSubnet(?int $cidr):string { * calculate the base address of the subnet with the given CIDR * that contains the first routable IP address of the given IP address family * - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * @param int|null $cidr the CIDR "mask" size for the subnet * * @return string IP of local subnet base address @@ -375,7 +374,7 @@ private static function routableIpAddressSubnet(?string $ipAddressFamily, ?int $ * * @param string|null $networkScope which type of address to return, * "routable" or "loopback" - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * * @return string IP address * @throws Exception @@ -384,16 +383,13 @@ public static function ipAddress(?string $networkScope, ?string $ipAddressFamily switch (\strtolower($networkScope)) { case 'routable': return self::routableIpAddress($ipAddressFamily); - break; case 'loopback': return self::loopbackIpAddress($ipAddressFamily); - break; default: throw new \InvalidArgumentException( "ipAddress: Invalid networkScope passed. " . "(Must be routable or loopback)" ); - break; } } @@ -403,7 +399,7 @@ public static function ipAddress(?string $networkScope, ?string $ipAddressFamily * * @param string|null $networkScope which type of address to return, * "routable" or "loopback" - * @param string|null $ipAddressFamily IPv4 or IPv6 (not case sensitive) + * @param string|null $ipAddressFamily IPv4 or IPv6 (not case-sensitive) * @param int|null $cidr the CIDR "mask" size for the subnet * * @return string IP of base address @@ -413,16 +409,13 @@ public static function ipAddressSubnet(?string $networkScope, ?string $ipAddress switch (\strtolower($networkScope)) { case 'routable': return self::routableIpAddressSubnet($ipAddressFamily, $cidr); - break; case 'loopback': return self::loopbackIpAddressSubnet($ipAddressFamily); - break; default: throw new \InvalidArgumentException( "ipAddressSubnet: Invalid networkScope passed. " . "(Must be routable or loopback)" ); - break; } } } diff --git a/tests/TestHelpers/LoggingHelper.php b/tests/TestHelpers/LoggingHelper.php index 573648725378..8563661e6713 100644 --- a/tests/TestHelpers/LoggingHelper.php +++ b/tests/TestHelpers/LoggingHelper.php @@ -22,6 +22,7 @@ namespace TestHelpers; use Exception; +use GuzzleHttp\Exception\GuzzleException; use InvalidArgumentException; /** @@ -48,7 +49,7 @@ class LoggingHelper { * @param string|null $xRequestId * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogFilePath( ?string $xRequestId = '' @@ -86,7 +87,7 @@ public static function getLogFilePath( * @param int|null $noOfLinesToRead * * @return array - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogFileContent( ?string $baseUrl, @@ -112,7 +113,7 @@ public static function getLogFileContent( $result = []; foreach ($response->data->element as $line) { - array_push($result, (string)$line); + $result[] = (string) $line; } return $result; } @@ -123,7 +124,7 @@ public static function getLogFileContent( * @param string|null $xRequestId * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogLevel( ?string $xRequestId = '' @@ -150,7 +151,7 @@ public static function getLogLevel( * @param string|null $xRequestId * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function setLogLevel( ?string $logLevel, @@ -177,7 +178,7 @@ public static function setLogLevel( * @param string|null $xRequestId * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogBackend( ?string $xRequestId = '' @@ -209,7 +210,7 @@ public static function getLogBackend( * @param string|null $xRequestId * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function setLogBackend( ?string $backend, @@ -236,7 +237,7 @@ public static function setLogBackend( * @param string|null $xRequestId * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogTimezone( ?string $xRequestId = '' @@ -268,7 +269,7 @@ public static function getLogTimezone( * @param string|null $xRequestId * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function setLogTimezone( ?string $timezone, @@ -294,7 +295,7 @@ public static function setLogTimezone( * @param string|null $xRequestId * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function clearLogFile( ?string $baseUrl, @@ -323,7 +324,7 @@ public static function clearLogFile( * @param string|null $xRequestId * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public static function restoreLoggingStatus( ?string $logLevel, @@ -341,13 +342,13 @@ public static function restoreLoggingStatus( $commands = ["log:manage"]; if ($timezone) { - \array_push($commands, "--timezone=$timezone"); + $commands[] = "--timezone=$timezone"; } if ($logLevel) { - \array_push($commands, "--backend=$backend"); + $commands[] = "--backend=$backend"; } if ($backend) { - \array_push($commands, "--level=$logLevel"); + $commands[] = "--level=$logLevel"; } if (\count($commands) > 1) { @@ -370,7 +371,7 @@ public static function restoreLoggingStatus( * @param string|null $xRequestId * * @return array|string[] - * @throws Exception + * @throws Exception|GuzzleException */ public static function getLogInfo( ?string $xRequestId = '' diff --git a/tests/TestHelpers/MoveCopyHelper.php b/tests/TestHelpers/MoveCopyHelper.php index 9e9ed4098b42..93906025c03c 100644 --- a/tests/TestHelpers/MoveCopyHelper.php +++ b/tests/TestHelpers/MoveCopyHelper.php @@ -21,6 +21,7 @@ */ namespace TestHelpers; +use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Message\ResponseInterface; /** @@ -33,7 +34,7 @@ class MoveCopyHelper { /** * * @param string|null $baseUrl URL of owncloud - * e.g. http://localhost:8080 + * e.g. http://localhost:8080 * should include the subfolder * if owncloud runs in a subfolder * e.g. http://localhost:8080/owncloud-core @@ -47,6 +48,7 @@ class MoveCopyHelper { * @param string|null $sourceIpAddress * * @return ResponseInterface + * @throws GuzzleException */ public static function copy( ?string $baseUrl, @@ -90,6 +92,7 @@ public static function copy( * @param string|null $sourceIpAddress * * @return ResponseInterface + * @throws GuzzleException */ public static function move( ?string $baseUrl, @@ -134,6 +137,7 @@ public static function move( * @param string|null $sourceIpAddress * * @return ResponseInterface + * @throws GuzzleException */ private static function copyOrMove( ?string $baseUrl, diff --git a/tests/TestHelpers/OcsApiHelper.php b/tests/TestHelpers/OcsApiHelper.php index 6e0623f42a2f..27ba2d1d1eb4 100644 --- a/tests/TestHelpers/OcsApiHelper.php +++ b/tests/TestHelpers/OcsApiHelper.php @@ -61,7 +61,7 @@ public static function sendRequest( if (\substr($fullUrl, -1) !== '/') { $fullUrl .= '/'; } - $fullUrl .= "ocs/v{$ocsApiVersion}.php" . $path; + $fullUrl .= "ocs/v$ocsApiVersion.php" . $path; $headers['OCS-APIREQUEST'] = true; return HttpRequestHelper::sendRequest($fullUrl, $xRequestId, $method, $user, $password, $headers, $body); } @@ -91,7 +91,7 @@ public static function createOcsRequest( if (\substr($fullUrl, -1) !== '/') { $fullUrl .= '/'; } - $fullUrl .= "ocs/v{$ocsApiVersion}.php" . $path; + $fullUrl .= "ocs/v$ocsApiVersion.php" . $path; return HttpRequestHelper::createRequest( $fullUrl, $xRequestId, diff --git a/tests/TestHelpers/SetupHelper.php b/tests/TestHelpers/SetupHelper.php index cbe4b957bd6e..89a811b1c078 100644 --- a/tests/TestHelpers/SetupHelper.php +++ b/tests/TestHelpers/SetupHelper.php @@ -25,32 +25,21 @@ use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\ServerException; use Exception; +use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; use SimpleXMLElement; /** - * Helper to setup UI / Integration tests + * Helper to set up UI / Integration tests * * @author Artur Neumann * */ -class SetupHelper extends \PHPUnit\Framework\Assert { - /** - * @var string - */ - private static $ocPath = null; - /** - * @var string - */ - private static $baseUrl = null; - /** - * @var string - */ - private static $adminUsername = null; - /** - * @var string - */ - private static $adminPassword = null; +class SetupHelper extends Assert { + private static ?string $ocPath = null; + private static ?string $baseUrl = null; + private static ?string $adminUsername = null; + private static ?string $adminPassword = null; /** * creates a user @@ -61,8 +50,8 @@ class SetupHelper extends \PHPUnit\Framework\Assert { * @param string|null $displayName * @param string|null $email * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function createUser( ?string $userName, @@ -91,8 +80,8 @@ public static function createUser( * @param string|null $userName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function deleteUser( ?string $userName, @@ -113,7 +102,7 @@ public static function deleteUser( * @param string|null $xRequestId * * @return string[] - * @throws Exception + * @throws Exception|GuzzleException */ public static function changeUserSetting( ?string $userName, @@ -134,8 +123,8 @@ public static function changeUserSetting( * @param string|null $groupName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function createGroup( ?string $groupName, @@ -154,8 +143,8 @@ public static function createGroup( * @param string|null $userName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function addUserToGroup( ?string $groupName, @@ -175,8 +164,8 @@ public static function addUserToGroup( * @param string|null $userName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function removeUserFromGroup( ?string $groupName, @@ -195,8 +184,8 @@ public static function removeUserFromGroup( * @param string|null $groupName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function deleteGroup( ?string $groupName, @@ -213,7 +202,7 @@ public static function deleteGroup( * @param string|null $xRequestId * * @return string[] - * @throws Exception + * @throws Exception|GuzzleException */ public static function getGroups( ?string $xRequestId = '' @@ -301,6 +290,7 @@ public static function getOcPath():?string { * * @return SimpleXMLElement * @throws GuzzleException + * @throws Exception */ public static function getSysInfo( ?string $baseUrl, @@ -503,6 +493,7 @@ public static function rmDirOnServer( * * @return void * @throws GuzzleException + * @throws Exception */ public static function createFileOnServer( ?string $filePathFromServerRoot, @@ -609,13 +600,13 @@ public static function readFileFromServer( $adminUsername, $adminPassword, 'GET', - "/apps/testing/api/v1/file?file={$fileInCore}", + "/apps/testing/api/v1/file?file=$fileInCore", $xRequestId ); self::assertSame( 200, $response->getStatusCode(), - "Failed to read the file {$fileInCore}" + "Failed to read the file $fileInCore" ); $localContent = HttpRequestHelper::getResponseXml($response, __METHOD__); $localContent = (string)$localContent->data->element->contentUrlEncoded; @@ -673,18 +664,17 @@ public static function readSkeletonFile( $adminUsername, $adminPassword, 'GET', - "/apps/testing/api/v1/file?file={$fileInSkeletonFolder}&absolute=true", + "/apps/testing/api/v1/file?file=$fileInSkeletonFolder&absolute=true", $xRequestId ); self::assertSame( 200, $response->getStatusCode(), - "Failed to read the file {$fileInSkeletonFolder}" + "Failed to read the file $fileInSkeletonFolder" ); $localContent = HttpRequestHelper::getResponseXml($response, __METHOD__); $localContent = (string)$localContent->data->element->contentUrlEncoded; - $localContent = \urldecode($localContent); - return $localContent; + return \urldecode($localContent); } /** @@ -693,8 +683,8 @@ public static function readSkeletonFile( * @param string|null $appName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function enableApp( ?string $appName, @@ -712,8 +702,8 @@ public static function enableApp( * @param string|null $appName * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr" - * @throws Exception + * @return string[] an associative array with "code", "stdOut", "stdErr" + * @throws Exception|GuzzleException */ public static function disableApp( ?string $appName, @@ -732,7 +722,7 @@ public static function disableApp( * @param string|null $xRequestId * * @return bool true if enabled, false if disabled or nonexistent - * @throws Exception + * @throws Exception|GuzzleException */ public static function isAppEnabled( ?string $appName, @@ -752,7 +742,7 @@ public static function isAppEnabled( * @param string|null $xRequestId * * @return bool true if the app needed to be enabled, false otherwise - * @throws Exception + * @throws Exception|GuzzleException */ public static function enableAppIfNotEnabled( ?string $appName, @@ -812,7 +802,7 @@ public static function runBulkOcc( if (isset($occ['envVariables'])) { $body['env_variables'] = $occ['envVariables']; } - \array_push($bodies, $body); + $bodies[] = $body; } try { $result = OcsApiHelper::sendRequest( @@ -840,7 +830,7 @@ public static function runBulkOcc( * invokes an OCC command * * @param array|null $args anything behind "occ". - * For example: "files:transfer-ownership" + * For example, "files:transfer-ownership" * @param string|null $xRequestId * @param string|null $adminUsername * @param string|null $adminPassword @@ -848,7 +838,7 @@ public static function runBulkOcc( * @param string|null $ocPath * @param array|null $envVariables * - * @return string[] associated array with "code", "stdOut", "stdErr" + * @return string[] an associative array with "code", "stdOut", "stdErr" * @throws GuzzleException * @throws Exception */ @@ -984,10 +974,10 @@ public static function runOcc( } /** - * @param string $baseUrl - * @param string $user - * @param string $password - * @param string $xRequestId + * @param string|null $baseUrl + * @param string|null $user + * @param string|null $password + * @param string|null $xRequestId * * @return ResponseInterface|null * @throws GuzzleException @@ -1020,7 +1010,7 @@ public static function resetOpcache( * @param string|null $mount (name of local storage mount) * @param string|null $xRequestId * - * @return string[] associated array with "code", "stdOut", "stdErr", "storageId" + * @return string[] an associative array with "code", "stdOut", "stdErr", "storageId" * @throws GuzzleException */ public static function createLocalStorageMount( @@ -1055,7 +1045,7 @@ public static function createLocalStorageMount( if (\array_key_exists(4, $storageIdWords)) { $result['storageId'] = (int)$storageIdWords[4]; } else { - // presumably something went wrong with the files_external:create command + // Presumably something went wrong with the files_external:create command // so return "unknown" to the caller. The result array has the command exit // code and stdErr output etc., so the caller can process what it likes // of that information to work out what went wrong. @@ -1076,7 +1066,7 @@ public static function createLocalStorageMount( * @param string|null $baseUrl * @param string|null $ocPath * - * @return string[] associated array with "code", "stdOut", "stdErr" + * @return string[] an associative array with "code", "stdOut", "stdErr" * @throws GuzzleException */ public static function getSystemConfig( @@ -1122,7 +1112,7 @@ public static function getSystemConfig( * @param string|null $baseUrl * @param string|null $ocPath * - * @return string[] associated array with "code", "stdOut", "stdErr" + * @return string[] an associative array with "code", "stdOut", "stdErr" * @throws GuzzleException */ public static function setSystemConfig( @@ -1231,7 +1221,7 @@ public static function findLines(?string $input, ?string $text):array { * @param string|null $baseUrl * @param string|null $ocPath * - * @return string[] associated array with "code", "stdOut", "stdErr" + * @return string[] an associative array with "code", "stdOut", "stdErr" * @throws GuzzleException if parameters have not been provided yet or the testing app is not enabled */ public static function deleteSystemConfig( diff --git a/tests/TestHelpers/SharingHelper.php b/tests/TestHelpers/SharingHelper.php index a368ce28dbf2..bb0e30af8f85 100644 --- a/tests/TestHelpers/SharingHelper.php +++ b/tests/TestHelpers/SharingHelper.php @@ -22,6 +22,7 @@ namespace TestHelpers; use Exception; +use GuzzleHttp\Exception\GuzzleException; use InvalidArgumentException; use Psr\Http\Message\ResponseInterface; use SimpleXMLElement; @@ -52,7 +53,7 @@ class SharingHelper { 'accepted' => 0, 'pending' => 1, 'rejected' => 2, - 'declined' => 2, // declined is a synonym for rejected + 'declined' => 2, // declined is a synonym for rejected. ]; /** @@ -88,7 +89,7 @@ class SharingHelper { * @param string $sharingApp * * @return ResponseInterface - * @throws InvalidArgumentException + * @throws InvalidArgumentException|GuzzleException */ public static function createShare( string $baseUrl, @@ -136,7 +137,7 @@ public static function createShare( if (\substr($fullUrl, -1) !== '/') { $fullUrl .= '/'; } - $fullUrl .= "ocs/v{$ocsApiVersion}.php/apps/{$sharingApp}/api/v{$sharingApiVersion}/shares"; + $fullUrl .= "ocs/v$ocsApiVersion.php/apps/$sharingApp/api/v$sharingApiVersion/shares"; $fd['path'] = $path; $fd['shareType'] = self::getShareType($shareType); @@ -145,7 +146,7 @@ public static function createShare( $fd['shareWith'] = $shareWith; } if ($publicUpload !== null) { - $fd['publicUpload'] = (bool) $publicUpload; + $fd['publicUpload'] = $publicUpload; } if ($sharePassword !== null) { $fd['password'] = $sharePassword; @@ -169,8 +170,8 @@ public static function createShare( } /** - * calculates the permission sum (int) from given permissions - * permissions can be passed in as int, string or array of int or string + * Calculates the permission sum (int) from the given permissions. + * Permissions can be passed in as int, string or array of int or string * 'read' => 1 * 'update' => 2 * 'create' => 4 @@ -197,7 +198,7 @@ public static function getPermissionSum($permissions):int { if (\array_key_exists($permission, self::PERMISSION_TYPES)) { $permissionSum += self::PERMISSION_TYPES[$permission]; } elseif (\in_array($permission, self::PERMISSION_TYPES, true)) { - $permissionSum += (int) $permission; + $permissionSum += $permission; } else { throw new InvalidArgumentException( "invalid permission type ($permission)" diff --git a/tests/TestHelpers/TagsHelper.php b/tests/TestHelpers/TagsHelper.php index 21f23facc31a..6ce59146e412 100644 --- a/tests/TestHelpers/TagsHelper.php +++ b/tests/TestHelpers/TagsHelper.php @@ -21,6 +21,8 @@ */ namespace TestHelpers; +use GuzzleHttp\Exception\GuzzleException; +use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; use Exception; use SimpleXMLElement; @@ -31,7 +33,7 @@ * @author Artur Neumann * */ -class TagsHelper extends \PHPUnit\Framework\Assert { +class TagsHelper extends Assert { /** * tags a file * @@ -48,7 +50,7 @@ class TagsHelper extends \PHPUnit\Framework\Assert { * @param string|null $adminPassword * * @return ResponseInterface - * @throws Exception + * @throws Exception|GuzzleException */ public static function tag( ?string $baseUrl, @@ -162,7 +164,7 @@ public static function requestTagsForUser( 'oc:can-assign' ]; if ($withGroups) { - \array_push($properties, 'oc:groups'); + $properties[] = 'oc:groups'; } $response = WebDavHelper::propfind( $baseUrl, @@ -230,6 +232,7 @@ public static function requestTagByDisplayName( * @param int|null $davPathVersionToUse (1|2) * * @return ResponseInterface + * @throws GuzzleException * @link self::makeDavRequest() */ public static function createTag( @@ -280,6 +283,7 @@ public static function createTag( * @param int|null $davPathVersionToUse (1|2) * * @return ResponseInterface + * @throws GuzzleException */ public static function deleteTag( ?string $baseUrl, diff --git a/tests/TestHelpers/TranslationHelper.php b/tests/TestHelpers/TranslationHelper.php index 815b20d29187..e4c05b1be8de 100644 --- a/tests/TestHelpers/TranslationHelper.php +++ b/tests/TestHelpers/TranslationHelper.php @@ -24,7 +24,7 @@ /** * Class TranslationHelper * - * Helper functions that are needed to run tests on different languages + * Helper functions that are needed to run tests in different languages * * @package TestHelpers */ diff --git a/tests/TestHelpers/Unit/DeleteHelperTest.php b/tests/TestHelpers/Unit/DeleteHelperTest.php index 4749e247adcc..d958bd646664 100644 --- a/tests/TestHelpers/Unit/DeleteHelperTest.php +++ b/tests/TestHelpers/Unit/DeleteHelperTest.php @@ -56,7 +56,7 @@ public function setUp(): void { * @return void */ public function testDeleteHelperWithOlderDavVersion():void { - $response = DeleteHelper::delete( + DeleteHelper::delete( 'http://localhost', 'user', 'password', @@ -86,7 +86,7 @@ public function testDeleteHelperWithOlderDavVersion():void { * @return void */ public function testDeleteHelperWithNewerDavVersion():void { - $response = DeleteHelper::delete( + DeleteHelper::delete( 'http://localhost', 'user', 'password', @@ -117,7 +117,7 @@ public function testDeleteHelperWithNewerDavVersion():void { */ public function testDeleteHelperSendsWithGivenHeaders():void { $headers = ["Cache-Control" => "no-cache"]; - $response = DeleteHelper::delete( + DeleteHelper::delete( 'http://localhost', 'user', 'password', diff --git a/tests/TestHelpers/Unit/WebDavHelperTest.php b/tests/TestHelpers/Unit/WebDavHelperTest.php index ff36267c0cb5..6fe5059999c3 100644 --- a/tests/TestHelpers/Unit/WebDavHelperTest.php +++ b/tests/TestHelpers/Unit/WebDavHelperTest.php @@ -32,11 +32,8 @@ * Test for WebDavHelper */ class WebDavHelperTest extends PHPUnit\Framework\TestCase { - private $container = []; - /** - * @var Client - */ - private $client; + private array $container = []; + private Client $client; /** * Setup mock response, client and listen for all requests @@ -62,9 +59,10 @@ public function setUp(): void { * for newer Dav path * * @return void + * @throws \GuzzleHttp\Exception\GuzzleException */ public function testUrlIsSanitizedByMakeDavRequestForNewerDav():void { - $response = WebDavHelper::makeDavRequest( + WebDavHelper::makeDavRequest( 'http://own.cloud///core', 'user1', 'pass', @@ -99,9 +97,10 @@ public function testUrlIsSanitizedByMakeDavRequestForNewerDav():void { * for older Dav path * * @return void + * @throws \GuzzleHttp\Exception\GuzzleException */ public function testUrlIsSanitizedByMakeDavRequestForOlderDavPath():void { - $response = WebDavHelper::makeDavRequest( + WebDavHelper::makeDavRequest( 'http://own.cloud///core', 'user1', 'pass', @@ -136,9 +135,10 @@ public function testUrlIsSanitizedByMakeDavRequestForOlderDavPath():void { * Guzzle doesn't do that, we replace manually there. * * @return void + * @throws \GuzzleHttp\Exception\GuzzleException */ public function testMakeDavRequestReplacesAsteriskAndHashesOnUrls():void { - $response = WebDavHelper::makeDavRequest( + WebDavHelper::makeDavRequest( 'http://own.cloud///core', 'user1', 'pass', @@ -178,9 +178,10 @@ public function testMakeDavRequestReplacesAsteriskAndHashesOnUrls():void { * bearer password when authType is set to "bearer" * * @return void + * @throws \GuzzleHttp\Exception\GuzzleException */ public function testMakeDavRequestOnBearerAuthorization():void { - $response = WebDavHelper::makeDavRequest( + WebDavHelper::makeDavRequest( 'http://own.cloud/core', 'user1', 'pass', @@ -204,7 +205,7 @@ public function testMakeDavRequestOnBearerAuthorization():void { $lastRequest = $this->container[0]['request']; // no way to know that $user and $password is set to null, except confirming that - // the Authorization is `Bearer`. If it would have gotten username and password, + // the Authorization is `Bearer`. If it had gotten username and password, // it would have been `Basic`. $this->assertEquals(['Bearer pass'], $lastRequest->getHeaders()["Authorization"]); } @@ -236,7 +237,7 @@ public function testSanitizationOnDefault(?string $unsanitizedUrl, ?string $expe * @return void */ public function testSanitizationWhenTrailingSlashIsSetToFalse(?string $unsanitizedUrl, ?string $expectedUrl):void { - $sanitizedUrl = WebDavHelper::sanitizeUrl($unsanitizedUrl, false); + $sanitizedUrl = WebDavHelper::sanitizeUrl($unsanitizedUrl); $this->assertEquals($expectedUrl, $sanitizedUrl); } @@ -245,8 +246,8 @@ public function testSanitizationWhenTrailingSlashIsSetToFalse(?string $unsanitiz * * @dataProvider withTrailingSlashUrlsProvider * - * @param string $unsanitizedUrl - * @param string $expectedUrl + * @param string|null $unsanitizedUrl + * @param string|null $expectedUrl * * @return void */ @@ -262,15 +263,15 @@ public function testSanitizationWhenTrailingSlashIsSetToTrue(?string $unsanitize */ public function testGetDavPathForOlderDavVersion():void { $davPath = WebDavHelper::getDavPath('user1', 1); - $this->assertEquals($davPath, 'remote.php/webdav/'); + $this->assertEquals('remote.php/webdav/', $davPath); // we don't need `user` to generate url for older dav path $davPath = WebDavHelper::getDavPath(null, 1); - $this->assertEquals($davPath, 'remote.php/webdav/'); + $this->assertEquals('remote.php/webdav/', $davPath); // version 1 should be default $davPath = WebDavHelper::getDavPath(null); - $this->assertEquals($davPath, 'remote.php/webdav/'); + $this->assertEquals('remote.php/webdav/', $davPath); } /** @@ -282,10 +283,10 @@ public function testGetDavPathForNewerDavPath():void { // `type` should be `files` by default. // check that both returns same thing. $davPath = WebDavHelper::getDavPath('user1', 2); - $this->assertEquals($davPath, 'remote.php/dav/files/user1/'); + $this->assertEquals('remote.php/dav/files/user1/', $davPath); - $davPath = WebDavHelper::getDavPath('user1', 2, 'files'); - $this->assertEquals($davPath, 'remote.php/dav/files/user1/'); + $davPath = WebDavHelper::getDavPath('user1', 2); + $this->assertEquals('remote.php/dav/files/user1/', $davPath); } /** @@ -296,10 +297,10 @@ public function testGetDavPathForNewerDavPath():void { */ public function testGetDavPathForNewerDavPathButNotForFiles():void { $davPath = WebDavHelper::getDavPath('user1', 2, null); - $this->assertEquals($davPath, 'remote.php/dav'); + $this->assertEquals('remote.php/dav', $davPath); $davPath = WebDavHelper::getDavPath('user1', 2, 'not_files'); - $this->assertEquals($davPath, 'remote.php/dav'); + $this->assertEquals('remote.php/dav', $davPath); } /** @@ -312,7 +313,7 @@ public function testGetDavPathForInvalidVersionsShouldThrowException():void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage("DAV path version 3 is unknown"); - $davPath = WebDavHelper::getDavPath(null, 3); + WebDavHelper::getDavPath(null, 3); } /** diff --git a/tests/TestHelpers/UploadHelper.php b/tests/TestHelpers/UploadHelper.php index 1ff63cfa55bb..7cb3d4534156 100644 --- a/tests/TestHelpers/UploadHelper.php +++ b/tests/TestHelpers/UploadHelper.php @@ -21,6 +21,8 @@ */ namespace TestHelpers; +use GuzzleHttp\Exception\GuzzleException; +use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; /** @@ -29,7 +31,7 @@ * @author Artur Neumann * */ -class UploadHelper extends \PHPUnit\Framework\Assert { +class UploadHelper extends Assert { /** * * @param string|null $baseUrl URL of owncloud @@ -46,9 +48,10 @@ class UploadHelper extends \PHPUnit\Framework\Assert { * @param int|null $davPathVersionToUse (1|2) * @param int|null $chunkingVersion (1|2|null) * if set to null chunking will not be used - * @param int|null $noOfChunks how many chunks do we want to upload + * @param int|null $noOfChunks how many chunks to upload * * @return ResponseInterface + * @throws GuzzleException */ public static function upload( ?string $baseUrl, @@ -79,10 +82,12 @@ public static function upload( } else { //prepare chunking $chunks = self::chunkFile($source, $noOfChunks); - $chunkingId = 'chunking-' . (string)\rand(1000, 9999); + $chunkingId = 'chunking-' . \rand(1000, 9999); $v2ChunksDestination = '/uploads/' . $user . '/' . $chunkingId; } + $result = null; + //prepare chunking version specific stuff if ($chunkingVersion === 1) { $headers['OC-Chunked'] = '1'; @@ -102,16 +107,19 @@ public static function upload( if ($result->getStatusCode() >= 400) { return $result; } + } else { + self::fail(__METHOD__ . " Chunking version must be 1, 2 or null but $chunkingVersion was passed in."); } //upload chunks foreach ($chunks as $index => $chunk) { if ($chunkingVersion === 1) { $filename = $destination . "-" . $chunkingId . "-" . - \count($chunks) . '-' . ( string ) $index; + \count($chunks) . '-' . $index; $davRequestType = "files"; - } elseif ($chunkingVersion === 2) { - $filename = $v2ChunksDestination . '/' . (string)($index); + } else { + // do chunking version 2 + $filename = $v2ChunksDestination . '/' . $index; $davRequestType = "uploads"; } $result = WebDavHelper::makeDavRequest( @@ -152,6 +160,7 @@ public static function upload( return $result; } } + self::assertNotNull($result, __METHOD__ . " chunking version $chunkingVersion was requested but no upload was done."); return $result; } @@ -164,11 +173,12 @@ public static function upload( * @param string|null $source source file path * @param string|null $destination destination path on the server * @param string|null $xRequestId - * @param bool $overwriteMode when false creates separate files to test uploading brand new files, + * @param bool $overwriteMode when false creates separate files to test uploading brand-new files, * when true it just overwrites the same file over and over again with the same name * @param string|null $exceptChunkingType empty string or "old" or "new" * * @return array of ResponseInterface + * @throws GuzzleException */ public static function uploadWithAllMechanisms( ?string $baseUrl, diff --git a/tests/TestHelpers/UserHelper.php b/tests/TestHelpers/UserHelper.php index dca43b9b113f..2df8d9f5ea97 100644 --- a/tests/TestHelpers/UserHelper.php +++ b/tests/TestHelpers/UserHelper.php @@ -23,6 +23,7 @@ use Exception; use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Message\ResponseInterface; /** @@ -44,6 +45,7 @@ class UserHelper { * @param int|null $ocsApiVersion * * @return ResponseInterface + * @throws GuzzleException */ public static function editUser( ?string $baseUrl, @@ -99,15 +101,12 @@ public static function editUserBatch( $path = "/cloud/users/" . $data['user']; $body = ["key" => $data['key'], 'value' => $data["value"]]; // Create the OCS API requests and push them to an array. - \array_push( - $requests, - OcsApiHelper::createOcsRequest( - $baseUrl, - 'PUT', - $path, - $xRequestId, - $body - ) + $requests[] = OcsApiHelper::createOcsRequest( + $baseUrl, + 'PUT', + $path, + $xRequestId, + $body ); } // Send the array of requests at once in parallel. @@ -135,6 +134,7 @@ public static function editUserBatch( * @param int|null $ocsApiVersion * * @return ResponseInterface + * @throws GuzzleException */ public static function getUser( ?string $baseUrl, @@ -166,6 +166,7 @@ public static function getUser( * @param int|null $ocsApiVersion * * @return ResponseInterface + * @throws GuzzleException */ public static function deleteUser( ?string $baseUrl, @@ -196,6 +197,7 @@ public static function deleteUser( * @param string|null $xRequestId * * @return ResponseInterface + * @throws GuzzleException */ public static function createGroup( ?string $baseUrl, @@ -225,6 +227,7 @@ public static function createGroup( * @param int|null $ocsApiVersion * * @return ResponseInterface + * @throws GuzzleException */ public static function deleteGroup( ?string $baseUrl, @@ -258,6 +261,7 @@ public static function deleteGroup( * @param int|null $ocsApiVersion (1|2) * * @return ResponseInterface + * @throws GuzzleException */ public static function addUserToGroup( ?string $baseUrl, @@ -291,6 +295,7 @@ public static function addUserToGroup( * @param int|null $ocsApiVersion (1|2) * * @return ResponseInterface + * @throws GuzzleException */ public static function removeUserFromGroup( ?string $baseUrl, @@ -322,6 +327,7 @@ public static function removeUserFromGroup( * @param string|null $search * * @return ResponseInterface + * @throws GuzzleException */ public static function getGroups( ?string $baseUrl, @@ -349,7 +355,7 @@ public static function getGroups( * @param string|null $search * * @return string[] - * @throws Exception + * @throws Exception|GuzzleException */ public static function getGroupsAsArray( ?string $baseUrl, diff --git a/tests/TestHelpers/WebDavHelper.php b/tests/TestHelpers/WebDavHelper.php index 6cd5fd1b03e5..577519240264 100644 --- a/tests/TestHelpers/WebDavHelper.php +++ b/tests/TestHelpers/WebDavHelper.php @@ -29,7 +29,6 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; use DateTime; -use TestHelpers\SpaceNotFoundException; /** * Helper to make WebDav Requests @@ -45,7 +44,7 @@ class WebDavHelper { /** * @var array of users with their different spaces ids */ - public static $spacesIdRef = []; + public static array $spacesIdRef = []; /** * clear space id reference for user @@ -74,7 +73,7 @@ public static function removeSpaceIdReferenceForUser( * @param int|null $davPathVersionToUse * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getFileIdForPath( ?string $baseUrl, @@ -173,7 +172,7 @@ public static function getBodyForPropfind(?array $properties): string { * @param string[] $properties * string can contain namespace prefix, * if no prefix is given 'd:' is used as prefix - * if associated array is used then the key will be used as namespace + * if an associative array is used then the key will be used as namespace * @param string|null $xRequestId * @param string|null $folderDepth * @param string|null $type @@ -181,6 +180,7 @@ public static function getBodyForPropfind(?array $properties): string { * @param string|null $doDavRequestAsUser * * @return ResponseInterface + * @throws GuzzleException */ public static function propfind( ?string $baseUrl, @@ -236,6 +236,7 @@ public static function propfind( * @param string|null $type * * @return ResponseInterface + * @throws GuzzleException */ public static function proppatch( ?string $baseUrl, @@ -386,6 +387,7 @@ public static function proppatchWithMultipleProps( * @param int|null $davPathVersionToUse * * @return ResponseInterface + * @throws GuzzleException */ public static function listFolder( ?string $baseUrl, @@ -428,7 +430,7 @@ public static function generateUUIDv4():string { $data = random_bytes(16); \assert(\strlen($data) == 16); - $data[6] = \chr(\ord($data[6]) & 0x0f | 0x40); // set version to 0100 + $data[6] = \chr(\ord($data[6]) & 0x0f | 0x40); // set the version to 0100 $data[8] = \chr(\ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); @@ -543,7 +545,7 @@ public static function getPersonalSpaceIdForUser(string $baseUrl, string $user, } /** - * First checks if a user exist to return its space ID + * First checks if a user exists to return its space ID * In case of any exception, it returns a fake space ID * * @param string $baseUrl @@ -552,7 +554,7 @@ public static function getPersonalSpaceIdForUser(string $baseUrl, string $user, * @param string $xRequestId * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getPersonalSpaceIdForUserOrFakeIfNotFound(string $baseUrl, string $user, string $password, string $xRequestId):string { try { @@ -594,8 +596,8 @@ public static function getPersonalSpaceIdForUserOrFakeIfNotFound(string $baseUrl * than download it all up-front. * @param int|null $timeout * @param Client|null $client - * @param array|null $urlParameter to concatenate with path - * @param string|null $doDavRequestAsUser run the DAV as this user, if null its same as $user + * @param array|null $urlParameter to concatenate with the path + * @param string|null $doDavRequestAsUser run the DAV as this user, if null it is the same as $user * * @return ResponseInterface * @throws GuzzleException @@ -622,7 +624,7 @@ public static function makeDavRequest( ):ResponseInterface { $baseUrl = self::sanitizeUrl($baseUrl, true); - // We need to manipulate and use path as a string. + // We need to manipulate and use the path as a string. // So ensure that it is a string to avoid any type-conversion errors. if ($path === null) { $path = ""; @@ -729,7 +731,7 @@ public static function getDavPath( } else { if ($davPathVersionToUse === self::DAV_VERSION_OLD) { if ($type === "trash-bin") { - // Since there is no trash bin endpoint for old dav version, new dav version's endpoint is used here. + // Since there is no trash bin endpoint for an old dav version, new dav version's endpoint is used here. return $newTrashbinDavPath; } return "remote.php/webdav/"; @@ -751,7 +753,7 @@ public static function getDavPath( } /** - * make sure there are no double slash in the URL + * make sure there are no double slashes in the URL * * @param string|null $url * @param bool|null $trailingSlash forces a trailing slash @@ -764,30 +766,29 @@ public static function sanitizeUrl(?string $url, ?bool $trailingSlash = false):s } else { $url = \rtrim($url, "/"); } - $url = \preg_replace("/([^:]\/)\/+/", '$1', $url); - return $url; + return \preg_replace("/([^:]\/)\/+/", '$1', $url); } /** - * decides if the proposed dav version and chunking version are + * Decides if the proposed dav version and chunking version are * a valid combination. * If no chunkingVersion is specified, then any dav version is valid. * If a chunkingVersion is specified, then it has to match the dav version. - * Note: in future the dav and chunking versions might or might not + * Note: in the future, the dav and chunking versions might or might not * move together and/or be supported together. So a more complex * matrix could be needed here. * * @param string|int $davPathVersion * @param string|int|null $chunkingVersion * - * @return boolean is this a valid combination + * @return boolean if this a valid combination */ public static function isValidDavChunkingCombination( $davPathVersion, $chunkingVersion ): bool { if ($davPathVersion === self::DAV_VERSION_SPACES) { - // allow only old chunking version when using the spaces dav + // allow only an old chunking version when using the spaces dav return $chunkingVersion === 1; } return ( @@ -806,9 +807,9 @@ public static function isValidDavChunkingCombination( * @param int|null $davVersionToUse * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ - public static function getMtimeOfFileinPublicLinkShare( + public static function getMtimeOfFileInPublicLinkShare( ?string $baseUrl, ?string $fileName, ?string $token, @@ -819,7 +820,7 @@ public static function getMtimeOfFileinPublicLinkShare( $baseUrl, null, null, - "/public-files/{$token}/{$fileName}", + "/public-files/$token/$fileName", ['d:getlastmodified'], $xRequestId, '1', @@ -846,7 +847,7 @@ public static function getMtimeOfFileinPublicLinkShare( * @param int|null $davPathVersionToUse * * @return string - * @throws Exception + * @throws Exception|GuzzleException */ public static function getMtimeOfResource( ?string $user, @@ -875,7 +876,7 @@ public static function getMtimeOfResource( Assert::assertArrayHasKey( 0, $xmlpart, - __METHOD__ . " XML part does not have key 0. Expected a value at index 0 of 'xmlPart' but, found: " . (string) json_encode($xmlpart) + __METHOD__ . " XML part does not have key 0. Expected a value at index 0 of 'xmlPart' but, found: " . json_encode($xmlpart) ); $mtime = new DateTime($xmlpart[0]->__toString()); return $mtime->format('U'); diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index b1653494924d..64e9f9964602 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -709,6 +709,7 @@ default: contexts: - FeatureContext: *common_feature_context_params - OccContext: + - LoggingContext: cliCreateLocalStorage: paths: diff --git a/tests/acceptance/features/apiVersions/fileVersionAuthor.feature b/tests/acceptance/features/apiVersions/fileVersionAuthor.feature index aa5f9d548d88..98e4437ed158 100644 --- a/tests/acceptance/features/apiVersions/fileVersionAuthor.feature +++ b/tests/acceptance/features/apiVersions/fileVersionAuthor.feature @@ -23,11 +23,11 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Brian,Carol,David" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Brian,Carol,David" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -46,10 +46,10 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Brian,Carol" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Brian,Carol" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -66,10 +66,10 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/textfile0.txt" When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Brian,Carol" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Brian,Carol" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -90,11 +90,11 @@ Feature: file versions remember the author of each version And user "Brian" has moved file "/textfile0.txt" to "/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Brian,Carol" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Brian,Carol" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -113,14 +113,14 @@ Feature: file versions remember the author of each version And user "Alice" has moved file "/exist.txt" to "/textfile0.txt" When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as user "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as user "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/exist.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/exist.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -138,14 +138,14 @@ Feature: file versions remember the author of each version And user "Brian" has moved file "/exist.txt" to "/textfile0.txt" When user "Alice" gets the number of versions of file "exist.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/exist.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/exist.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Carol" the authors of the noncurrent versions of file "/exist.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/exist.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/exist.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Carol" the authors of the non-current versions of file "/exist.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as user "Brian" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -166,11 +166,11 @@ Feature: file versions remember the author of each version And user "Alice" has shared folder "/test" with group "grp1" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,Brian,Carol" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,Brian,Carol" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -194,30 +194,30 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,David" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,David" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/test (2)/textfile0.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/test (2)/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | When user "Brian" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "1" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Brian" should be "duplicate brian" - And as user "Brian" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "1" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Brian" should be "duplicate brian" + And as user "Brian" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | When user "Carol" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "0" + And the number of non-current versions should be "0" @skip_on_objectstore Scenario: enable file versioning and check the history of changes from multiple users who have a matching file @@ -234,30 +234,30 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/textfile0.txt" When user "Alice" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice,David" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice,David" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/textfile0 (2).txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/textfile0 (2).txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | When user "Brian" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "1" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Brian" should be "duplicate brian" - And as user "Brian" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "1" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Brian" should be "duplicate brian" + And as user "Brian" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | When user "Carol" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "0" + And the number of non-current versions should be "0" @skip_on_objectstore Scenario: enable file versioning and check the version author after restoring a version of a file inside a folder @@ -269,7 +269,7 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/test/textfile0.txt" When user "Brian" restores version index "1" of file "/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian,Carol" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice,Brian,Carol" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -284,7 +284,7 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/textfile0.txt" When user "Brian" restores version index "1" of file "/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian,Carol" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice,Brian,Carol" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -299,13 +299,13 @@ Feature: file versions remember the author of each version And user "Brian" has uploaded file with content "uploaded content brian" to "/textfile0.txt" When user "Brian" restores version index "1" of file "/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice,Brian" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | When user "Brian" restores version index "1" of file "/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice,Brian" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | @@ -321,13 +321,13 @@ Feature: file versions remember the author of each version And user "Brian" has uploaded file with content "uploaded content brian" to "/test/textfile0.txt" When user "Brian" restores version index "1" of file "/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice,Brian" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | When user "Brian" restores version index "1" of file "/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice,Brian" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice,Brian" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | diff --git a/tests/acceptance/features/apiVersions/fileVersionAuthorSharingToShares.feature b/tests/acceptance/features/apiVersions/fileVersionAuthorSharingToShares.feature index bc3051d384e2..f58334a3cfc4 100644 --- a/tests/acceptance/features/apiVersions/fileVersionAuthorSharingToShares.feature +++ b/tests/acceptance/features/apiVersions/fileVersionAuthorSharingToShares.feature @@ -28,16 +28,16 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/Shares/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol,David" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as users "Brian,Carol,David" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -58,14 +58,14 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/Shares/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -84,14 +84,14 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/Shares/textfile0.txt" When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/Shares/textfile0.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/Shares/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -114,16 +114,16 @@ Feature: file versions remember the author of each version And user "Brian" has moved file "/textfile0.txt" to "/Shares/test/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -144,14 +144,14 @@ Feature: file versions remember the author of each version And user "Alice" has moved file "/exist.txt" to "/textfile0.txt" When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as user "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as user "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/Shares/exist.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/Shares/exist.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -171,18 +171,18 @@ Feature: file versions remember the author of each version And user "Brian" has moved file "/Shares/exist.txt" to "/Shares/textfile0.txt" When user "Alice" gets the number of versions of file "exist.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "2" - And the content of noncurrent version index "1" of file "/exist.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "2" of file "/exist.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/exist.txt" should be: + And the number of non-current versions should be "2" + And the content of non-current version index "1" of file "/exist.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "2" of file "/exist.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/exist.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as users "Carol" the authors of the noncurrent versions of file "/Shares/exist.txt" should be: + And as users "Carol" the authors of the non-current versions of file "/Shares/exist.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | - And as user "Brian" the authors of the noncurrent versions of file "/Shares/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/Shares/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Alice | @@ -207,16 +207,16 @@ Feature: file versions remember the author of each version And user "Carol" has accepted share "/test" offered by user "Alice" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as users "Brian,Carol" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -249,30 +249,30 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/Shares/test (2)/textfile0.txt" When user "Alice" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/test/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol,David" the authors of the noncurrent versions of file "/Shares/test (2)/textfile0.txt" should be: + And as users "Brian,Carol,David" the authors of the non-current versions of file "/Shares/test (2)/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | When user "Brian" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "1" - And the content of noncurrent version index "1" of file "/test/textfile0.txt" for user "Brian" should be "duplicate brian" - And as user "Brian" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And the number of non-current versions should be "1" + And the content of non-current version index "1" of file "/test/textfile0.txt" for user "Brian" should be "duplicate brian" + And as user "Brian" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | When user "Carol" gets the number of versions of file "/test/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "0" + And the number of non-current versions should be "0" @skip_on_objectstore Scenario: enable file versioning and check the history of changes from multiple users who have a matching file @@ -298,30 +298,30 @@ Feature: file versions remember the author of each version And user "David" has uploaded file with content "uploaded content david" to "/Shares/textfile0 (2).txt" When user "Alice" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content carol" - And the content of noncurrent version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" - And the content of noncurrent version index "3" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" - And as users "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "3" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Alice" should be "uploaded content carol" + And the content of non-current version index "2" of file "/textfile0.txt" for user "Alice" should be "uploaded content brian" + And the content of non-current version index "3" of file "/textfile0.txt" for user "Alice" should be "uploaded content alice" + And as users "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as users "Brian,Carol,David" the authors of the noncurrent versions of file "/Shares/textfile0 (2).txt" should be: + And as users "Brian,Carol,David" the authors of the non-current versions of file "/Shares/textfile0 (2).txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | When user "Brian" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "1" - And the content of noncurrent version index "1" of file "/textfile0.txt" for user "Brian" should be "duplicate brian" - And as user "Brian" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And the number of non-current versions should be "1" + And the content of non-current version index "1" of file "/textfile0.txt" for user "Brian" should be "duplicate brian" + And as user "Brian" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | When user "Carol" gets the number of versions of file "/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "0" + And the number of non-current versions should be "0" @skip_on_objectstore @files_sharing-app-required Scenario: enable file versioning and check the version author after restoring a version of a file inside a folder @@ -335,12 +335,12 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/Shares/test/textfile0.txt" When user "Brian" restores version index "1" of file "/Shares/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as user "Brian,Carol" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as user "Brian,Carol" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -357,12 +357,12 @@ Feature: file versions remember the author of each version And user "Carol" has uploaded file with content "uploaded content carol" to "/Shares/textfile0.txt" When user "Brian" restores version index "1" of file "/Shares/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | | 3 | Alice | - And as user "Brian,Carol" the authors of the noncurrent versions of file "/Shares/textfile0.txt" should be: + And as user "Brian,Carol" the authors of the non-current versions of file "/Shares/textfile0.txt" should be: | index | author | | 1 | Carol | | 2 | Brian | @@ -378,22 +378,22 @@ Feature: file versions remember the author of each version And user "Brian" has uploaded file with content "uploaded content brian" to "/Shares/textfile0.txt" When user "Brian" restores version index "1" of file "/Shares/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | - And as user "Brian" the authors of the noncurrent versions of file "/Shares/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/Shares/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | When user "Brian" restores version index "1" of file "/Shares/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | | 3 | | - And as user "Brian" the authors of the noncurrent versions of file "/Shares/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/Shares/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | @@ -410,22 +410,22 @@ Feature: file versions remember the author of each version And user "Brian" has uploaded file with content "uploaded content brian" to "/Shares/test/textfile0.txt" When user "Brian" restores version index "1" of file "/Shares/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | - And as user "Brian" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | | When user "Brian" restores version index "1" of file "/Shares/test/textfile0.txt" using the WebDAV API Then the HTTP status code should be "204" - And as user "Alice" the authors of the noncurrent versions of file "/test/textfile0.txt" should be: + And as user "Alice" the authors of the non-current versions of file "/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | | 3 | | - And as user "Brian" the authors of the noncurrent versions of file "/Shares/test/textfile0.txt" should be: + And as user "Brian" the authors of the non-current versions of file "/Shares/test/textfile0.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | diff --git a/tests/acceptance/features/apiVersions/fileVersions.feature b/tests/acceptance/features/apiVersions/fileVersions.feature index dce455ff962a..35434211c706 100644 --- a/tests/acceptance/features/apiVersions/fileVersions.feature +++ b/tests/acceptance/features/apiVersions/fileVersions.feature @@ -381,7 +381,7 @@ Feature: dav-versions And user "Alice" has shared file "textfile0.txt" with user "Brian" When user "Brian" tries to get versions of file "textfile0.txt" from "Alice" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" + And the number of non-current versions should be "3" Scenario: User cannot access meta folder of a file which does not exist @@ -420,14 +420,14 @@ Feature: dav-versions When user "Alice" moves file "textfile0.txt" to "/testFolder/textfile0.txt" using the WebDAV API And user "Alice" gets the number of versions of file "/testFolder/textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" + And the number of non-current versions should be "3" Scenario: Original file has version number 0 Given user "Alice" has uploaded file with content "uploaded content" to "textfile0.txt" When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "0" + And the number of non-current versions should be "0" Scenario: the number of etag elements in response changes according to version of the file @@ -437,7 +437,7 @@ Feature: dav-versions When user "Alice" gets the number of versions of file "textfile0.txt" Then the HTTP status code should be "207" And the number of etag elements in the response should be "2" - And the number of noncurrent versions should be "2" + And the number of non-current versions should be "2" Scenario: download old versions of a file diff --git a/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature b/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature index 093f94cd468a..54a8954f21be 100644 --- a/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature +++ b/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature @@ -267,7 +267,7 @@ Feature: dav-versions And user "Brian" has accepted share "/textfile0.txt" offered by user "Alice" When user "Brian" tries to get versions of file "textfile0.txt" from "Alice" Then the HTTP status code should be "207" - And the number of noncurrent versions should be "3" + And the number of non-current versions should be "3" Scenario: Receiver tries get file versions of shared file before receiving it diff --git a/tests/acceptance/features/apiWebdavProperties1/copyFile.feature b/tests/acceptance/features/apiWebdavProperties1/copyFile.feature index 8ecc91202e92..51903ba7c6a9 100644 --- a/tests/acceptance/features/apiWebdavProperties1/copyFile.feature +++ b/tests/acceptance/features/apiWebdavProperties1/copyFile.feature @@ -215,10 +215,32 @@ Feature: copy file And user "Alice" has accepted share "/BRIAN-Folder" offered by user "Brian" When user "Alice" copies file "/textfile1.txt" to "/Shares/BRIAN-Folder" using the WebDAV API Then the HTTP status code should be "204" + # Alice now sees the content of "her" file in /Shares/BRIAN-Folder + # The share that she received from Brian has "automatically" gone into the "declined" state And the content of file "/Shares/BRIAN-Folder" for user "Alice" should be "ownCloud test text file 1" And as "Alice" folder "/Shares/BRIAN-Folder/sample-folder" should not exist And as "Alice" file "/textfile1.txt" should exist And user "Alice" should not have any received shares + And the sharing API should report to user "Alice" that these shares are in the declined state + | path | + | /Shares/BRIAN-Folder/ | + # Brian still has his original BRIAN-Folder and can see that it is shared with Alice + And as "Brian" folder "BRIAN-Folder" should exist + And as "Brian" folder "BRIAN-Folder/sample-folder" should exist + When user "Brian" gets all shares shared by him using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And folder "/Shares/BRIAN-Folder" should be included in the response + # Alice can accept the share from Brian again + When user "Alice" accepts share "/BRIAN-Folder" offered by user "Brian" using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + # now Alice has "her" text file as "/Shares/BRIAN-Folder" + # and has the shared folder from Brian as "/Shares/BRIAN-Folder (2)" + And as "Alice" file "/Shares/BRIAN-Folder" should exist + And the content of file "/Shares/BRIAN-Folder" for user "Alice" should be "ownCloud test text file 1" + And as "Alice" folder "/Shares/BRIAN-Folder (2)" should exist + And as "Alice" folder "/Shares/BRIAN-Folder (2)/sample-folder" should exist Examples: | dav_version | | old | @@ -234,9 +256,72 @@ Feature: copy file And user "Alice" has created folder "FOLDER/sample-folder" When user "Alice" copies folder "/FOLDER" to "/Shares/sharedfile1.txt" using the WebDAV API Then the HTTP status code should be "204" + # Alice now sees the content of "her" folder as folder "/Shares/sharedfile1.txt" + # The share that she received from Brian has "automatically" gone into the "declined" state And as "Alice" folder "/FOLDER/sample-folder" should exist And as "Alice" folder "/Shares/sharedfile1.txt/sample-folder" should exist And user "Alice" should not have any received shares + And the sharing API should report to user "Alice" that these shares are in the declined state + | path | + | /Shares/sharedfile1.txt | + # Brian still has his original sharedfile1.txt and can see that it is shared with Alice + And as "Brian" file "sharedfile1.txt" should exist + And the content of file "sharedfile1.txt" for user "Brian" should be "file to share" + When user "Brian" gets all shares shared by him using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And file "/Shares/sharedfile1.txt" should be included in the response + When user "Alice" accepts share "/sharedfile1.txt" offered by user "Brian" using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + # now Alice has "her" folder as "/Shares/sharedfile1.txt" + # and has the shared file from Brian as "/Shares/sharedfile1 (2).txt" + And as "Alice" folder "/Shares/sharedfile1.txt" should exist + And as "Alice" folder "/Shares/sharedfile1.txt/sample-folder" should exist + And as "Alice" file "/Shares/sharedfile1 (2).txt" should exist + And the content of file "/Shares/sharedfile1 (2).txt" for user "Alice" should be "file to share" + Examples: + | dav_version | + | old | + | new | + + @skipOnOcV10 @issue-40787 @files_sharing-app-required + Scenario Outline: copy a file over the top of an existing file received as a user share + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has uploaded file with content "file to share" to "/sharedfile1.txt" + And user "Brian" has shared file "/sharedfile1.txt" with user "Alice" + And user "Alice" has accepted share "/sharedfile1.txt" offered by user "Brian" + When user "Alice" copies file "/textfile1.txt" to "/Shares/sharedfile1.txt" using the WebDAV API + Then the HTTP status code should be "204" + And as "Alice" file "/Shares/sharedfile1.txt" should exist + And the content of file "/Shares/sharedfile1.txt" for user "Alice" should be "ownCloud test text file 1" + And as "Alice" file "/textfile1.txt" should exist + And as "Brian" file "/sharedfile1.txt" should exist + And the content of file "/sharedfile1.txt" for user "Brian" should be "ownCloud test text file 1" + Examples: + | dav_version | + | old | + | new | + + @skipOnOcV10 @issue-40788 @files_sharing-app-required + Scenario Outline: copy a folder over the top of an existing folder received as a user share + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has created folder "/BRIAN-Folder" + And user "Brian" has created folder "BRIAN-Folder/sample-folder" + And user "Brian" has shared folder "BRIAN-Folder" with user "Alice" + And user "Alice" has accepted share "/BRIAN-Folder" offered by user "Brian" + And user "Alice" has created folder "FOLDER/ALICE-folder" + When user "Alice" copies folder "/FOLDER" to "/Shares/BRIAN-Folder" using the WebDAV API + Then the HTTP status code should be "409" + And as "Alice" folder "/FOLDER/ALICE-folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder/sample-folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder/ALICE-folder" should not exist + And as "Brian" folder "BRIAN-Folder" should exist + And as "Brian" folder "BRIAN-Folder/sample-folder" should exist + And as "Brian" folder "/Shares/BRIAN-Folder/ALICE-folder" should not exist Examples: | dav_version | | old | @@ -785,3 +870,19 @@ Feature: copy file | dav_version | | old | | new | + + + Scenario Outline: Copying a folder with a file onto another folder + Given using DAV path + And user "Alice" has created folder "/FOLDER1" + And user "Alice" has created folder "/FOLDER2" + And user "Alice" has uploaded file with content "Folder 1 text" to "/FOLDER1/textfile1.txt" + And user "Alice" has uploaded file with content "Folder 2 text" to "/FOLDER2/textfile2.txt" + When user "Alice" copies folder "/FOLDER1" to "/FOLDER2" using the WebDAV API + Then the HTTP status code should be "204" + And as "Alice" file "/FOLDER2/textfile1.txt" should exist + And as "Alice" file "/FOLDER2/textfile2.txt" should not exist + Examples: + | dav_version | + | old | + | new | diff --git a/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40787.feature b/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40787.feature new file mode 100644 index 000000000000..b9c6d4513280 --- /dev/null +++ b/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40787.feature @@ -0,0 +1,51 @@ +@api +Feature: copy file + As a user + I want to be able to copy files + So that I can manage my files + + # When fixing this issue, delete this bug-demo feature file. + # And unskip the corresponding scenario in copyFile.feature and make it pass. + Background: + Given using OCS API version "1" + And the administrator has set the default folder for received shares to "Shares" + And auto-accept shares has been disabled + And user "Alice" has been created with default attributes and without skeleton files + And user "Alice" has uploaded file with content "ownCloud test text file 0" to "/textfile0.txt" + And user "Alice" has uploaded file with content "ownCloud test text file 1" to "/textfile1.txt" + + @issue-40787 @files_sharing-app-required + Scenario Outline: copy a file over the top of an existing file received as a user share + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has uploaded file with content "file to share" to "/sharedfile1.txt" + And user "Brian" has shared file "/sharedfile1.txt" with user "Alice" + And user "Alice" has accepted share "/sharedfile1.txt" offered by user "Brian" + When user "Alice" copies file "/textfile1.txt" to "/Shares/sharedfile1.txt" using the WebDAV API + Then the HTTP status code should be "204" + # Alice now sees the content of "her" file in /Shares/sharedfile1.txt + # The share that she received from Brian has "automatically" gone into the "declined" state + And as "Alice" file "/Shares/sharedfile1.txt" should exist + And the content of file "/Shares/sharedfile1.txt" for user "Alice" should be "ownCloud test text file 1" + And as "Alice" file "/textfile1.txt" should exist + And user "Alice" should not have any received shares + And the sharing API should report to user "Alice" that these shares are in the declined state + | path | + | /Shares/sharedfile1.txt | + # Brian still has his original "/sharedfile1.txt" and can see that it is shared with Alice + And as "Brian" file "/sharedfile1.txt" should exist + And the content of file "/sharedfile1.txt" for user "Brian" should be "file to share" + # Alice can accept the share from Brian again + When user "Alice" accepts share "/sharedfile1.txt" offered by user "Brian" using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + # now Alice has "her" text file as "/Shares/sharedfile1.txt" + # and has the shared folder from Brian as "/Shares/sharedfile1 (2).txt" + And as "Alice" file "/Shares/sharedfile1.txt" should exist + And the content of file "/Shares/sharedfile1.txt" for user "Alice" should be "ownCloud test text file 1" + And as "Alice" file "/Shares/sharedfile1 (2).txt" should exist + And the content of file "/Shares/sharedfile1 (2).txt" for user "Alice" should be "file to share" + Examples: + | dav_version | + | old | + | new | diff --git a/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40788.feature b/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40788.feature new file mode 100644 index 000000000000..f63bed3d3622 --- /dev/null +++ b/tests/acceptance/features/apiWebdavProperties1/copyFileOc10Issue40788.feature @@ -0,0 +1,64 @@ +@api +Feature: copy file + As a user + I want to be able to copy files + So that I can manage my files + + # When fixing this issue, delete this bug-demo feature file. + # And unskip the corresponding scenario in copyFile.feature and make it pass. + Background: + Given using OCS API version "1" + And the administrator has set the default folder for received shares to "Shares" + And auto-accept shares has been disabled + And user "Alice" has been created with default attributes and without skeleton files + And user "Alice" has uploaded file with content "ownCloud test text file 0" to "/textfile0.txt" + And user "Alice" has uploaded file with content "ownCloud test text file 1" to "/textfile1.txt" + And user "Alice" has created folder "/FOLDER" + + Scenario Outline: copy a folder over the top of an existing folder received as a user share + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has created folder "/BRIAN-Folder" + And user "Brian" has created folder "BRIAN-Folder/sample-folder" + And user "Brian" has shared folder "BRIAN-Folder" with user "Alice" + And user "Alice" has accepted share "/BRIAN-Folder" offered by user "Brian" + And user "Alice" has created folder "FOLDER/ALICE-folder" + When user "Alice" copies folder "/FOLDER" to "/Shares/BRIAN-Folder" using the WebDAV API + Then the HTTP status code should be "204" + # Alice now sees the content of "her" folder as folder "/Shares/BRIAN-Folder" + # The share that she received from Brian has "automatically" gone into the "declined" state + And as "Alice" folder "/FOLDER/ALICE-folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder/ALICE-folder" should exist + And user "Alice" should not have any received shares + And the sharing API should report to user "Alice" that these shares are in the declined state + | path | + | /Shares/BRIAN-Folder | + # Brian still has his original BRIAN-Folder and can see that it is shared with Alice + And as "Brian" folder "BRIAN-Folder" should exist + And as "Brian" folder "BRIAN-Folder/sample-folder" should exist + When user "Brian" gets all shares shared by him using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And file "/Shares/BRIAN-Folder" should be included in the response + When user "Alice" accepts share "/BRIAN-Folder" offered by user "Brian" using the sharing API + Then the OCS status code should be "100" + And the HTTP status code should be "200" + # now Alice has "her" folder as "/Shares/BRIAN-Folder" + # and has the shared file from Brian as "/Shares/BRIAN-Folder (2)" + And as "Alice" folder "/Shares/BRIAN-Folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder/ALICE-folder" should exist + And as "Alice" folder "/Shares/BRIAN-Folder (2)" should exist + And as "Alice" folder "/Shares/BRIAN-Folder (2)/sample-folder" should exist + # Alice can add content to both folders + # Brian sees what Alice puts into "/Shares/BRIAN-Folder (2)" + And user "Alice" has created folder "/Shares/BRIAN-Folder/new-folder1" + And user "Alice" has created folder "/Shares/BRIAN-Folder (2)/new-folder2" + And user "Alice" has uploaded file with content "new content 1" to "/Shares/BRIAN-Folder/new-folder1/file1.txt" + And user "Alice" has uploaded file with content "new content 2" to "/Shares/BRIAN-Folder (2)/new-folder2/file2.txt" + And the content of file "/Shares/BRIAN-Folder/new-folder1/file1.txt" for user "Alice" should be "new content 1" + And the content of file "/Shares/BRIAN-Folder (2)/new-folder2/file2.txt" for user "Alice" should be "new content 2" + And the content of file "/BRIAN-Folder/new-folder2/file2.txt" for user "Brian" should be "new content 2" + Examples: + | dav_version | + | old | + | new | diff --git a/tests/acceptance/features/bootstrap/AppConfigurationContext.php b/tests/acceptance/features/bootstrap/AppConfigurationContext.php index a27735fabadb..377be9d79963 100644 --- a/tests/acceptance/features/bootstrap/AppConfigurationContext.php +++ b/tests/acceptance/features/bootstrap/AppConfigurationContext.php @@ -34,10 +34,7 @@ * AppConfiguration trait */ class AppConfigurationContext implements Context { - /** - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @When /^the administrator sets parameter "([^"]*)" of app "([^"]*)" to ((?:'[^']*')|(?:"[^"]*"))$/ @@ -169,7 +166,7 @@ public function userGetsCapabilities(string $username, ?bool $formatJson = false * @throws Exception */ public function userGetsCapabilitiesCheckResponse(string $username):void { - $this->userGetsCapabilities($username, false); + $this->userGetsCapabilities($username); $statusCode = $this->featureContext->getResponse()->getStatusCode(); if ($statusCode !== 200) { throw new \Exception( diff --git a/tests/acceptance/features/bootstrap/AppManagementContext.php b/tests/acceptance/features/bootstrap/AppManagementContext.php index c04315da09a5..33615a55fddd 100644 --- a/tests/acceptance/features/bootstrap/AppManagementContext.php +++ b/tests/acceptance/features/bootstrap/AppManagementContext.php @@ -29,23 +29,16 @@ * Context for steps that test apps_paths. */ class AppManagementContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; private $oldAppsPaths; /** - * @var string stdout of last command + * stdout of last command */ - private $cmdOutput; + private string $cmdOutput; - /** - * @var array[] - */ - private $createdApps = []; + private array $createdApps = []; /** * @@ -283,9 +276,9 @@ public function adminListsTheAppsInMinimalFormat():void { * @throws Exception */ public function appWithVersionAndPathShouldHaveBeenListedInTheEnabledAppsSection( - $appId, - $appVersion, - $appPath + string $appId, + string $appVersion, + string $appPath ):void { $commandOutput = $this->featureContext->getStdOutOfOccCommand(); $expectedStartOfOutput = "Enabled:"; @@ -438,7 +431,7 @@ public function appPathIs(string $appId, string $dir):void { Assert::assertEquals( $this->featureContext->getServerRoot() . "/$dir/$appId", \trim($this->cmdOutput), - "Expected: the path to ${appId} should be ${dir} but got " + "Expected: the path to $appId should be $dir but got " . \trim($this->cmdOutput) ); } @@ -460,7 +453,7 @@ public function assertInstalledVersionOfAppIs(string $appId, string $version):vo Assert::assertEquals( $version, \trim($cmdOutput), - "Expected: the installed version of ${appId} should be ${version} but got " . \trim($cmdOutput) + "Expected: the installed version of $appId should be $version but got " . \trim($cmdOutput) ); } diff --git a/tests/acceptance/features/bootstrap/AuthContext.php b/tests/acceptance/features/bootstrap/AuthContext.php index 37ae48a100f5..6cd401ee49f1 100644 --- a/tests/acceptance/features/bootstrap/AuthContext.php +++ b/tests/acceptance/features/bootstrap/AuthContext.php @@ -29,35 +29,16 @@ * Authentication functions */ class AuthContext implements Context { - /** - * @var string - */ - private $clientToken; - - /** - * @var string - */ - private $appToken; - - /** - * @var array - */ - private $appTokens; + private string $clientToken; + private string $appToken; + private array $appTokens; + private bool $tokenAuthHasBeenSet = false; + private FeatureContext $featureContext; /** - * @var boolean + * 'true' or 'false' or '' */ - private $tokenAuthHasBeenSet = false; - - /** - * @var FeatureContext - */ - private $featureContext; - - /** - * @var string 'true' or 'false' or '' - */ - private $tokenAuthHasBeenSetTo = ''; + private string $tokenAuthHasBeenSetTo = ''; /** * @return string @@ -176,12 +157,12 @@ public function verifyStatusCode(string $ocsCode, string $httpCode, string $endP if ($ocsCode !== null) { $this->featureContext->ocsContext->theOCSStatusCodeShouldBe( $ocsCode, - $message = "Got unexpected OCS code while sending request to endpoint " . $endPoint + "Got unexpected OCS code while sending request to endpoint " . $endPoint ); } $this->featureContext->theHTTPStatusCodeShouldBe( $httpCode, - $message = "Got unexpected HTTP code while sending request to endpoint " . $endPoint + "Got unexpected HTTP code while sending request to endpoint " . $endPoint ); } @@ -1146,9 +1127,7 @@ public function deleteTokenAuthEnforcedAfterScenario():void { 'token_auth_enforced', $this->featureContext->getStepLineRef(), null, - $appTokenForOccCommand, - null, - null + $appTokenForOccCommand ); $this->tokenAuthHasBeenSet = false; $this->tokenAuthHasBeenSetTo = ''; diff --git a/tests/acceptance/features/bootstrap/CalDavContext.php b/tests/acceptance/features/bootstrap/CalDavContext.php index f264fe4bcc3c..1f95f7ba706a 100644 --- a/tests/acceptance/features/bootstrap/CalDavContext.php +++ b/tests/acceptance/features/bootstrap/CalDavContext.php @@ -19,6 +19,7 @@ * */ +use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; @@ -27,16 +28,9 @@ /** * CalDav functions */ -class CalDavContext implements \Behat\Behat\Context\Context { - /** - * @var ResponseInterface - */ - private $response; - - /** - * @var FeatureContext - */ - private $featureContext; +class CalDavContext implements Context { + private ResponseInterface $response; + private FeatureContext $featureContext; /** * @BeforeScenario @caldav diff --git a/tests/acceptance/features/bootstrap/CapabilitiesContext.php b/tests/acceptance/features/bootstrap/CapabilitiesContext.php index 6791fb85a6ce..2695fca43539 100644 --- a/tests/acceptance/features/bootstrap/CapabilitiesContext.php +++ b/tests/acceptance/features/bootstrap/CapabilitiesContext.php @@ -24,7 +24,6 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; -use Behat\Gherkin\Node\TableNode; use PHPUnit\Framework\Assert; require_once 'bootstrap.php'; @@ -33,11 +32,7 @@ * Capabilities context. */ class CapabilitiesContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @Then the major-minor-micro version data in the response should match the version string @@ -106,7 +101,7 @@ public function theCapabilityOfFilesSharingAppShouldBe( Assert::assertEquals( $value === "EMPTY" ? '' : $value, $actualValue, - "Expected {$pathToElement} capability of files sharing app to be {$value}, but got {$actualValue}" + "Expected $pathToElement capability of files sharing app to be $value, but got $actualValue" ); } diff --git a/tests/acceptance/features/bootstrap/CardDavContext.php b/tests/acceptance/features/bootstrap/CardDavContext.php index b5cad13ac838..3e778e6e8abe 100644 --- a/tests/acceptance/features/bootstrap/CardDavContext.php +++ b/tests/acceptance/features/bootstrap/CardDavContext.php @@ -19,6 +19,7 @@ * */ +use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; @@ -27,16 +28,9 @@ /** * CardDav functions */ -class CardDavContext implements \Behat\Behat\Context\Context { - /** - * @var ResponseInterface - */ - private $response; - - /** - * @var FeatureContext - */ - private $featureContext; +class CardDavContext implements Context { + private ResponseInterface $response; + private FeatureContext $featureContext; /** * @BeforeScenario @carddav @@ -208,9 +202,9 @@ public function theAdministratorHasSuccessfullyCreatedAnAddressBookNamed(string public function theCardDavHttpStatusCodeShouldBe(int $code):void { $actualStatusCode = $this->response->getStatusCode(); Assert::assertEquals( - (int) $code, + $code, $actualStatusCode, - "Expected: HTTP status code to be {$code} but got {$actualStatusCode}" + "Expected: HTTP status code to be $code but got $actualStatusCode" ); } } diff --git a/tests/acceptance/features/bootstrap/ChecksumContext.php b/tests/acceptance/features/bootstrap/ChecksumContext.php index cc7d528279e5..17f8496b0706 100644 --- a/tests/acceptance/features/bootstrap/ChecksumContext.php +++ b/tests/acceptance/features/bootstrap/ChecksumContext.php @@ -30,11 +30,7 @@ * Checksum functions */ class ChecksumContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @When user :user uploads file :source to :destination with checksum :checksum using the WebDAV API @@ -60,8 +56,7 @@ public function userUploadsFileToWithChecksumUsingTheAPI( 'PUT', $destination, ['OC-Checksum' => $checksum], - $file, - "files" + $file ); $this->featureContext->setResponse($response); } @@ -113,8 +108,7 @@ public function userUploadsFileWithContentAndChecksumToUsingTheAPI( 'PUT', $destination, ['OC-Checksum' => $checksum], - $content, - "files" + $content ); $this->featureContext->setResponse($response); } @@ -267,7 +261,7 @@ public function theWebdavChecksumShouldMatch(string $expectedChecksum):void { Assert::assertEquals( $expectedChecksum, $actualChecksum, - "Expected: webDav checksum should be {$expectedChecksum} but got {$actualChecksum}" + "Expected: webDav checksum should be $expectedChecksum but got $actualChecksum" ); } @@ -321,7 +315,7 @@ public function theHeaderChecksumShouldMatch(string $expectedChecksum):void { Assert::assertEquals( $expectedChecksum, $headerChecksum, - "Expected: header checksum should match {$expectedChecksum} but got {$headerChecksum}" + "Expected: header checksum should match $expectedChecksum but got $headerChecksum" ); } @@ -361,7 +355,7 @@ public function theWebdavChecksumShouldBeEmpty():void { Assert::assertEquals( $expectedStatus, $status, - "Expected status to be {$expectedStatus} but got {$status}" + "Expected status to be $expectedStatus but got $status" ); } @@ -408,8 +402,7 @@ public function userUploadsChunkFileOfWithToWithChecksum( 'PUT', $file, ['OC-Checksum' => $expectedChecksum, 'OC-Chunked' => '1'], - $data, - "files" + $data ); $this->featureContext->setResponse($response); } diff --git a/tests/acceptance/features/bootstrap/CommentsContext.php b/tests/acceptance/features/bootstrap/CommentsContext.php index 4675b9aa22f7..8b65e87d7bef 100644 --- a/tests/acceptance/features/bootstrap/CommentsContext.php +++ b/tests/acceptance/features/bootstrap/CommentsContext.php @@ -33,20 +33,9 @@ * Comments functions */ class CommentsContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * @var int - */ - private $lastCommentId; - /** - * @var int - */ - private $lastFileId; + private FeatureContext $featureContext; + private int $lastCommentId; + private int $lastFileId; /** * @When /^user "([^"]*)" comments with content "([^"]*)" on (?:file|folder) "([^"]*)" using the WebDAV API$/ @@ -60,7 +49,7 @@ class CommentsContext implements Context { public function userCommentsWithContentOnEntry(string $user, string $content, string $path):void { $user = $this->featureContext->getActualUsername($user); $fileId = $this->featureContext->getFileIdForPath($user, $path); - $this->lastFileId = $fileId; + $this->lastFileId = (int) $fileId; $commentsPath = "/comments/files/$fileId/"; $response = $this->featureContext->makeDavRequest( $user, @@ -76,7 +65,7 @@ public function userCommentsWithContentOnEntry(string $user, string $content, st $responseHeaders = $response->getHeaders(); if (isset($responseHeaders['Content-Location'][0])) { $commentUrl = $responseHeaders['Content-Location'][0]; - $this->lastCommentId = \substr( + $this->lastCommentId = (int) \substr( $commentUrl, \strrpos($commentUrl, '/') + 1 ); @@ -215,7 +204,7 @@ public function checkNumberOfComments(string $user, string $numberOfComments, st Assert::assertCount( (int) $numberOfComments, $messages, - "Expected: {$user} should have {$numberOfComments} on {$path} but got " + "Expected: $user should have $numberOfComments on $path but got " . \count($messages) ); } @@ -308,7 +297,7 @@ public function theResponseShouldContainAPropertyWithValue(string $key, string $ } Assert::assertTrue( $found, - "The response does not contain a property {$key} with value {$value}" + "The response does not contain a property $key with value $value" ); } @@ -323,9 +312,9 @@ public function theResponseShouldContainAPropertyWithValue(string $key, string $ public function theResponseShouldContainOnlyComments(int $number):void { $response = $this->featureContext->getResponse(); Assert::assertEquals( - (int) $number, + $number, \count($response), - "Expected: the response should contain {$number} comments but got " + "Expected: the response should contain $number comments but got " . \count($response) ); } diff --git a/tests/acceptance/features/bootstrap/CorsContext.php b/tests/acceptance/features/bootstrap/CorsContext.php index 4610d5cdc493..0f394744f623 100644 --- a/tests/acceptance/features/bootstrap/CorsContext.php +++ b/tests/acceptance/features/bootstrap/CorsContext.php @@ -30,13 +30,9 @@ * Steps that relate to CORS tests */ class CorsContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; - private $originalAdminCorsDomains = null; + private ?string $originalAdminCorsDomains = null; /** * @Given user :user has added :domain to the list of personal CORS domains diff --git a/tests/acceptance/features/bootstrap/EmailContext.php b/tests/acceptance/features/bootstrap/EmailContext.php index d8f9e3228237..05f46d7f3624 100644 --- a/tests/acceptance/features/bootstrap/EmailContext.php +++ b/tests/acceptance/features/bootstrap/EmailContext.php @@ -32,13 +32,8 @@ * context file for email related steps. */ class EmailContext implements Context { - private $localInbucketUrl = null; - - /** - * - * @var FeatureContext - */ - private $featureContext; + private ?string $localInbucketUrl = null; + private FeatureContext $featureContext; /** * @return string @@ -66,8 +61,7 @@ public function assertThatEmailContains(string $address, PyStringNode $content, Assert::assertStringContainsString( $expectedContent, $emailBody, - "The email address {$address} should have received an email with the body containing {$expectedContent} - but the received email is {$emailBody}" + "The email address $address should have received an email with the body containing $expectedContent but the received email is $emailBody" ); } @@ -134,7 +128,7 @@ public function theResetEmailSenderEmailAddressShouldBe(string $user, string $se Assert::assertStringContainsString( $senderAddress, $actualSenderAddress, - "The sender address is expected to be {$senderAddress} but the actual sender is {$actualSenderAddress}" + "The sender address is expected to be $senderAddress but the actual sender is $actualSenderAddress" ); } @@ -153,7 +147,7 @@ public function assertThatEmailDoesntExistWithTheAddress(string $address):void { $address, $this->featureContext->getStepLineRef(), ), - "Email exists with email address: {$address} but was not expected to be." + "Email exists with email address: $address but was not expected to be." ); } @@ -182,11 +176,11 @@ public function setUpScenario(BeforeScenarioScope $scope):void { public function clearInbucketMessages():void { try { if (!empty($this->featureContext->emailRecipients)) { - foreach ($this->featureContext->emailRecipients as $emailRecipent) { + foreach ($this->featureContext->emailRecipients as $emailRecipient) { EmailHelper::deleteAllEmailsForAMailbox( $this->getLocalInbucketUrl(), $this->featureContext->getStepLineRef(), - $emailRecipent + $emailRecipient ); } } diff --git a/tests/acceptance/features/bootstrap/EncryptionContext.php b/tests/acceptance/features/bootstrap/EncryptionContext.php index 5db306bc282f..5fa6f7227504 100644 --- a/tests/acceptance/features/bootstrap/EncryptionContext.php +++ b/tests/acceptance/features/bootstrap/EncryptionContext.php @@ -5,10 +5,10 @@ * @author Artur Neumann * @copyright Copyright (c) 2018 Artur Neumann info@jankaritech.com * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, + * as published by the Free Software Foundation; + * either version 3 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,15 +32,8 @@ * Context for encryption specific steps */ class EncryptionContext implements Context { - /** - * @var FeatureContext - */ - private $featureContext; - - /** - * @var OccContext - */ - private $occContext; + private FeatureContext $featureContext; + private OccContext $occContext; /** * @return void @@ -162,7 +155,7 @@ public function fileOfUserShouldNotBeEncrypted(string $fileName, string $usernam Assert::assertEquals( $fileContentServer, $fileContent, - "The content of file {$fileName} is {$fileContent}, but was supposed to be non-encrypted: {$fileContentServer}" + "The content of file $fileName is $fileContent, but was supposed to be non-encrypted: $fileContentServer" ); } @@ -180,7 +173,6 @@ public function fileOfUserShouldBeEncrypted(string $fileName, string $username): $filePath = "data/$username/files/$fileName"; $this->featureContext->readFileInServerRootForCore($filePath); - $response = $this->featureContext->getResponse(); $parsedResponse = HttpRequestHelper::getResponseXml( $this->featureContext->getResponse(), __METHOD__ @@ -192,7 +184,7 @@ public function fileOfUserShouldBeEncrypted(string $fileName, string $username): Assert::assertStringStartsWith( $expectedContentStart, $fileContent, - "FileContent: {$fileContent} of file {$fileName} is expected to start with encrypted string {$expectedContentStart}, but does not" + "FileContent: $fileContent of file $fileName is expected to start with encrypted string $expectedContentStart, but does not" ); } diff --git a/tests/acceptance/features/bootstrap/FavoritesContext.php b/tests/acceptance/features/bootstrap/FavoritesContext.php index 1164dc26a8a3..80eeb7b061af 100644 --- a/tests/acceptance/features/bootstrap/FavoritesContext.php +++ b/tests/acceptance/features/bootstrap/FavoritesContext.php @@ -32,17 +32,8 @@ * context containing favorites related API steps */ class FavoritesContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebDavPropertiesContext - */ - private $webDavPropertiesContext; + private FeatureContext $featureContext; + private WebDavPropertiesContext $webDavPropertiesContext; /** * @param string$user @@ -117,8 +108,8 @@ public function theUserHasFavoritedElement(string $path):void { } /** - * @param $user - * @param $path + * @param string $user + * @param string $path * * @return void */ @@ -171,7 +162,7 @@ public function checkFavoritedElements( TableNode $expectedElements ):void { $user = $this->featureContext->getActualUsername($user); - $this->userListsFavorites($user, null); + $this->userListsFavorites($user); $this->featureContext->propfindResultShouldContainEntries( $shouldOrNot, $expectedElements, diff --git a/tests/acceptance/features/bootstrap/FeatureContext.php b/tests/acceptance/features/bootstrap/FeatureContext.php index a11b05808d20..da25d3be2584 100644 --- a/tests/acceptance/features/bootstrap/FeatureContext.php +++ b/tests/acceptance/features/bootstrap/FeatureContext.php @@ -51,34 +51,14 @@ class FeatureContext extends BehatVariablesContext { use WebDav; /** - * @var int Unix timestamp seconds + * Unix timestamp seconds */ - private $scenarioStartTime; - - /** - * @var string - */ - private $adminUsername = ''; - - /** - * @var string - */ - private $adminPassword = ''; - - /** - * @var string - */ - private $adminDisplayName = ''; - - /** - * @var string - */ - private $adminEmailAddress = ''; - - /** - * @var string - */ - private $originalAdminPassword = ''; + private int $scenarioStartTime; + private string $adminUsername = ''; + private string $adminPassword = ''; + private string $adminDisplayName = ''; + private string $adminEmailAddress = ''; + private string $originalAdminPassword = ''; /** * An array of values of replacement values of user attributes. @@ -86,258 +66,131 @@ class FeatureContext extends BehatVariablesContext { * run-time values are maintained and referenced in the $createdUsers array. * * Key is the username, value is an array of user attributes - * - * @var array|null */ - private $userReplacements = null; - - /** - * @var string - */ - private $regularUserPassword = ''; - - /** - * @var string - */ - private $alt1UserPassword = ''; - - /** - * @var string - */ - private $alt2UserPassword = ''; - - /** - * @var string - */ - private $alt3UserPassword = ''; - - /** - * @var string - */ - private $alt4UserPassword = ''; + private ?array $userReplacements = null; + private string $regularUserPassword = ''; + private string $alt1UserPassword = ''; + private string $alt2UserPassword = ''; + private string $alt3UserPassword = ''; + private string $alt4UserPassword = ''; /** * The password to use in tests that create a sub-admin user - * - * @var string */ - private $subAdminPassword = ''; + private string $subAdminPassword = ''; /** * The password to use in tests that create another admin user - * - * @var string */ - private $alternateAdminPassword = ''; + private string $alternateAdminPassword = ''; /** * The password to use in tests that create public link shares - * - * @var string - */ - private $publicLinkSharePassword = ''; - - /** - * @var string - */ - private $ocPath = ''; - - /** - * @var string location of the root folder of ownCloud on the local server under test */ - private $localServerRoot = null; + private string $publicLinkSharePassword = ''; + private string $ocPath = ''; /** - * @var string + * Location of the root folder of ownCloud on the local server under test */ - private $currentUser = ''; - - /** - * @var string - */ - private $currentServer = ''; + private ?string $localServerRoot = null; + private string $currentUser = ''; + private string $currentServer = ''; /** * The base URL of the current server under test, * without any terminating slash * e.g. http://localhost:8080 - * - * @var string */ - private $baseUrl = ''; + private string $baseUrl = ''; /** * The base URL of the local server under test, * without any terminating slash * e.g. http://localhost:8080 - * - * @var string */ - private $localBaseUrl = ''; + private string $localBaseUrl = ''; /** * The base URL of the remote (federated) server under test, * without any terminating slash * e.g. http://localhost:8180 - * - * @var string */ - private $remoteBaseUrl = ''; + private string $remoteBaseUrl = ''; /** * The suite name, feature name and scenario line number. * Example: apiComments/createComments.feature:24 - * - * @var string */ - private $scenarioString = ''; + private string $scenarioString = ''; /** * A full unique reference to the step that is currently executing. * Example: apiComments/createComments.feature:24-28 * That is line 28, in the scenario at line 24, in the createComments feature * in the apiComments suite. - * - * @var string */ - private $stepLineRef = ''; + private string $stepLineRef = ''; + private bool $sendStepLineRef = false; + private bool $sendStepLineRefHasBeenChecked = false; /** - * @var bool|null - */ - private $sendStepLineRef = null; - - /** - * - * * @var boolean true if TEST_SERVER_FED_URL is defined */ - private $federatedServerExists = false; - - /** - * @var int - */ - private $ocsApiVersion = 1; - - /** - * @var ResponseInterface - */ - private $response = null; - - /** - * @var string - */ - private $responseUser = ""; - - /** - * @var string - */ - private $responseBodyContent = null; - - /** - * @var array - */ - private $userResponseBodyContents = []; - - /** - * @var array - */ - public $emailRecipients = []; - - /** - * @var CookieJar - */ - private $cookieJar; - - /** - * @var string - */ - private $requestToken; - - /** - * @var array - */ - private $storageIds = []; - - /** - * @var array - */ - private $createdFiles = []; + private bool $federatedServerExists; + private int $ocsApiVersion = 1; + private ?ResponseInterface $response = null; + private string $responseUser = ''; + private ?string $responseBodyContent = null; + private array $userResponseBodyContents = []; + public array $emailRecipients = []; + private CookieJar $cookieJar; + private string $requestToken; + private array $storageIds = []; + private array $createdFiles = []; /** * The local source IP address from which to initiate API actions. * Defaults to system-selected address matching IP address family and scope. - * - * @var string|null - */ - private $sourceIpAddress = null; - - private $guzzleClientHeaders = []; - - /** - * - * @var OCSContext - */ - public $ocsContext; - - /** - * - * @var AuthContext - */ - public $authContext; - - /** - * - * @var GraphContext */ - public $graphContext; + private ?string $sourceIpAddress = null; + private array $guzzleClientHeaders = []; + public OCSContext $ocsContext; + public AuthContext $authContext; + public AppConfigurationContext $appConfigurationContext; /** - * - * @var AppConfigurationContext + * Saved configuration of the system before test runs as reported + * by occ config:list */ - public $appConfigurationContext; + private array $savedConfigList = []; + private array $initialTrustedServer; /** - * @var array saved configuration of the system before test runs as reported - * by occ config:list + * return code of last command */ - private $savedConfigList = []; - + private ?int $occLastCode = null; /** - * @var array + * stdout of last command */ - private $initialTrustedServer; - + private string $lastStdOut; /** - * @var int return code of last command + * stderr of last command */ - private $occLastCode; - /** - * @var string stdout of last command - */ - private $lastStdOut; - /** - * @var string stderr of last command - */ - private $lastStdErr; + private string $lastStdErr; /** * The codes are stored as strings, even though they are numbers - * - * @var array last http status codes */ - private $lastHttpStatusCodesArray = []; + private array $lastHttpStatusCodesArray = []; /** - * @var array last ocs status codes + * last ocs status codes */ - private $lastOCSStatusCodesArray = []; + private array $lastOCSStatusCodesArray = []; /** - * @var bool - * * this is set true for db conversion tests */ - private $dbConversion = false; + private bool $dbConversion = false; /** * @param bool $value @@ -355,10 +208,7 @@ public function isRunningForDbConversion():bool { return $this->dbConversion; } - /** - * @var string - */ - private $oCSelector; + private string $oCSelector; /** * @param string $selector @@ -384,7 +234,7 @@ public function resetOccLastCode():void { } /** - * @param int $statusCode + * @param int|null $statusCode * * @return void */ @@ -505,18 +355,12 @@ public function pushEmailRecipientAsMailBox(string $emailAddress):void { * @var string */ private $ldapGroupSchema; - /** - * @var bool - */ - private $skipImportLdif; - /** - * @var array - */ - private $toDeleteDNs = []; - private $ldapCreatedUsers = []; - private $ldapCreatedGroups = []; - private $toDeleteLdapConfigs = []; - private $oldLdapConfig = []; + private bool $skipImportLdif = false; + private array $toDeleteDNs = []; + private array $ldapCreatedUsers = []; + private array $ldapCreatedGroups = []; + private array $toDeleteLdapConfigs = []; + private array $oldLdapConfig = []; /** * @return Ldap @@ -621,8 +465,9 @@ public function isTestingWithLdap():bool { * @return bool */ public function sendScenarioLineReferencesInXRequestId():?bool { - if ($this->sendStepLineRef === null) { + if ($this->sendStepLineRefHasBeenChecked === false) { $this->sendStepLineRef = (\getenv("SEND_SCENARIO_LINE_REFERENCES") === "true"); + $this->sendStepLineRefHasBeenChecked = true; } return $this->sendStepLineRef; } @@ -3050,7 +2895,7 @@ public function getVersionStringFromStatus():?string { } /** - * returns a string that can be used to check a url of comments with + * returns a string that can be used to check a URL of comments with * regular expression (without delimiter) * * @return string @@ -4134,8 +3979,7 @@ public function runOccWithEnvVariables( ); $this->lastStdOut = $return['stdOut']; $this->lastStdErr = $return['stdErr']; - $occStatusCode = (int) $return['code']; - return $occStatusCode; + return (int) $return['code']; } /** diff --git a/tests/acceptance/features/bootstrap/FederationContext.php b/tests/acceptance/features/bootstrap/FederationContext.php index aedeab35f590..e4b11c6fe98c 100644 --- a/tests/acceptance/features/bootstrap/FederationContext.php +++ b/tests/acceptance/features/bootstrap/FederationContext.php @@ -33,17 +33,8 @@ * Federation context. */ class FederationContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OCSContext - */ - private $ocsContext; + private FeatureContext $featureContext; + private OCSContext $ocsContext; /** * @When /^user "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with user "([^"]*)" from server "(LOCAL|REMOTE)" using the sharing API$/ @@ -254,8 +245,7 @@ public function userFromServerAcceptsLastPendingShareUsingTheSharingAPI(string $ $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'POST', - "/apps/files_sharing/api/v1/remote_shares/pending/{$share_id}", - null + "/apps/files_sharing/api/v1/remote_shares/pending/$share_id" ); $this->featureContext->pushToLastStatusCodesArrays(); $this->featureContext->usingServer($previous); @@ -296,8 +286,7 @@ public function userRetrievesInformationOfLastFederatedShare(string $user):void $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - "/apps/files_sharing/api/v1/remote_shares/{$share_id}", - null + "/apps/files_sharing/api/v1/remote_shares/$share_id" ); } @@ -337,8 +326,7 @@ public function userRetrievesInformationOfLastPendingFederatedShare(string $user $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - "/apps/files_sharing/api/v1/remote_shares/{$share_id}", - null + "/apps/files_sharing/api/v1/remote_shares/$share_id" ); } @@ -356,8 +344,7 @@ public function userGetsTheListOfPendingFederatedCloudShares(string $user):void $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - $url, - null + $url ); } @@ -428,8 +415,7 @@ public function userRequestsSharedSecretUsingTheFederationApi(string $user):void $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'POST', - $url, - null + $url ); } diff --git a/tests/acceptance/features/bootstrap/FilesVersionsContext.php b/tests/acceptance/features/bootstrap/FilesVersionsContext.php index eaea0ad0a9ca..0f8836c9334e 100644 --- a/tests/acceptance/features/bootstrap/FilesVersionsContext.php +++ b/tests/acceptance/features/bootstrap/FilesVersionsContext.php @@ -33,11 +33,7 @@ * Steps that relate to files_versions app */ class FilesVersionsContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @param string $fileId @@ -243,13 +239,13 @@ public function theContentLengthOfFileForUserInVersionsFolderIs( Assert::assertEquals( $length, (int) $xmlPart[$index], - "The content length of file {$path} with version {$index} for user {$user} was - expected to be {$length} but the actual content length is {$xmlPart[$index]}" + "The content length of file $path with version $index for user $user was + expected to be $length but the actual content length is $xmlPart[$index]" ); } /** - * @Then /^as (?:users|user) "([^"]*)" the authors of the noncurrent versions of file "([^"]*)" should be:$/ + * @Then /^as (?:users|user) "([^"]*)" the authors of the non-current versions of file "([^"]*)" should be:$/ * * @param string $users comma-separated list of usernames * @param string $filename @@ -258,7 +254,7 @@ public function theContentLengthOfFileForUserInVersionsFolderIs( * @return void * @throws Exception */ - public function asUsersAuthorsOfNoncurrentVersionsOfFileShouldBe( + public function asUsersAuthorsOfNonCurrentVersionsOfFileShouldBe( string $users, string $filename, TableNode $table @@ -317,7 +313,7 @@ public function downloadVersion(string $user, string $path, string $index):void } /** - * @Then /^the content of noncurrent version index "([^"]*)" of file "([^"]*)" for user "([^"]*)" should be "([^"]*)"$/ + * @Then /^the content of non-current version index "([^"]*)" of file "([^"]*)" for user "([^"]*)" should be "([^"]*)"$/ * * @param string $index * @param string $path @@ -327,7 +323,7 @@ public function downloadVersion(string $user, string $path, string $index):void * @return void * @throws Exception */ - public function theContentOfNoncurrentVersionIndexOfFileForUserShouldBe( + public function theContentOfNonCurrentVersionIndexOfFileForUserShouldBe( string $index, string $path, string $user, @@ -388,7 +384,7 @@ public function userGetMetaInfo(string $user, string $fileOrFileId, string $path /** * returns the result parsed into an SimpleXMLElement - * with an registered namespace with 'd' as prefix and 'DAV:' as namespace + * with a registered namespace with 'd' as prefix and 'DAV:' as namespace * * @param string $user * @param string $fileId diff --git a/tests/acceptance/features/bootstrap/IpContext.php b/tests/acceptance/features/bootstrap/IpContext.php index 617f8d237d7c..c212402f293d 100644 --- a/tests/acceptance/features/bootstrap/IpContext.php +++ b/tests/acceptance/features/bootstrap/IpContext.php @@ -28,32 +28,24 @@ * Ip trait */ class IpContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * The local source IP address from which to initiate API actions. * Defaults to system-selected address matching IP address family and scope. - * - * @var string|null */ - private $sourceIpAddress = null; + private ?string $sourceIpAddress = null; /** * The base URL parameter to use with the source IP address. * Accesses the server on IPv4 or IPv6 matching the source IP. - * - * @var string */ - private $baseUrlForSourceIp = null; + private ?string $baseUrlForSourceIp = null; - private $ipv4Url; - private $ipv6Url; + private string $ipv4Url; + private string $ipv6Url; - private $guzzleClientHeaders = []; + private array $guzzleClientHeaders = []; /** * @return string|null @@ -69,7 +61,7 @@ public function getSourceIpAddress():?string { * @return string */ public function getBaseUrlForSourceIp():string { - // Lazy init so we know that featureContext has been setup + // Lazy init so we know that featureContext has been set up // by the time we need it here. if ($this->baseUrlForSourceIp === null) { $this->baseUrlForSourceIp = $this->featureContext->getBaseUrl(); diff --git a/tests/acceptance/features/bootstrap/LoggingContext.php b/tests/acceptance/features/bootstrap/LoggingContext.php index 4332f52ee1b3..994403efa69c 100644 --- a/tests/acceptance/features/bootstrap/LoggingContext.php +++ b/tests/acceptance/features/bootstrap/LoggingContext.php @@ -33,15 +33,12 @@ * Context to make the Logging steps available */ class LoggingContext implements Context { - /** - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; - private $oldLogLevel = null; - private $logLevel = null; - private $oldLogBackend = null; - private $oldLogTimezone = null; + private ?string $oldLogLevel = null; + private ?string $logLevel = null; + private ?string $oldLogBackend = null; + private ?string $oldLogTimezone = null; /** * checks for specific rows in the log file. @@ -68,7 +65,7 @@ public function theLastLinesOfTheLogFileShouldContainEntriesWithTheseAttributes( if ($this->logLevel === "info") { $ignoredLines = 1; } - $ignoredLines = (int) $ignoredLines; + $ignoredLines = $ignoredLines; //-1 because getRows gives also the header $linesToRead = \count($expectedLogEntries->getRows()) - 1 + $ignoredLines; $logLines = LoggingHelper::getLogFileContent( @@ -82,7 +79,7 @@ public function theLastLinesOfTheLogFileShouldContainEntriesWithTheseAttributes( foreach ($expectedLogEntries as $expectedLogEntry) { $logEntry = \json_decode($logLines[$lineNo], true); if ($logEntry === null) { - throw new Exception("the log line :\n{$logLines[$lineNo]} is not valid JSON"); + throw new Exception("the log line :\n$logLines[$lineNo] is not valid JSON"); } foreach (\array_keys($expectedLogEntry) as $attribute) { @@ -104,9 +101,9 @@ public function theLastLinesOfTheLogFileShouldContainEntriesWithTheseAttributes( Assert::assertArrayHasKey( $attribute, $logEntry, - "could not find attribute: '$attribute' in log entry: '{$logLines[$lineNo]}'" + "could not find attribute: '$attribute' in log entry: '$logLines[$lineNo]'" ); - $message = "log entry:\n{$logLines[$lineNo]}\n"; + $message = "log entry:\n$logLines[$lineNo]\n"; if (!\is_string($logEntry[$attribute])) { $logEntry[$attribute] = \json_encode( $logEntry[$attribute], @@ -287,7 +284,7 @@ private function assertLogFileContainsAtLeastOneEntryMatchingTable( foreach ($logLines as $logLine) { $logEntry = \json_decode($logLine, true); if ($logEntry === null) { - throw new Exception("the log line :\n{$logLine} is not valid JSON"); + throw new Exception("the log line :\n$logLine is not valid JSON"); } //reindex the array, we might have deleted entries $expectedLogEntries = \array_values($expectedLogEntries); @@ -335,7 +332,7 @@ private function assertLogFileContainsAtLeastOneEntryMatchingTable( $foundLine = false; break; } - if ($matchAttribute and !$shouldOrNot) { + if (!$shouldOrNot) { $count += 1; Assert::assertNotEquals( $count, @@ -359,9 +356,9 @@ private function assertLogFileContainsAtLeastOneEntryMatchingTable( } /** - * fails if there is at least one line in the log file that matches all - * given attributes - * attributes in the table that are empty will match any value in the + * Fails if there is at least one line in the log file that matches all + * given attributes. + * Attributes in the table that are empty will match any value in the * corresponding attribute in the log file * * @Then /^the log file should not contain any log-entries (with|containing) these attributes:$/ @@ -377,7 +374,7 @@ private function assertLogFileContainsAtLeastOneEntryMatchingTable( * @throws Exception */ public function theLogFileShouldNotContainAnyLogEntriesWithTheseAttributes( - $withOrContaining, + string $withOrContaining, TableNode $logEntriesExpectedNotToExist ):void { $logLines = LoggingHelper::getLogFileContent( @@ -413,11 +410,11 @@ public function theLogFileShouldNotContainAnyLogEntriesWithTheseAttributes( break; } } + Assert::assertFalse( + $match, + "found a log entry that should not be there\n$logLine\n" + ); } - Assert::assertFalse( - $match, - "found a log entry that should not be there\n$logLine\n" - ); } } @@ -458,7 +455,7 @@ public function owncloudLogLevelHasBeenSetTo(string $logLevel):void { Assert::assertEquals( $logLevelExpected, $logLevelActual, - "The expected log level is {$logLevelExpected} but the log level has been set to {$logLevelActual}" + "The expected log level is $logLevelExpected but the log level has been set to $logLevelActual" ); } @@ -493,7 +490,7 @@ public function owncloudLogBackendHasBeenSetTo(string $expectedBackend):void { Assert::assertEquals( $expectedBackend, $currentBackend, - "The owncloud log backend was expected to be set to {$expectedBackend} but got {$currentBackend}" + "The owncloud log backend was expected to be set to $expectedBackend but got $currentBackend" ); } @@ -528,7 +525,7 @@ public function owncloudLogTimezoneHasBeenSetTo(string $expectedTimezone):void { Assert::assertEquals( $expectedTimezone, $currentTimezone, - "The owncloud log timezone was expected to be set to {$expectedTimezone}, but got {$currentTimezone}" + "The owncloud log timezone was expected to be set to $expectedTimezone, but got $currentTimezone" ); } diff --git a/tests/acceptance/features/bootstrap/NotificationsCoreContext.php b/tests/acceptance/features/bootstrap/NotificationsCoreContext.php index 0e1770dba092..68746b2470e7 100644 --- a/tests/acceptance/features/bootstrap/NotificationsCoreContext.php +++ b/tests/acceptance/features/bootstrap/NotificationsCoreContext.php @@ -33,26 +33,10 @@ * Defines application features from the specific context. */ class NotificationsCoreContext implements Context { - /** - * @var array[] - */ - protected $notificationIds; - - /** - * @var int - */ - protected $deletedNotification; - - /** - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OCSContext - */ - private $ocsContext; + protected array $notificationIds; + protected int $deletedNotification; + private FeatureContext $featureContext; + private OCSContext $ocsContext; /** * @return array[] @@ -96,10 +80,10 @@ public function checkNumNotifications(int $numNotifications):void { $this->featureContext->getResponse() ); Assert::assertCount( - (int) $numNotifications, + $numNotifications, $notifications, "Expected notifications count to have '" - . (int) $numNotifications + . $numNotifications . "' entries but got '" . \count($notifications) . "' entries" @@ -142,7 +126,7 @@ public function userNumNotifications(string $user, int $numNotifications, string if ($missingLast) { Assert::assertNotEmpty( $this->getNotificationIds(), - "The notifications is empty, but was not expected to be empty when step is used '{$missingLast}'" + "The notifications is empty, but was not expected to be empty when step is used '$missingLast'" ); $previousNotificationIds = $this->getLastNotificationIds(); } @@ -160,7 +144,7 @@ public function userNumNotifications(string $user, int $numNotifications, string Assert::assertEquals( $previousNotificationIds, $now, - "The actual notifications, {$missingLast}, are not what was expected. {$numNotifications} were expected.See the differences below." + "The actual notifications, $missingLast, are not what was expected. $numNotifications were expected.See the differences below." ); } } @@ -278,7 +262,7 @@ public function matchNotification( Assert::assertEquals( $value, $response['ocs']['data'][$notification['key']], - "Expected {$value} but got {$response['ocs']['data'][$notification['key']]}" + "Expected $value but got {$response['ocs']['data'][$notification['key']]}" ); } } diff --git a/tests/acceptance/features/bootstrap/OCSContext.php b/tests/acceptance/features/bootstrap/OCSContext.php index 1554b3935a8d..050b00114b94 100644 --- a/tests/acceptance/features/bootstrap/OCSContext.php +++ b/tests/acceptance/features/bootstrap/OCSContext.php @@ -35,11 +35,7 @@ * steps needed to send requests to the OCS API */ class OCSContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @When /^the user sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)"$/ @@ -50,7 +46,7 @@ class OCSContext implements Context { * @return void */ public function theUserSendsToOcsApiEndpoint(string $verb, string $url):void { - $this->theUserSendsToOcsApiEndpointWithBody($verb, $url, null); + $this->theUserSendsToOcsApiEndpointWithBody($verb, $url); } /** @@ -62,7 +58,7 @@ public function theUserSendsToOcsApiEndpoint(string $verb, string $url):void { * @return void */ public function theUserHasSentToOcsApiEndpoint(string $verb, string $url):void { - $this->theUserSendsToOcsApiEndpointWithBody($verb, $url, null); + $this->theUserSendsToOcsApiEndpointWithBody($verb, $url); $this->featureContext->theHTTPStatusCodeShouldBeSuccess(); } @@ -129,8 +125,6 @@ public function userSendsHTTPMethodToOcsApiEndpointWithBody( /** * array of the data to be sent in the body. * contains $body data converted to an array - * - * @var array $bodyArray */ $bodyArray = []; if ($body instanceof TableNode) { @@ -233,7 +227,7 @@ public function userSendHTTPMethodToOcsApiEndpointWithBody( * @param string $verb * @param string $url * @param TableNode|null $body - * @param string $password + * @param string|null $password * * @return void */ @@ -793,7 +787,7 @@ public function userRequestsTheseEndpointsWithoutBodyUsingThePasswordOfUser(stri * @return void * @throws Exception */ - public function theOCSStatusCodeShouldBe(string $statusCode, $message = ""):void { + public function theOCSStatusCodeShouldBe(string $statusCode, string $message = ""):void { $statusCodes = explode(",", $statusCode); $responseStatusCode = $this->getOCSResponseStatusCode( $this->featureContext->getResponse() @@ -936,7 +930,7 @@ public function getOCSResponseStatusCode(ResponseInterface $response):string { if (\is_object($jsonResponse) && $jsonResponse->ocs->meta->statuscode) { return (string) $jsonResponse->ocs->meta->statuscode; } - // go to xml response when json response is null (it means not formated and get status code) + // go to xml response when json response is null (it means not formatted and get status code) $responseXml = $this->featureContext->getResponseXml($response, __METHOD__); if (isset($responseXml->meta[0], $responseXml->meta[0]->statuscode)) { return (string) $responseXml->meta[0]->statuscode; diff --git a/tests/acceptance/features/bootstrap/OccAppManagementContext.php b/tests/acceptance/features/bootstrap/OccAppManagementContext.php index 696a3da57355..7258482cb0a9 100644 --- a/tests/acceptance/features/bootstrap/OccAppManagementContext.php +++ b/tests/acceptance/features/bootstrap/OccAppManagementContext.php @@ -31,17 +31,8 @@ * Occ context for test steps that test occ commands */ class OccAppManagementContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OccContext - */ - private $occContext; + private FeatureContext $featureContext; + private OccContext $occContext; /** * @When the administrator disables app :appName using the occ command @@ -124,7 +115,7 @@ public function theAppNameReturnedByTheOccCommandShouldBe(string $appName):void Assert::assertEquals( $appName, \key($lastOutputArray['apps']), - "The app name expected to be returned by the occ command is {$appName} but got " + "The app name expected to be returned by the occ command is $appName but got " . \key($lastOutputArray['apps']) ); } @@ -145,7 +136,7 @@ public function thePathReturnedByTheOccCommandShouldBeInsideOneOfTheAppsPathInTh $configOutputArray = \json_decode($lastOutput, true); // Default apps location is '${INSTALLED_LOCATION}/apps/${appName} - if (\substr_compare($appPath, '/apps/${appName}', 0)) { + if (\substr_compare($appPath, "/apps/$appName", 0)) { return; } @@ -179,7 +170,7 @@ public function theAppEnabledStatusShouldBe(string $appName, string $appStatus): Assert::assertEquals( $appStatus, $actualAppEnabledStatus, - "The app enabled status of app {$appName} was expected to be {$appStatus}, but the actual status is {$actualAppEnabledStatus}" + "The app enabled status of app $appName was expected to be $appStatus, but the actual status is $actualAppEnabledStatus" ); } diff --git a/tests/acceptance/features/bootstrap/OccContext.php b/tests/acceptance/features/bootstrap/OccContext.php index 596c9a506c7f..7b9aa8f6519b 100644 --- a/tests/acceptance/features/bootstrap/OccContext.php +++ b/tests/acceptance/features/bootstrap/OccContext.php @@ -34,11 +34,7 @@ * Occ context for test steps that test occ commands */ class OccContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @@ -52,30 +48,17 @@ class OccContext implements Context { */ private $removedCertificates = []; - /** - * @var string lastDeletedJobId - */ - private $lastDeletedJobId; + private string $lastDeletedJobId; /** * The code to manage dav.enable.tech_preview was used in 10.4/10.3 * The use of the steps to enable/disable it has been removed from the * feature files. But the infrastructure has been left here, as a similar * thing might likely happen in the future. - * - * @var boolean */ - private $doTechPreview = false; - - /** - * @var boolean techPreviewEnabled - */ - private $techPreviewEnabled = false; - - /** - * @var string initialTechPreviewStatus - */ - private $initialTechPreviewStatus; + private bool $doTechPreview = false; + private bool $techPreviewEnabled = false; + private string $initialTechPreviewStatus; /** * @return boolean @@ -342,7 +325,7 @@ public function createLocalStorageMountUsingTheOccCommand(string $mount):void { */ public function addConfigKeyWithValueInAppUsingTheOccCommand(string $key, string $value, string $app):void { $this->invokingTheCommand( - "config:app:set --value ${value} ${app} ${key}" + "config:app:set --value $value $app $key" ); } @@ -355,7 +338,7 @@ public function addConfigKeyWithValueInAppUsingTheOccCommand(string $key, string */ public function deleteConfigKeyOfAppUsingTheOccCommand(string $key, string $app):void { $this->invokingTheCommand( - "config:app:delete ${app} ${key}" + "config:app:delete $app $key" ); } @@ -373,7 +356,7 @@ public function addSystemConfigKeyUsingTheOccCommand( string $type = "string" ):void { $this->invokingTheCommand( - "config:system:set --value '${value}' --type ${type} ${key}" + "config:system:set --value '$value' --type $type $key" ); } @@ -385,7 +368,7 @@ public function addSystemConfigKeyUsingTheOccCommand( */ public function deleteSystemConfigKeyUsingTheOccCommand(string $key):void { $this->invokingTheCommand( - "config:system:delete ${key}" + "config:system:delete $key" ); } @@ -413,6 +396,18 @@ public function emptyTrashBinOfUserUsingOccCommand(string $user):void { ); } + /** + * @When the administrator cleans up previews using the occ command + * + * @return void + * @throws Exception + */ + public function theAdministratorCleansUpPreviewsUsingTheOccCommand():void { + $this->invokingTheCommand( + "previews:cleanup" + ); + } + /** * Create a calendar for given user with given calendar name * @@ -509,6 +504,22 @@ public function deleteExpiredVersionsForAllUsersUsingOccCommand(): void { $this->deleteExpiredVersionsForUserUsingOccCommand(); } + /** + * @param string $job + * + * @return void + * @throws Exception + */ + public function executeLastBackgroundJobUsingTheOccCommand(string $job):void { + $match = $this->getLastJobIdForJob($job); + if ($match === false) { + throw new Exception("Couldn't find jobId for given job: $job"); + } + $this->invokingTheCommand( + "background:queue:execute --accept-warning --force -vvv $match" + ); + } + /** * @param string $job * @@ -848,9 +859,9 @@ public function theCommandShouldHaveBeenSuccessful():void { public function theCommandFailedWithExitCode(int $exitCode):void { $exitStatusCode = $this->featureContext->getExitStatusCodeOfOccCommand(); Assert::assertEquals( - (int) $exitCode, + $exitCode, $exitStatusCode, - "The command was expected to fail with exit code $exitCode but got {$exitStatusCode}" + "The command was expected to fail with exit code $exitCode but got $exitStatusCode" ); } @@ -2581,7 +2592,7 @@ public function theBackgroundJobsModeShouldBe(string $mode):void { Assert::assertEquals( $mode, \trim($lastOutput), - "The background jobs mode was expected to be {$mode} but got '" + "The background jobs mode was expected to be $mode but got '" . \trim($lastOutput) . "'" ); @@ -2896,6 +2907,18 @@ public function theAdministratorGetsAllTheJobsInTheBackgroundQueueUsingTheOccCom $this->getAllJobsInBackgroundQueueUsingOccCommand(); } + /** + * @When the administrator executes the last background job :job using the occ command + * + * @param string $job + * + * @return void + * @throws Exception + */ + public function theAdministratorExecutesLastBackgroundJobUsingTheOccCommand(string $job):void { + $this->executeLastBackgroundJobUsingTheOccCommand($job); + } + /** * @When the administrator deletes the last background job :job using the occ command * @@ -3120,7 +3143,7 @@ public function theSystemConfigKeyFromLastCommandOutputShouldContainValue( ); $systemConfig = $configList['system']; - // convert the value to it's respective type based on type given in the type column + // convert the value to its respective type based on type given in the type column if ($type === 'boolean') { $value = $value === 'true' ? true : false; } elseif ($type === 'integer') { @@ -3665,13 +3688,13 @@ public function theAdministratorListsMigrationStatusOfApp(string $app):void { * @throws Exception */ public function theFollowingMigrationStatusShouldHaveBeenListed(TableNode $table): void { - $actualOuput = $this->getMigrationStatusInfo(); + $actualOutput = $this->getMigrationStatusInfo(); $expectedOutput = $table->getRowsHash(); foreach ($expectedOutput as $key => $value) { try { - $actualValue = $actualOuput[$key]; + $actualValue = $actualOutput[$key]; } catch (Exception $e) { - Assert:: fail("Expected '$key' but not found!\nActual Migration status: " . \print_r($actualOuput, true)); + Assert:: fail("Expected '$key' but not found!\nActual Migration status: " . \print_r($actualOutput, true)); } if ($this->isRegex($value)) { $match = preg_match($value, $actualValue); @@ -3698,29 +3721,28 @@ public function theExecutedMigrationsShouldEqualTheAvailableMigrations(): void { * * @return int */ - public function isRegex($value) { + public function isRegex(string $value) { $regex = "/^\/[\s\S]+\/$/"; return preg_match($regex, $value); } /** - * @return void + * @return array */ - public function getMigrationStatusInfo() { + public function getMigrationStatusInfo():array { $commandOutput = $this->featureContext->getStdOutOfOccCommand(); $migrationStatus = []; - if (!empty($commandOutput)) { - $infoArr = explode("\n", $commandOutput); - foreach ($infoArr as $info) { - if (!empty($info)) { - $row = \trim(\str_replace('>>', '', $info)); - $rowCol = explode(":", $row); - $migrationStatus[\trim($rowCol[0])] = \trim($rowCol[1]); - } - } - return $migrationStatus; - } else { + if (empty($commandOutput)) { throwException("Migration status information is empty!"); } + $infoArr = explode("\n", $commandOutput); + foreach ($infoArr as $info) { + if (!empty($info)) { + $row = \trim(\str_replace('>>', '', $info)); + $rowCol = explode(":", $row); + $migrationStatus[\trim($rowCol[0])] = \trim($rowCol[1]); + } + } + return $migrationStatus; } } diff --git a/tests/acceptance/features/bootstrap/OccUsersGroupsContext.php b/tests/acceptance/features/bootstrap/OccUsersGroupsContext.php index c556a638d4c1..6664ef3babc6 100644 --- a/tests/acceptance/features/bootstrap/OccUsersGroupsContext.php +++ b/tests/acceptance/features/bootstrap/OccUsersGroupsContext.php @@ -31,17 +31,8 @@ * Context for test steps that test occ commands that manage users and groups */ class OccUsersGroupsContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OccContext - */ - private $occContext; + private FeatureContext $featureContext; + private OccContext $occContext; /** * @param TableNode $table @@ -61,31 +52,19 @@ public function createUsersUsingOccCommand( $username = $row['username']; $user = $this->featureContext->getActualUsername($username); $cmd = "user:add $user --password-from-env"; - if (isset($row['displayname'])) { - $displayName = $row['displayname']; - } else { - $displayName = $this->featureContext->getDisplayNameForUser($username); - } + $displayName = $row['displayname'] ?? $this->featureContext->getDisplayNameForUser($username); if ($displayName !== null) { $cmd = "$cmd --display-name='$displayName'"; } - if (isset($row['email'])) { - $email = $row['email']; - } else { - $email = $this->featureContext->getEmailAddressForUser($username); - } + $email = $row['email'] ?? $this->featureContext->getEmailAddressForUser($username); if ($email !== null) { $cmd = "$cmd --email='$email'"; } - if (isset($row['password'])) { - $password = $row['password']; - } else { - $password = $this->featureContext->getPasswordForUser($row ['username']); - } + $password = $row['password'] ?? $this->featureContext->getPasswordForUser($row ['username']); $this->featureContext->setOccLastCode( $this->occContext->invokingTheCommandWithEnvVariable( @@ -105,7 +84,6 @@ public function createUsersUsingOccCommand( $password, $displayName, $email, - null, $this->occContext->theOccCommandExitStatusWasSuccess() ); } @@ -190,7 +168,6 @@ public function theAdministratorCreatesUserPasswordGroupUsingTheOccCommand(strin $actualPassword, null, null, - null, $this->occContext->theOccCommandExitStatusWasSuccess() ); $this->featureContext->addGroupToCreatedGroupsList($group); @@ -737,6 +714,8 @@ public function theDisplayNameReturnedByTheOccCommandShouldBe(string $place, str case "third": $index = 2; break; + default: + $index = 0; } $lastOutput = $this->featureContext->getStdOutOfOccCommand(); $lastOutputUser = \json_decode($lastOutput, true); diff --git a/tests/acceptance/features/bootstrap/Provisioning.php b/tests/acceptance/features/bootstrap/Provisioning.php index 06b9e1c66dbe..9a0501bacd5b 100644 --- a/tests/acceptance/features/bootstrap/Provisioning.php +++ b/tests/acceptance/features/bootstrap/Provisioning.php @@ -39,48 +39,20 @@ trait Provisioning { /** * list of users that were created on the local server during test runs * key is the lowercase username, value is an array of user attributes - * - * @var array */ - private $createdUsers = []; + private array $createdUsers = []; /** * list of users that were created on the remote server during test runs * key is the lowercase username, value is an array of user attributes - * - * @var array - */ - private $createdRemoteUsers = []; - - /** - * @var array - */ - private $enabledApps = []; - - /** - * @var array - */ - private $disabledApps = []; - - /** - * @var array - */ - private $startingGroups = []; - - /** - * @var array - */ - private $createdRemoteGroups = []; - - /** - * @var array - */ - private $createdGroups = []; - - /** - * @var array */ - private $userResponseFields = [ + private array $createdRemoteUsers = []; + private array $enabledApps = []; + private array $disabledApps = []; + private array $startingGroups = []; + private array $createdRemoteGroups = []; + private array $createdGroups = []; + private array $userResponseFields = [ "enabled", "quota", "email", "displayname", "home", "two_factor_auth_enabled", "quota definition", "quota free", "quota user", "quota total", "quota relative" ]; @@ -453,15 +425,13 @@ public function userHasBeenCreatedOnDatabaseBackend(?string $user):void { * * @param string $user * @param string $skeletonType - * @param boolean $skeleton * * @return void - * @throws Exception + * @throws JsonException */ public function userHasBeenCreatedWithDefaultAttributes( string $user, - string $skeletonType = "", - bool $skeleton = true + string $skeletonType = "" ):void { if ($skeletonType === "") { $skeletonType = $this->getSmallestSkeletonDirName(); @@ -471,14 +441,7 @@ public function userHasBeenCreatedWithDefaultAttributes( try { $this->createUser( - $user, - null, - null, - null, - true, - null, - true, - $skeleton + $user ); $this->userShouldExist($user); } finally { @@ -512,7 +475,7 @@ public function userHasBeenCreatedWithDefaultAttributesAndWithoutSkeletonFiles(s public function theseUsersHaveBeenCreatedWithDefaultAttributesAndWithoutSkeletonFiles(TableNode $table):void { $originalSkeletonPath = $this->setSkeletonDirByType($this->getSmallestSkeletonDirName()); try { - $this->createTheseUsers(true, true, true, $table); + $this->createTheseUsers(true, true, $table); } finally { // restore skeleton directory even if user creation failed $this->setSkeletonDir($originalSkeletonPath); @@ -596,7 +559,6 @@ public function importLdifData(string $ldifData):void { * @throws \LdapException */ public function connectToLdap(array $suiteParameters):void { - $useSsl = false; $occResult = SetupHelper::runOcc( ['ldap:show-config', 'LDAPTestId', '--output=json'], $this->getStepLineRef() @@ -635,14 +597,14 @@ public function connectToLdap(array $suiteParameters):void { 'port' => $this->ldapPort, 'password' => $this->ldapAdminPassword, 'bindRequiresDn' => true, - 'useSsl' => $useSsl, + 'useSsl' => false, 'baseDn' => $this->ldapBaseDN, 'username' => $this->ldapAdminUser ]; $this->ldap = new Ldap($options); $this->ldap->bind(); - $ldifFile = __DIR__ . (string)$suiteParameters['ldapInitialUserFilePath']; + $ldifFile = __DIR__ . $suiteParameters['ldapInitialUserFilePath']; if (!$this->skipImportLdif) { $this->importLdifFile($ldifFile); } @@ -745,7 +707,7 @@ public function createLdapUser(array $setting):void { $userId = \str_replace('+', '\+', $setting["userid"]); $newDN = 'uid=' . $userId . ',ou=' . $ou . ',' . $this->ldapBaseDN; - //pick a high number as uidnumber to make sure there are no conflicts with existing uidnumbers + //pick a high uid number to make sure there are no conflicts with existing uid numbers $uidNumber = \count($this->ldapCreatedUsers) + 30000; $entry = []; $entry['cn'] = $userId; @@ -903,6 +865,12 @@ public function resetOldLdapConfig():void { ['ldap:delete-config', $configId], $this->getStepLineRef() ); + // The LDAP config has been deleted, so any settings that were + // changed in that config do not need to be reverted. + // Remove the memory of those settings. + if (isset($this->oldLdapConfig[$configId])) { + unset($this->oldLdapConfig[$configId]); + } } foreach ($this->oldLdapConfig as $configId => $settings) { foreach ($settings as $configKey => $configValue) { @@ -921,7 +889,6 @@ public function resetOldLdapConfig():void { * @param boolean $initialize * @param array|null $usersAttributes * @param string|null $method create the user with "ldap" or "api" - * @param boolean $skeleton * * @return void * @throws Exception @@ -930,8 +897,7 @@ public function resetOldLdapConfig():void { public function usersHaveBeenCreated( bool $initialize, ?array $usersAttributes, - ?string $method = null, - ?bool $skeleton = true + ?string $method = null ) { $requests = []; $client = HttpRequestHelper::createClient( @@ -940,46 +906,27 @@ public function usersHaveBeenCreated( ); $useLdap = false; - $useGraph = false; if ($method === null) { $useLdap = $this->isTestingWithLdap(); } elseif ($method === "ldap") { $useLdap = true; - } elseif ($method === "graph") { - $useGraph = true; } - foreach ($usersAttributes as $i => $userAttributes) { + foreach ($usersAttributes as $userAttributes) { if ($useLdap) { $this->createLdapUser($userAttributes); } else { $attributesToCreateUser['userid'] = $userAttributes['userid']; $attributesToCreateUser['password'] = $userAttributes['password']; $attributesToCreateUser['displayname'] = $userAttributes['displayName']; - if ($useGraph) { - $body = \TestHelpers\GraphHelper::prepareCreateUserPayload( - $attributesToCreateUser['userid'], - $attributesToCreateUser['password'], - $attributesToCreateUser['email'], - $attributesToCreateUser['displayname'] - ); - $request = \TestHelpers\GraphHelper::createRequest( - $this->getBaseUrl(), - $this->getStepLineRef(), - "POST", - 'users', - $body, - ); - } else { - // Create a OCS request for creating the user. The request is not sent to the server yet. - $request = OcsApiHelper::createOcsRequest( - $this->getBaseUrl(), - 'POST', - "/cloud/users", - $this->stepLineRef, - $attributesToCreateUser - ); - } + // Create an OCS request for creating the user. The request is not sent to the server yet. + $request = OcsApiHelper::createOcsRequest( + $this->getBaseUrl(), + 'POST', + "/cloud/users", + $this->stepLineRef, + $attributesToCreateUser + ); // Add the request to the $requests array so that they can be sent in parallel. $requests[] = $request; } @@ -991,32 +938,17 @@ public function usersHaveBeenCreated( // Check all requests to inspect failures. foreach ($results as $key => $e) { if ($e instanceof ClientException) { - if ($useGraph) { - $responseBody = $this->getJsonDecodedResponse($e->getResponse()); - $httpStatusCode = $e->getResponse()->getStatusCode(); - $graphStatusCode = $responseBody['error']['code']; - $messageText = $responseBody['error']['message']; - $exceptionToThrow = new Exception( - __METHOD__ . - " Unexpected failure when creating the user '" . - $usersAttributes[$key]['userid'] . "'" . - "\nHTTP status $httpStatusCode " . - "\nGraph status $graphStatusCode " . - "\nError message $messageText" - ); - } else { - $responseXml = $this->getResponseXml($e->getResponse(), __METHOD__); - $messageText = (string) $responseXml->xpath("/ocs/meta/message")[0]; - $ocsStatusCode = (string) $responseXml->xpath("/ocs/meta/statuscode")[0]; - $httpStatusCode = $e->getResponse()->getStatusCode(); - $reasonPhrase = $e->getResponse()->getReasonPhrase(); - $exceptionToThrow = new Exception( - __METHOD__ . " Unexpected failure when creating the user '" . - $usersAttributes[$key]['userid'] . "': HTTP status $httpStatusCode " . - "HTTP reason $reasonPhrase OCS status $ocsStatusCode " . - "OCS message $messageText" - ); - } + $responseXml = $this->getResponseXml($e->getResponse(), __METHOD__); + $messageText = (string) $responseXml->xpath("/ocs/meta/message")[0]; + $ocsStatusCode = (string) $responseXml->xpath("/ocs/meta/statuscode")[0]; + $httpStatusCode = $e->getResponse()->getStatusCode(); + $reasonPhrase = $e->getResponse()->getReasonPhrase(); + $exceptionToThrow = new Exception( + __METHOD__ . " Unexpected failure when creating the user '" . + $usersAttributes[$key]['userid'] . "': HTTP status $httpStatusCode " . + "HTTP reason $reasonPhrase OCS status $ocsStatusCode " . + "OCS message $messageText" + ); } } } @@ -1027,20 +959,11 @@ public function usersHaveBeenCreated( $editData = []; foreach ($usersAttributes as $userAttributes) { $users[] = $userAttributes['userid']; - if ($useGraph) { - // for graph api, we need to save the user id to be able to add it in some group - // can be fetched with the "onPremisesSamAccountName" i.e. userid - $this->graphContext->adminHasRetrievedUserUsingTheGraphApi($userAttributes['userid']); - $userAttributes['id'] = $this->getJsonDecodedResponse()['id']; - } else { - $userAttributes['id'] = null; - } $this->addUserToCreatedUsersList( $userAttributes['userid'], $userAttributes['password'], $userAttributes['displayName'], - $userAttributes['email'], - $userAttributes['id'] + $userAttributes['email'] ); if (isset($userAttributes['displayName'])) { @@ -1110,22 +1033,19 @@ public function theAdministratorCreatesTheseUsers( * * @param boolean $setDefaultAttributes * @param boolean $initialize - * @param boolean $skeleton * @param TableNode $table * * @return void * @throws Exception * @throws GuzzleException */ - public function createTheseUsers(bool $setDefaultAttributes, bool $initialize, bool $skeleton, TableNode $table):void { + public function createTheseUsers(bool $setDefaultAttributes, bool $initialize, TableNode $table):void { $this->verifyTableNodeColumns($table, ['username'], ['displayname', 'email', 'password']); $table = $table->getColumnsHash(); $usersAttributes = $this->buildUsersAttributesArray($setDefaultAttributes, $table); $this->usersHaveBeenCreated( $initialize, - $usersAttributes, - null, - $skeleton + $usersAttributes ); foreach ($usersAttributes as $expectedUser) { $this->userShouldExist($expectedUser["userid"]); @@ -1161,7 +1081,7 @@ public function theseUsersHaveBeenCreated( $setDefaultAttributes = $defaultAttributesText !== ""; $initialize = $doNotInitialize === ""; try { - $this->createTheseUsers($setDefaultAttributes, $initialize, true, $table); + $this->createTheseUsers($setDefaultAttributes, $initialize, $table); } finally { // The effective skeleton directory is the one when the user is initialized // If we did not initialize the user on creation, then we need to leave @@ -1231,7 +1151,7 @@ public function adminHasChangedPasswordOfUserTo( */ public function userEnablesOrDisablesApp(string $user, string $action, string $app):void { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/apps/$app"; + . "/ocs/v$this->ocsApiVersion.php/cloud/apps/$app"; if ($action === 'enables') { $this->response = HttpRequestHelper::post( $fullUrl, @@ -1368,7 +1288,6 @@ public function adminSendsUserCreationRequestWithFollowingAttributesUsingTheProv $password, $displayname, $email, - null, $this->theHTTPStatusCodeWasSuccess() ); } @@ -1403,7 +1322,6 @@ public function adminSendsUserCreationRequestUsingTheProvisioningApi(string $use $password, null, $email, - null, $success ); } @@ -1451,7 +1369,6 @@ public function userSendsUserCreationRequestUsingTheProvisioningApi(string $user $password, null, $email, - null, $this->theHTTPStatusCodeWasSuccess() ); } @@ -1477,7 +1394,7 @@ public function theAdministratorCreatesUserPasswordGroupUsingTheProvisioningApi( $bodyTable = new TableNode( [['userid', $user], ['password', $password], ['groups[]', $group]] ); - + $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $this->getAdminUsername(), "POST", @@ -1489,7 +1406,6 @@ public function theAdministratorCreatesUserPasswordGroupUsingTheProvisioningApi( $password, null, $email, - null, $this->theHTTPStatusCodeWasSuccess() ); } @@ -1529,7 +1445,6 @@ public function theGroupAdminCreatesUserPasswordGroupUsingTheProvisioningApi( $password, null, $email, - null, $this->theHTTPStatusCodeWasSuccess() ); } @@ -1568,7 +1483,6 @@ public function theGroupAdminCreatesUserPasswordInOtherGroupUsingTheProvisioning $password, null, $email, - null, $this->theHTTPStatusCodeWasSuccess() ); } @@ -1606,7 +1520,7 @@ public function adminResetsPasswordOfUserUsingTheProvisioningApi(string $usernam * @Given the administrator has reset the password of user :username to :password * * @param string $username of the user whose password is reset - * @param string $password + * @param string|null $password * * @return void */ @@ -2200,7 +2114,7 @@ public function userHasChangedTheDisplayNameOfUserUsingTheProvisioningApi( $displayName ); $this->theHTTPStatusCodeShouldBeSuccess(); - + $this->rememberUserDisplayName($targetUser, $displayName); } /** @@ -2681,7 +2595,7 @@ public function theAdministratorGetsAllTheMembersOfGroupUsingTheProvisioningApi( * @return void */ public function userGetsAllTheMembersOfGroupUsingTheProvisioningApi(string $user, string $group):void { - $fullUrl = $this->getBaseUrl() . "/ocs/v{$this->ocsApiVersion}.php/cloud/groups/$group"; + $fullUrl = $this->getBaseUrl() . "/ocs/v$this->ocsApiVersion.php/cloud/groups/$group"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -2696,7 +2610,7 @@ public function userGetsAllTheMembersOfGroupUsingTheProvisioningApi(string $user * @return ResponseInterface */ public function getAllGroups():ResponseInterface { - $fullUrl = $this->getBaseUrl() . "/ocs/v{$this->ocsApiVersion}.php/cloud/groups"; + $fullUrl = $this->getBaseUrl() . "/ocs/v$this->ocsApiVersion.php/cloud/groups"; return HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -2724,7 +2638,7 @@ public function theAdministratorGetsAllTheGroupsUsingTheProvisioningApi():void { * @throws Exception */ public function userTriesToGetAllTheGroupsUsingTheProvisioningApi(string $user):void { - $fullUrl = $this->getBaseUrl() . "/ocs/v{$this->ocsApiVersion}.php/cloud/groups"; + $fullUrl = $this->getBaseUrl() . "/ocs/v$this->ocsApiVersion.php/cloud/groups"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::get( @@ -2758,7 +2672,7 @@ public function theAdministratorGetsAllTheGroupsOfUser(string $user):void { */ public function userGetsAllTheGroupsOfUser(string $user, string $otherUser):void { $actualOtherUser = $this->getActualUsername($otherUser); - $fullUrl = $this->getBaseUrl() . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$actualOtherUser/groups"; + $fullUrl = $this->getBaseUrl() . "/ocs/v$this->ocsApiVersion.php/cloud/users/$actualOtherUser/groups"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::get( @@ -2787,7 +2701,7 @@ public function theAdministratorGetsTheListOfAllUsersUsingTheProvisioningApi():v * @throws Exception */ public function userGetsTheListOfAllUsersUsingTheProvisioningApi(string $user):void { - $fullUrl = $this->getBaseUrl() . "/ocs/v{$this->ocsApiVersion}.php/cloud/users"; + $fullUrl = $this->getBaseUrl() . "/ocs/v$this->ocsApiVersion.php/cloud/users"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::get( @@ -2809,14 +2723,13 @@ public function userGetsTheListOfAllUsersUsingTheProvisioningApi(string $user):v */ public function initializeUser(string $user, string $password):void { $url = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$user"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$user"; HttpRequestHelper::get( $url, $this->getStepLineRef(), $user, $password ); - $this->lastUploadTime = \time(); } /** @@ -2852,8 +2765,7 @@ public function initializeUsers(array $users):void { * @param string|null $password * @param string|null $displayName * @param string|null $email - * @param string|null $userId only set for the users created using the Graph API - * @param bool $shouldExist + * @param bool|null $shouldExist * * @return void * @throws JsonException @@ -2863,8 +2775,7 @@ public function addUserToCreatedUsersList( ?string $password, ?string $displayName = null, ?string $email = null, - ?string $userId = null, - bool $shouldExist = true + ?bool $shouldExist = true ):void { $user = $this->getActualUsername($user); $normalizedUsername = $this->normalizeUsername($user); @@ -2873,8 +2784,7 @@ public function addUserToCreatedUsersList( "displayname" => $displayName, "email" => $email, "shouldExist" => $shouldExist, - "actualUsername" => $user, - "id" => $userId + "actualUsername" => $user ]; if ($this->currentServer === 'LOCAL') { @@ -2947,10 +2857,10 @@ public function rememberThatUserIsNotExpectedToExist(string $user):void { * @param bool $initialize initialize the user skeleton files etc * @param string|null $method how to create the user api|occ, default api * @param bool $setDefault sets the missing values to some default - * @param bool $skeleton * * @return void - * @throws Exception + * @throws GuzzleException + * @throws JsonException */ public function createUser( ?string $user, @@ -2959,10 +2869,8 @@ public function createUser( ?string $email = null, bool $initialize = true, ?string $method = null, - bool $setDefault = true, - bool $skeleton = true + bool $setDefault = true ):void { - $userId = null; if ($password === null) { $password = $this->getPasswordForUser($user); } @@ -3020,32 +2928,21 @@ public function createUser( $this->usersHaveBeenCreated( $initialize, $settings, - $method, - $skeleton + $method ); } catch (LdapException $exception) { throw new Exception( - __METHOD__ . " cannot create a LDAP user with provided data. Error: {$exception}" + __METHOD__ . " cannot create a LDAP user with provided data. Error: $exception" ); } break; - case "graph": - $this->graphContext->theAdminHasCreatedUser( - $user, - $password, - $email, - $displayName, - ); - $newUser = $this->getJsonDecodedResponse(); - $userId = $newUser['id']; - break; default: throw new InvalidArgumentException( __METHOD__ . " Invalid method to create a user" ); } - $this->addUserToCreatedUsersList($user, $password, $displayName, $email, $userId); + $this->addUserToCreatedUsersList($user, $password, $displayName, $email); if ($initialize) { $this->initializeUser($user, $password); } @@ -3133,7 +3030,6 @@ public function userExists(?string $user):bool { */ public function userShouldBelongToGroup(string $user, string $group):void { $user = $this->getActualUsername($user); - $respondedArray = []; $this->theAdministratorGetsAllTheGroupsOfUser($user); $respondedArray = $this->getArrayOfGroupsResponded($this->response); \sort($respondedArray); @@ -3464,16 +3360,10 @@ public function addUserToGroup(string $user, string $group, ?string $method = nu ); } catch (LdapException $exception) { throw new Exception( - "User " . $user . " cannot be added to " . $group . " . Error: {$exception}" + "User $user cannot be added to $group Error: $exception" ); }; break; - case "graph": - $this->graphContext->adminHasAddedUserToGroupUsingTheGraphApi( - $user, - $group - ); - break; default: throw new InvalidArgumentException( "Invalid method to add a user to a group" @@ -3498,23 +3388,18 @@ public function theAdministratorHasBeenAddedToGroup(string $group):void { * @param string $group * @param bool $shouldExist - true if the group should exist * @param bool $possibleToDelete - true if it is possible to delete the group - * @param string|null $id - id of the group, only required for the groups created using the Graph API * * @return void */ public function addGroupToCreatedGroupsList( string $group, bool $shouldExist = true, - bool $possibleToDelete = true, - ?string $id = null + bool $possibleToDelete = true ):void { $groupData = [ "shouldExist" => $shouldExist, "possibleToDelete" => $possibleToDelete ]; - if ($id !== null) { - $groupData["id"] = $id; - } if ($this->currentServer === 'LOCAL') { $this->createdGroups[$group] = $groupData; @@ -3684,7 +3569,6 @@ public function createTheGroup(string $group, ?string $method = null):void { $group = \trim($group); $method = \trim(\strtolower($method)); $groupCanBeDeleted = false; - $groupId = null; switch ($method) { case "api": $result = UserHelper::createGroup( @@ -3721,22 +3605,17 @@ public function createTheGroup(string $group, ?string $method = null):void { $this->createLdapGroup($group); } catch (LdapException $e) { throw new Exception( - "could not create group '$group'. Error: {$e}" + "could not create group '$group'. Error: $e" ); } break; - case "graph": - $newGroup = $this->graphContext->adminHasCreatedGroupUsingTheGraphApi($group); - $groupCanBeDeleted = true; - $groupId = $newGroup["id"]; - break; default: throw new InvalidArgumentException( "Invalid method to create group '$group'" ); } - $this->addGroupToCreatedGroupsList($group, true, $groupCanBeDeleted, $groupId); + $this->addGroupToCreatedGroupsList($group, true, $groupCanBeDeleted); } /** @@ -4369,7 +4248,7 @@ public function userMakesUserASubadminOfGroupUsingTheProvisioningApi( $actualSubadminUsername = $this->getActualUsername($otherUser); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$actualSubadminUsername/subadmins"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$actualSubadminUsername/subadmins"; $body = ['groupid' => $group]; $this->response = HttpRequestHelper::post( $fullUrl, @@ -4390,7 +4269,7 @@ public function userMakesUserASubadminOfGroupUsingTheProvisioningApi( */ public function theAdministratorGetsAllTheGroupsWhereUserIsSubadminUsingTheProvisioningApi(string $user):void { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$user/subadmins"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$user/subadmins"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -4412,7 +4291,7 @@ public function theAdministratorGetsAllTheGroupsWhereUserIsSubadminUsingTheProvi public function userTriesToGetAllTheGroupsWhereUserIsSubadminUsingTheProvisioningApi(string $user, string $otherUser):void { $actualOtherUser = $this->getActualUsername($otherUser); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$actualOtherUser/subadmins"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$actualOtherUser/subadmins"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::get( @@ -4471,7 +4350,7 @@ public function theAdministratorGetsAllTheSubadminsOfGroupUsingTheProvisioningAp */ public function userGetsAllTheSubadminsOfGroupUsingTheProvisioningApi(string $user, string $group):void { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/groups/$group/subadmins"; + . "/ocs/v$this->ocsApiVersion.php/cloud/groups/$group/subadmins"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::get( @@ -4518,7 +4397,7 @@ public function userRemovesUserFromBeingASubadminOfGroupUsingTheProvisioningApi( ):void { $actualOtherUser = $this->getActualUsername($otherUser); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$actualOtherUser/subadmins"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$actualOtherUser/subadmins"; $actualUser = $this->getActualUsername($user); $actualPassword = $this->getUserPassword($actualUser); $this->response = HttpRequestHelper::delete( @@ -5023,9 +4902,7 @@ public function theCreationTimeReturnedByTheApiShouldBe():void { public function getArrayOfUsersResponded(ResponseInterface $resp):array { $listCheckedElements = $this->getResponseXml($resp, __METHOD__)->data[0]->users[0]->element; - $extractedElementsArray - = \json_decode(\json_encode($listCheckedElements), true); - return $extractedElementsArray; + return \json_decode(\json_encode($listCheckedElements), true); } /** @@ -5039,9 +4916,7 @@ public function getArrayOfUsersResponded(ResponseInterface $resp):array { public function getArrayOfGroupsResponded(ResponseInterface $resp):array { $listCheckedElements = $this->getResponseXml($resp, __METHOD__)->data[0]->groups[0]->element; - $extractedElementsArray - = \json_decode(\json_encode($listCheckedElements), true); - return $extractedElementsArray; + return \json_decode(\json_encode($listCheckedElements), true); } /** @@ -5055,9 +4930,7 @@ public function getArrayOfGroupsResponded(ResponseInterface $resp):array { public function getArrayOfAppsResponded(ResponseInterface $resp):array { $listCheckedElements = $this->getResponseXml($resp, __METHOD__)->data[0]->apps[0]->element; - $extractedElementsArray - = \json_decode(\json_encode($listCheckedElements), true); - return $extractedElementsArray; + return \json_decode(\json_encode($listCheckedElements), true); } /** @@ -5071,9 +4944,7 @@ public function getArrayOfAppsResponded(ResponseInterface $resp):array { public function getArrayOfSubadminsResponded(ResponseInterface $resp):array { $listCheckedElements = $this->getResponseXml($resp, __METHOD__)->data[0]->element; - $extractedElementsArray - = \json_decode(\json_encode($listCheckedElements), true); - return $extractedElementsArray; + return \json_decode(\json_encode($listCheckedElements), true); } /** @@ -5087,9 +4958,7 @@ public function getArrayOfSubadminsResponded(ResponseInterface $resp):array { public function getArrayOfAppInfoResponded(ResponseInterface $resp):array { $listCheckedElements = $this->getResponseXml($resp, __METHOD__)->data[0]; - $extractedElementsArray - = \json_decode(\json_encode($listCheckedElements), true); - return $extractedElementsArray; + return \json_decode(\json_encode($listCheckedElements), true); } /** @@ -5185,7 +5054,7 @@ public function theInformationForAppShouldHaveAValidVersion(string $app):void { public function userShouldBeDisabled(string $user):void { $user = $this->getActualUsername($user); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$user"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$user"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5225,7 +5094,7 @@ public function theFollowingUsersShouldBeDisabled(TableNode $table):void { public function userShouldBeEnabled(string $user):void { $user = $this->getActualUsername($user); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$user"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$user"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5277,8 +5146,7 @@ public function adminSetsUserQuotaToUsingTheProvisioningApi(string $user, string "PUT", "/cloud/users/$user", $this->getStepLineRef(), - $body, - 2 + $body ); } @@ -5327,7 +5195,7 @@ public function userHasBeenGivenUnlimitedQuota(string $user):void { */ public function getUserHome(string $user):string { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$user"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$user"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5377,8 +5245,7 @@ public function checkAttributesForUser(string $user, TableNode $body):void { $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $this->getAdminUsername(), "GET", - "/cloud/users/$user", - null + "/cloud/users/$user" ); $this->checkUserAttributes($body); } @@ -5472,11 +5339,11 @@ public function cleanupDatabaseUsers():void { $this->authContext->deleteTokenAuthEnforcedAfterScenario(); $previousServer = $this->currentServer; $this->usingServer('LOCAL'); - foreach ($this->createdUsers as $user => $userData) { + foreach ($this->createdUsers as $userData) { $this->deleteUser($userData['actualUsername']); } $this->usingServer('REMOTE'); - foreach ($this->createdRemoteUsers as $remoteUser => $userData) { + foreach ($this->createdRemoteUsers as $userData) { $this->deleteUser($userData['actualUsername']); } $this->usingServer($previousServer); @@ -5573,7 +5440,7 @@ public function disableOrEnableUser(string $user, string $otherUser, string $act $actualOtherUser = $this->getActualUsername($otherUser); $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/users/$actualOtherUser/$action"; + . "/ocs/v$this->ocsApiVersion.php/cloud/users/$actualOtherUser/$action"; $this->response = HttpRequestHelper::put( $fullUrl, $this->getStepLineRef(), @@ -5591,7 +5458,7 @@ public function disableOrEnableUser(string $user, string $otherUser, string $act */ public function getAllApps():array { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/apps"; + . "/ocs/v$this->ocsApiVersion.php/cloud/apps"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5609,7 +5476,7 @@ public function getAllApps():array { */ public function getEnabledApps():array { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/apps?filter=enabled"; + . "/ocs/v$this->ocsApiVersion.php/cloud/apps?filter=enabled"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5627,7 +5494,7 @@ public function getEnabledApps():array { */ public function getDisabledApps():array { $fullUrl = $this->getBaseUrl() - . "/ocs/v{$this->ocsApiVersion}.php/cloud/apps?filter=disabled"; + . "/ocs/v$this->ocsApiVersion.php/cloud/apps?filter=disabled"; $this->response = HttpRequestHelper::get( $fullUrl, $this->getStepLineRef(), @@ -5688,17 +5555,6 @@ private function getSmallestSkeletonDirName(): string { return "empty"; } - /** - * @return bool - */ - private function isEmptySkeleton(): bool { - $skeletonDir = \getenv("SKELETON_DIR"); - if (($skeletonDir !== false) && (\basename($skeletonDir) === $this->getSmallestSkeletonDirName() . "Skeleton")) { - return true; - } - return false; - } - /** * sets the skeletondirectory according to the type * diff --git a/tests/acceptance/features/bootstrap/PublicWebDavContext.php b/tests/acceptance/features/bootstrap/PublicWebDavContext.php index 4a97b81a5d51..c78c1a68c8f5 100644 --- a/tests/acceptance/features/bootstrap/PublicWebDavContext.php +++ b/tests/acceptance/features/bootstrap/PublicWebDavContext.php @@ -32,18 +32,8 @@ * context file for steps that execute actions as "the public". */ class PublicWebDavContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OccContext - */ - private $occContext; - + private FeatureContext $featureContext; + private OccContext $occContext; /** * @When /^the public downloads the last public link shared file with range "([^"]*)" using the (old|new) public WebDAV API$/ * @@ -389,13 +379,7 @@ public function publiclyCopyingFile( "COPY", null, null, - $headers, - null, - null, - null, - false, - 0, - null + $headers ); $this->featureContext->setResponse($response); } @@ -528,7 +512,7 @@ public function thePublicUploadsFileWithPasswordAndContentUsingPublicWebDAVApi( } /** - * @Given the public has uploaded file :filename" with password :password and content :body + * @Given the public has uploaded file :filename with password :password and content :body * * @param string $filename target file name * @param string|null $password @@ -1144,7 +1128,7 @@ public function publiclyUploadingShouldToSharedFileShouldFail( * @Then /^the public upload to the last publicly shared folder using the (old|new) public WebDAV API should fail with HTTP status code "([^"]*)"$/ * * @param string $publicWebDAVAPIVersion - * @param string $expectedHttpCode + * @param string|null $expectedHttpCode * * @return void * @throws Exception @@ -1326,8 +1310,7 @@ public function publiclyUploadingToPublicLinkSharedFileShouldWork( $this->downloadPublicFileWithRange( "", - $publicWebDAVAPIVersion, - "" + $publicWebDAVAPIVersion ); $this->featureContext->checkDownloadedContentMatches( @@ -1483,7 +1466,7 @@ public function theMtimeOfFileInTheLastSharedPublicLinkUsingTheWebdavApiShouldBe Assert::assertEquals( $mtime, - WebDavHelper::getMtimeOfFileinPublicLinkShare( + WebDavHelper::getMtimeOfFileInPublicLinkShare( $baseUrl, $fileName, $token, @@ -1509,7 +1492,7 @@ public function theMtimeOfFileInTheLastSharedPublicLinkUsingTheWebdavApiShouldNo $baseUrl = $this->featureContext->getBaseUrl(); Assert::assertNotEquals( $mtime, - WebDavHelper::getMtimeOfFileinPublicLinkShare( + WebDavHelper::getMtimeOfFileInPublicLinkShare( $baseUrl, $fileName, $token, @@ -1622,10 +1605,10 @@ public function setUpScenario(BeforeScenarioScope $scope):void { * * @param string $method * @param string $publicWebDAVAPIVersion - * @param string $password + * @param string|null $password * * @return void - * @throws GuzzleException + * @throws \GuzzleHttp\Exception\GuzzleException */ public function publicSendsRequestToLastPublicShare(string $method, string $publicWebDAVAPIVersion, ?string $password = ''):void { if ($method === "PROPFIND") { @@ -1640,6 +1623,8 @@ public function publicSendsRequestToLastPublicShare(string $method, string $publ '; + } else { + $body = null; } $token = $this->featureContext->getLastPublicShareToken(); $davPath = WebDavHelper::getDavPath( diff --git a/tests/acceptance/features/bootstrap/SearchContext.php b/tests/acceptance/features/bootstrap/SearchContext.php index 872701c6809e..1f9e8a4d1e88 100644 --- a/tests/acceptance/features/bootstrap/SearchContext.php +++ b/tests/acceptance/features/bootstrap/SearchContext.php @@ -32,11 +32,7 @@ * context containing search related API steps */ class SearchContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @When user :user searches for :pattern using the WebDAV API diff --git a/tests/acceptance/features/bootstrap/ShareesContext.php b/tests/acceptance/features/bootstrap/ShareesContext.php index 1bd1f7dfb10a..2fc8cbf146af 100644 --- a/tests/acceptance/features/bootstrap/ShareesContext.php +++ b/tests/acceptance/features/bootstrap/ShareesContext.php @@ -34,17 +34,8 @@ * Sharees context. */ class ShareesContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OCSContext - */ - private $ocsContext; + private FeatureContext $featureContext; + private OCSContext $ocsContext; /** * @When /^the user gets the sharees using the sharing API with parameters$/ @@ -73,21 +64,18 @@ public function userGetsTheShareesWithParameters(string $user, TableNode $body): $user = $this->featureContext->getActualUsername($user); $url = '/apps/files_sharing/api/v1/sharees'; $this->featureContext->verifyTableNodeColumnsCount($body, 2); - if ($body instanceof TableNode) { - $parameters = []; - foreach ($body->getRowsHash() as $key => $value) { - $parameters[] = "$key=$value"; - } - if (!empty($parameters)) { - $url .= '?' . \implode('&', $parameters); - } + $parameters = []; + foreach ($body->getRowsHash() as $key => $value) { + $parameters[] = "$key=$value"; + } + if (!empty($parameters)) { + $url .= '?' . \implode('&', $parameters); } $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - $url, - null + $url ); } diff --git a/tests/acceptance/features/bootstrap/Sharing.php b/tests/acceptance/features/bootstrap/Sharing.php index fe5fbb3c326d..d049b003d62c 100644 --- a/tests/acceptance/features/bootstrap/Sharing.php +++ b/tests/acceptance/features/bootstrap/Sharing.php @@ -36,10 +36,7 @@ * Sharing trait */ trait Sharing { - /** - * @var int - */ - private $sharingApiVersion = 1; + private int $sharingApiVersion = 1; /** * Contains the API response to the last share that was created by each user @@ -47,7 +44,7 @@ trait Sharing { * * @var SimpleXMLElement[] */ - private $lastShareDataByUser = []; + private array $lastShareDataByUser = []; /** * Contains the share id of the last share that was created by each user, @@ -55,51 +52,32 @@ trait Sharing { * * @var string[] */ - private $lastShareIdByUser = []; + private array $lastShareIdByUser = []; - /** - * @var string - */ - private $userWhoCreatedLastShare = null; - - /** - * @var string - */ - private $userWhoCreatedLastPublicShare = null; + private ?string $userWhoCreatedLastShare = null; + private ?string $userWhoCreatedLastPublicShare = null; /** * Contains the API response to the last public link share that was created * by the test-runner using the Sharing API. * Shares created on the webUI do not have an entry. - * - * @var SimpleXMLElement */ - private $lastPublicShareData = null; + private ?SimpleXMLElement $lastPublicShareData = null; /** * Contains the share id of the last public link share that was created by * the test-runner, either using the Sharing API or on the web UI. - * - * @var string */ - private $lastPublicShareId = null; + private ?string $lastPublicShareId = null; - /** - * @var int - */ - private $savedShareId = null; + private ?int $savedShareId = null; - /** - * @var int - */ - private $localLastShareTime = null; + private ?float $localLastShareTime = null; /** * Defines the fields that can be provided in a share request. - * - * @var array */ - private $shareFields = [ + private array $shareFields = [ 'path', 'name', 'publicUpload', 'password', 'expireDate', 'expireDateAsString', 'permissions', 'shareWith', 'shareType' ]; @@ -110,10 +88,8 @@ trait Sharing { * file_parent is not provided by OCIS/reva. * There are no known clients that use file_parent. * The acceptance tests do not test for file_parent. - * - * @var array fields that are possible in a share response */ - private $shareResponseFields = [ + private array $shareResponseFields = [ 'id', 'share_type', 'uid_owner', 'displayname_owner', 'stime', 'parent', 'expiration', 'token', 'uid_file_owner', 'displayname_file_owner', 'path', 'item_type', 'mimetype', 'storage_id', 'storage', 'item_source', @@ -125,7 +101,7 @@ trait Sharing { * Contains information about the public links that have been created with the webUI. * Each entry in the array has a "name", "url" and "path". */ - private $createdPublicLinks = []; + private array $createdPublicLinks = []; /** * @return array @@ -243,9 +219,9 @@ public function resetLastShareInfoForUser(string $user):void { } /** - * @return int + * @return float|null */ - public function getLocalLastShareTime():int { + public function getLocalLastShareTime(): ?float { return $this->localLastShareTime; } @@ -262,7 +238,7 @@ public function getServerLastShareTime():int { * @return string */ public function getSharesEndpointPath(?string $postfix = ''):string { - return "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares$postfix"; + return "/apps/files_sharing/api/v$this->sharingApiVersion/shares$postfix"; } /** @@ -307,7 +283,7 @@ private function splitPermissionsString(string $str):array { */ public function getServerShareTimeFromLastResponse():int { $stime = $this->getResponseXml(null, __METHOD__)->xpath("//stime"); - if ((bool) $stime) { + if ($stime) { return (int) $stime[0]; } throw new Exception("Last share time (i.e. 'stime') could not be found in the response."); @@ -330,7 +306,7 @@ private function waitToCreateShare():void { /** * @param string $user * @param TableNode|null $body - * TableNode $body should not have any heading and can have following rows | + * TableNode $body should not have any heading and can have the following rows | * | path | The folder or file path to be shared | * | name | A (human-readable) name for the share, | * | | which can be up to 64 characters in length. | @@ -354,7 +330,7 @@ private function waitToCreateShare():void { * | | (default: 31, for public shares: 1) | * | | Pass either the (total) number, | * | | or the keyword, | - * | | or an comma separated list of keywords | + * | | or a comma separated list of keywords | * | shareWith | The user or group id with which the file should | * | | be shared. | * | shareType | The type of the share. This can be one of: | @@ -876,58 +852,6 @@ public function getMimeTypeOfLastSharedFile():string { return \json_decode(\json_encode($this->getLastShareData()->data->mimetype), true)[0]; } - /** - * @param string $url - * @param string|null $user - * @param string|null $password - * @param string|null $mimeType - * - * @return void - */ - private function checkDownload( - string $url, - ?string $user = null, - ?string $password = null, - ?string $mimeType = null - ) { - $password = $this->getActualPassword($password); - $headers = ['X-Requested-With' => 'XMLHttpRequest']; - $this->response = HttpRequestHelper::get( - $url, - $this->getStepLineRef(), - $user, - $password, - $headers - ); - Assert::assertEquals( - 200, - $this->response->getStatusCode(), - __METHOD__ - . " Expected status code is '200' but got '" - . $this->response->getStatusCode() - . "'" - ); - - $buf = ''; - $body = $this->response->getBody(); - while (!$body->eof()) { - // read everything - $buf .= $body->read(8192); - } - $body->close(); - - if ($mimeType !== null) { - $finfo = new finfo; - Assert::assertEquals( - $mimeType, - $finfo->buffer($buf, FILEINFO_MIME_TYPE), - __METHOD__ - . " Expected mimeType '$mimeType' but got '" - . $finfo->buffer($buf, FILEINFO_MIME_TYPE) - ); - } - } - /** * @Then /^user "([^"]*)" should not be able to create a public link share of (file|folder) "([^"]*)" using the sharing API$/ * @@ -1912,8 +1836,7 @@ public function userHasSharedFileWithGroupUsingTheSharingApi( true ); - Assert::assertEquals( - true, + Assert::assertTrue( $this->isUserOrGroupInSharedData($group, "group", $permissions), __METHOD__ . " Could not assert that user '$user' has shared '$filepath' with group '$group' with permissions '$permissions'" @@ -2070,8 +1993,7 @@ public function deleteLastShareUsingSharingApi(string $user, string $sharer = nu $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, "DELETE", - $url, - null + $url ); } @@ -2197,7 +2119,7 @@ public function userGetsInfoOfLastPublicLinkShareUsingTheSharingApi(string $user /** * @Then /^as "([^"]*)" the info about the last share by user "([^"]*)" with user "([^"]*)" should include$/ * - * @param string $requestor + * @param string $requester * @param string $sharer * @param string $sharee * @param TableNode $table @@ -2206,12 +2128,12 @@ public function userGetsInfoOfLastPublicLinkShareUsingTheSharingApi(string $user * @throws Exception */ public function asLastShareInfoAboutUserSharingWithUserShouldInclude( - string $requestor, - string $sharer, - string $sharee, + string $requester, + string $sharer, + string $sharee, TableNode $table ) { - $this->userGetsInfoOfLastShareUsingTheSharingApi($requestor); + $this->userGetsInfoOfLastShareUsingTheSharingApi($requester); $this->ocsContext->assertOCSResponseIndicatesSuccess(); $this->checkFieldsOfLastResponseToUser($sharer, $sharee, $table); } @@ -2302,7 +2224,7 @@ public function getLastShareId():?string { * @return string|null */ public function getLastShareIdForUser(string $user):?string { - if ($user === null) { + if ($user === "") { throw new Exception( __METHOD__ . " user not specified. Probably no user or group shares have been created yet in the test scenario." ); @@ -2375,8 +2297,7 @@ public function userGetsAllTheSharesSharedWithHimUsingTheSharingApi(string $user $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - $url, - null + $url ); } @@ -2409,8 +2330,7 @@ public function userGetsFilteredSharesSharedWithHimUsingTheSharingApi(string $us 'GET', $this->getSharesEndpointPath( "?shared_with_me=true" . $pendingClause . "&share_types=" . $rawShareTypes - ), - null + ) ); } @@ -2425,12 +2345,11 @@ public function userGetsFilteredSharesSharedWithHimUsingTheSharingApi(string $us public function userGetsAllSharesSharedWithHimFromFileOrFolderUsingTheProvisioningApi(string $user, string $path):void { $user = $this->getActualUsername($user); $url = "/apps/files_sharing/api/" - . "v{$this->sharingApiVersion}/shares?shared_with_me=true&path=$path"; + . "v$this->sharingApiVersion/shares?shared_with_me=true&path=$path"; $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, 'GET', - $url, - null + $url ); } @@ -2992,17 +2911,13 @@ public function userDownloadsFailWithMessage(string $fileName, string $user, PyS $user = $this->getActualUsername($user); $this->downloadFileAsUserUsingPassword($user, $fileName); $receivedErrorMessage = $this->getResponseXml(null, __METHOD__)->xpath('//s:message'); - if ((bool) $errorMessage) { - Assert::assertEquals( - $errorMessage, - (string) $receivedErrorMessage[0], - "Expected error message was '$errorMessage' but got '" - . (string) $receivedErrorMessage[0] - . "'" - ); - return; - } - throw new Exception("No 's:message' element found on the response."); + Assert::assertEquals( + $errorMessage, + (string) $receivedErrorMessage[0], + "Expected error message was '$errorMessage' but got '" + . $receivedErrorMessage[0] + . "'" + ); } /** @@ -3060,7 +2975,7 @@ public function removeAllSharesFromResource(string $user, string $fileName):void $user, $this->getPasswordForUser($user), "DELETE", - $this->getSharesEndpointPath("/{$id}"), + $this->getSharesEndpointPath("/$id"), $this->getStepLineRef(), [], $this->ocsApiVersion @@ -3121,7 +3036,7 @@ public function userHasRemovedAllSharesFromTheFileNamed(string $user, string $fi * Returns shares of a file or folder as a SimpleXMLElement * * Note: the "single" SimpleXMLElement may contain one or more actual - * shares (to users, groups or public links etc). If you access an item directly, + * shares (to users, groups or public links etc.). If you access an item directly, * for example, getShares()->id, then the value of "id" for the first element * will be returned. To access all the elements, you can loop through the * returned SimpleXMLElement with "foreach" - it will act like a PHP array @@ -3173,7 +3088,7 @@ public function checkPublicShares(string $user, string $path, ?TableNode $TableN (string) $elementResponded->path[0], __METHOD__ . " Expected '${expectedElementsArray['path']}' but got '" - . (string) $elementResponded->path[0] + . $elementResponded->path[0] . "'" ); Assert::assertEquals( @@ -3181,7 +3096,7 @@ public function checkPublicShares(string $user, string $path, ?TableNode $TableN (string) $elementResponded->permissions[0], __METHOD__ . " Expected '${expectedElementsArray['permissions']}' but got '" - . (string) $elementResponded->permissions[0] + . $elementResponded->permissions[0] . "'" ); $nameFound = true; @@ -3256,8 +3171,7 @@ public function deletePublicLinkShareUsingTheSharingApi( $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, "DELETE", - $url, - null + $url ); } @@ -3363,19 +3277,19 @@ public function userReactsToShareOfferedBy(string $user, string $action, string $shareId, __METHOD__ . " could not find share $share, offered by $offeredBy to $user" ); - $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}" . + $url = "/apps/files_sharing/api/v$this->sharingApiVersion" . "/shares/pending/$shareId"; if (\substr($action, 0, 7) === "decline") { $httpRequestMethod = "DELETE"; - } elseif (\substr($action, 0, 6) === "accept") { + } else { + // do a POST to accept the share $httpRequestMethod = "POST"; } $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, $httpRequestMethod, - $url, - null + $url ); $this->pushToLastStatusCodesArrays(); } @@ -3421,19 +3335,19 @@ public function userReactsToShareWithShareIDOfferedBy(string $user, string $acti $shareId = $this->substituteInLineCodes($share_id, $user); - $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}" . + $url = "/apps/files_sharing/api/v$this->sharingApiVersion" . "/shares/pending/$shareId"; if (\substr($action, 0, 7) === "decline") { $httpRequestMethod = "DELETE"; - } elseif (\substr($action, 0, 6) === "accept") { + } else { + // do a POST to accept the share $httpRequestMethod = "POST"; } $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, $httpRequestMethod, - $url, - null + $url ); } @@ -3452,8 +3366,7 @@ public function userHasReactedToShareOfferedBy(string $user, string $action, str $this->userReactsToShareOfferedBy($user, $action, $share, $offeredBy); if ($action === 'declined') { $actionText = 'decline'; - } - if ($action === 'accepted') { + } else { $actionText = 'accept'; } $this->theHTTPStatusCodeShouldBe( @@ -3711,15 +3624,13 @@ private function getAllSharesSharedWithUser(string $user, ?string $state = "all" throw new InvalidArgumentException( __METHOD__ . ' invalid "state" given' ); - break; } $url = $this->getSharesEndpointPath("?format=json&shared_with_me=true&state=$stateCode"); $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( $user, "GET", - $url, - null + $url ); if ($this->response->getStatusCode() !== 200) { throw new Exception( @@ -4044,7 +3955,7 @@ public function expireShare(string $shareId = null):void { $adminUser, $this->getAdminPassword(), 'POST', - "/apps/testing/api/v1/expire-share/{$shareId}", + "/apps/testing/api/v1/expire-share/$shareId", $this->getStepLineRef(), [], $this->getOcsApiVersion() diff --git a/tests/acceptance/features/bootstrap/TUSContext.php b/tests/acceptance/features/bootstrap/TUSContext.php index aa5681f15f10..ed53c0e4572f 100644 --- a/tests/acceptance/features/bootstrap/TUSContext.php +++ b/tests/acceptance/features/bootstrap/TUSContext.php @@ -36,13 +36,9 @@ * TUS related test steps */ class TUSContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; - private $resourceLocation = null; + private ?string $resourceLocation = null; /** * @When user :user creates a new TUS resource on the WebDAV API with these headers: @@ -281,7 +277,7 @@ public function userUploadsAFileWithContentInChunksUsingTus( * @param string $user * @param string $source * @param string $destination - * @param string $mtime Time in human readable format is taken as input which is converted into milliseconds that is used by API + * @param string $mtime Time in human-readable format is taken as input which is converted into milliseconds that is used by API * * @return void * @throws Exception @@ -456,7 +452,7 @@ public function userUploadsChunkFileWithChecksum(string $user, string $offset, s */ public function userHasUploadedChunkFileWithChecksum(string $user, string $offset, string $data, string $checksum):void { $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum); - $this->featureContext->theHTTPStatusCodeShouldBe(204, ""); + $this->featureContext->theHTTPStatusCodeShouldBe(204); } /** diff --git a/tests/acceptance/features/bootstrap/TagsContext.php b/tests/acceptance/features/bootstrap/TagsContext.php index f86b9baeec10..86e74b039baf 100644 --- a/tests/acceptance/features/bootstrap/TagsContext.php +++ b/tests/acceptance/features/bootstrap/TagsContext.php @@ -35,16 +35,8 @@ * Acceptance test steps related to testing tags features */ class TagsContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * @var array - */ - private $createdTags = []; + private FeatureContext $featureContext; + private array $createdTags = []; /** * @param string $user @@ -220,7 +212,7 @@ public function theAdministratorCreatesATagWithNameSending(string $type, string if ($stringsOrNumbers === "true-false-strings") { $useTrueFalseStrings = true; } else { - $useTrueFalseStrings = true; + $useTrueFalseStrings = false; } $this->createTagWithNameAsAdmin( @@ -782,7 +774,7 @@ public function theTagHasGroup(string $type, string $tagName, string $groups):vo Assert::assertEquals( $groupsOfTag[0], $groups, - "Tag has groups '{$groupsOfTag[0]}' instead of the expected '$groups'" + "Tag has groups '$groupsOfTag[0]' instead of the expected '$groups'" ); } @@ -797,7 +789,7 @@ public function theTagHasGroup(string $type, string $tagName, string $groups):vo */ public function tagsShouldExistForUser(int $count, string $user):void { Assert::assertEquals( - (int) $count, + $count, \count($this->requestTagsforUser($user)), __METHOD__ . " Expected $count tags, got " @@ -824,14 +816,14 @@ public function findTagIdByName(string $name):int { * @param string $propertyName * @param string $propertyValue * - * @return ResponseInterface + * @return void */ private function sendProppatchToSystemtags( string $user, string $tagDisplayName, string $propertyName, string $propertyValue - ):ResponseInterface { + ):void { $renamedUser = $this->featureContext->getActualUsername($user); $tagID = $this->findTagIdByName($tagDisplayName); $response = WebDavHelper::proppatch( @@ -847,7 +839,6 @@ private function sendProppatchToSystemtags( "systemtags" ); $this->featureContext->setResponse($response); - return $response; } /** diff --git a/tests/acceptance/features/bootstrap/TransferOwnershipContext.php b/tests/acceptance/features/bootstrap/TransferOwnershipContext.php index 67fabe83bce0..8a8b466a6a76 100644 --- a/tests/acceptance/features/bootstrap/TransferOwnershipContext.php +++ b/tests/acceptance/features/bootstrap/TransferOwnershipContext.php @@ -29,19 +29,10 @@ * Steps that relate to transferring ownership */ class TransferOwnershipContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OccContext - */ - private $occContext; + private FeatureContext $featureContext; + private OccContext $occContext; - private $lastTransferPath; + private ?string $lastTransferPath; /** * @return string @@ -229,7 +220,7 @@ public function asFileOrFolderShouldNotExist(string $user, string $entry, string $user = $this->featureContext->getActualUsername($user); //the entry in the folder should not exist //but the last received transfer folder itself should exist - //that would help against snakeoil tests if testing a nonexistent folder + //that would help against snake-oil tests if testing a nonexistent folder $this->featureContext->asFileOrFolderShouldExist( $user, $entry, diff --git a/tests/acceptance/features/bootstrap/TrashbinContext.php b/tests/acceptance/features/bootstrap/TrashbinContext.php index ed0e90c81426..3c06eae5ff65 100644 --- a/tests/acceptance/features/bootstrap/TrashbinContext.php +++ b/tests/acceptance/features/bootstrap/TrashbinContext.php @@ -33,17 +33,8 @@ * Trashbin context */ class TrashbinContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var OccContext - */ - private $occContext; + private FeatureContext $featureContext; + private OccContext $occContext; /** * @When user :user empties the trashbin using the trashbin API @@ -448,11 +439,6 @@ public function userTriesToListTheTrashbinContentForUserUsingPassword(string $as */ public function theLastWebdavResponseShouldContainFollowingElements(TableNode $elements):void { $files = $this->getTrashbinContentFromResponseXml($this->featureContext->getResponseXmlObject()); - if (!($elements instanceof TableNode)) { - throw new InvalidArgumentException( - '$expectedElements has to be an instance of TableNode' - ); - } $elementRows = $elements->getHash(); foreach ($elementRows as $expectedElement) { $found = false; @@ -508,7 +494,7 @@ public function theLastWebdavResponseShouldNotContainFollowingElements(TableNode * @throws Exception */ public function userTriesToDeleteFromTrashbinOfUser(string $asUser, string $path, string $user):void { - $numItemsDeleted = $this->tryToDeleteFileFromTrashbin($user, $path, $asUser); + $this->tryToDeleteFileFromTrashbin($user, $path, $asUser); } /** @@ -600,7 +586,10 @@ public function tryToDeleteFileFromTrashbin(?string $user, ?string $originalPath $numItemsDeleted = 0; foreach ($listing as $entry) { - if ($entry['original-location'] === $originalPath) { + // The entry for the trashbin root can have original-location null. + // That is reasonable, because the trashbin root is not something that can be restored. + $originalLocation = $entry['original-location'] ?? ''; + if (\trim($originalLocation, '/') === $originalPath) { $trashItemHRef = $this->convertTrashbinHref($entry['href']); $response = $this->featureContext->makeDavRequest( $asUser, @@ -690,6 +679,8 @@ public function asFileOrFolderExistsInTrash(?string $user, ?string $path):void { if (\count($sections) !== 1) { // TODO: handle deeper structures $listing = $this->listTrashbinFolderCollection($user, \basename(\rtrim($firstEntry['href'], '/'))); + } else { + $listing = []; } if ($techPreviewHadToBeEnabled) { @@ -790,10 +781,10 @@ private function sendUndeleteRequest(string $user, string $trashItemHRef, string * @param string|null $asUser - To send request as another user * @param string|null $password * - * @return ResponseInterface|null + * @return void * @throws Exception */ - private function restoreElement(string $user, string $originalPath, ?string $destinationPath = null, bool $throwExceptionIfNotFound = true, ?string $asUser = null, ?string $password = null):?ResponseInterface { + private function restoreElement(string $user, string $originalPath, ?string $destinationPath = null, bool $throwExceptionIfNotFound = true, ?string $asUser = null, ?string $password = null):void { $asUser = $asUser ?? $user; $listing = $this->listTrashbinFolder($user); $originalPath = \trim($originalPath, '/'); @@ -802,13 +793,14 @@ private function restoreElement(string $user, string $originalPath, ?string $des } foreach ($listing as $entry) { if ($entry['original-location'] === $originalPath) { - return $this->sendUndeleteRequest( + $this->sendUndeleteRequest( $user, $entry['href'], $destinationPath, $asUser, $password ); + return; } } // The requested element to restore was not even in the trashbin. @@ -820,7 +812,6 @@ private function restoreElement(string $user, string $originalPath, ?string $des . " cannot restore from trashbin because no element was found for user $user at original path $originalPath" ); } - return null; } /** @@ -1038,7 +1029,7 @@ public function followingElementsAreNotInTrashCheckingOriginalPath( TableNode $table ):void { $this->featureContext->verifyTableNodeColumns($table, ["path"]); - $paths = $table->getHash($table); + $paths = $table->getHash(); foreach ($paths as $originalPath) { $this->elementIsNotInTrashCheckingOriginalPath($user, $originalPath["path"]); @@ -1059,7 +1050,7 @@ public function followingElementsAreInTrashCheckingOriginalPath( TableNode $table ):void { $this->featureContext->verifyTableNodeColumns($table, ["path"]); - $paths = $table->getHash($table); + $paths = $table->getHash(); foreach ($paths as $originalPath) { $this->elementIsInTrashCheckingOriginalPath($user, $originalPath["path"]); @@ -1122,7 +1113,7 @@ public function theDeletedFileFolderShouldHaveCorrectDeletionMtimeInTheResponse( $responseMtime = ''; foreach ($files as $file) { - if (\ltrim((string)$resource, "/") === \ltrim((string)$file['original-location'], "/")) { + if (\ltrim($resource, "/") === \ltrim((string)$file['original-location'], "/")) { $responseMtime = $file['mtime']; $mtime_difference = \abs((int)\trim((string)$expectedMtime) - (int)\trim($responseMtime)); @@ -1176,7 +1167,7 @@ public function theAdministratorHasSetFollowingDirectoriesToBeSkippedFromTrashbi * @return void * @throws Exception */ - public function theAdministratorHasSetTrashbinSkipSizethreshold(string $threshold) { + public function theAdministratorHasSetTrashbinSkipSizeThreshold(string $threshold) { $this->featureContext->runOcc(['config:system:set', 'trashbin_skip_size_threshold', '--value=' . $threshold]); } } diff --git a/tests/acceptance/features/bootstrap/WebDav.php b/tests/acceptance/features/bootstrap/WebDav.php index 5aa134b2bde9..9f8cd2b7d596 100644 --- a/tests/acceptance/features/bootstrap/WebDav.php +++ b/tests/acceptance/features/bootstrap/WebDav.php @@ -38,89 +38,58 @@ * WebDav functions */ trait WebDav { - /** - * @var string - */ - private $davPath = "remote.php/webdav"; - - /** - * @var boolean - */ - private $usingOldDavPath = true; - - /** - * @var boolean - */ - private $usingSpacesDavPath = false; + private string $davPath = "remote.php/webdav"; + private bool $usingOldDavPath = true; + private bool $usingSpacesDavPath = false; /** * @var ResponseInterface[] */ - private $uploadResponses; - - /** - * @var integer - */ - private $storedFileID = null; - - /** - * @var int - */ - private $lastUploadDeleteTime = null; + private array $uploadResponses; + private ?string $storedFileID = null; + private ?int $lastUploadDeleteTime = null; /** * a variable that contains the DAV path without "remote.php/(web)dav" * when setting $this->davPath directly by usingDavPath() - * - * @var string */ - private $customDavPath = null; + private ?string $customDavPath = null; - private $previousAsyncSetting = null; + private ?string $previousAsyncSetting = null; - private $previousDavSlowdownSetting = null; + private ?string + $previousDavSlowdownSetting = null; - /** - * @var int - */ - private $currentDavSlowdownSettingSeconds = 0; + private int $currentDavSlowdownSettingSeconds = 0; /** * response content parsed from XML to an array - * - * @var array */ - private $responseXml = []; + private array $responseXml = []; /** * add resource created by admin in an array * This array is used while cleaning up the resource created by admin during test run * As of now it tracks only for (files|folder) creation * This can be expanded and modified to track other actions like (upload, deleted ..) - * - * @var array */ - private $adminResources = []; + private array $adminResources = []; /** * response content parsed into a SimpleXMLElement - * - * @var SimpleXMLElement */ - private $responseXmlObject; + private ?SimpleXMLElement $responseXmlObject; - private $httpRequestTimeout = 0; + private int $httpRequestTimeout = 0; - private $chunkingToUse = null; + private ?int $chunkingToUse = null; /** * The ability to do requests with depth infinity is disabled by default. * This remembers when the setting dav.propfind.depth_infinity has been * enabled, so that test code can make use of it as appropriate. - * - * @var bool */ - private $davPropfindDepthInfinityEnabled = false; + private bool $davPropfindDepthInfinityEnabled = false; /** * @return void @@ -511,14 +480,14 @@ public function downloadPreviews(string $user, ?string $path, ?string $doDavRequ } /** - * @Then the number of noncurrent versions should be :arg1 + * @Then the number of non-current versions should be :arg1 * * @param int $number * * @return void * @throws Exception */ - public function theNumberOfNoncurrentVersionsShouldBe(int $number):void { + public function theNumberOfNonCurrentVersionsShouldBe(int $number):void { $resXml = $this->getResponseXmlObject(); if ($resXml === null) { $resXml = HttpRequestHelper::getResponseXml( @@ -603,7 +572,7 @@ public function triggerAsyncUpload(string $enabledOrDisabled):void { * @return void */ public function setHttpTimeout(int $timeout):void { - $this->httpRequestTimeout = (int) $timeout; + $this->httpRequestTimeout = $timeout; } /** @@ -732,11 +701,7 @@ public function userMovesEntriesUsingTheAPI( foreach ($table->getHash() as $row) { // Allow the "filename" column to be optionally be called "foldername" // to help readability of scenarios that test moving folders - if (isset($row['foldername'])) { - $targetName = $row['foldername']; - } else { - $targetName = $row['filename']; - } + $targetName = $row['foldername'] ?? $row['filename']; $this->userMovesFileUsingTheAPI( $user, $fileSource, @@ -1205,7 +1170,7 @@ public function theContentInTheResponseShouldMatchTheFollowingContent(PyStringNo * @return void * */ - public function theDownloadedContentForMultipartByterangeShouldBe(int $statusCode, PyStringNode $content):void { + public function theDownloadedContentForMultipartByteRangeShouldBe(int $statusCode, PyStringNode $content):void { $actualStatusCode = $this->response->getStatusCode(); if ($actualStatusCode === $statusCode) { $actualContent = (string) $this->response->getBody(); @@ -1605,14 +1570,11 @@ public function downloadFileAsUserUsingPassword( public function publicGetsSizeOfLastSharedPublicLinkUsingTheWebdavApi():void { $tokenArray = $this->getLastPublicShareData()->data->token; $token = (string)$tokenArray[0]; - $url = $this->getBaseUrl() . "/remote.php/dav/public-files/{$token}"; + $url = $this->getBaseUrl() . "/remote.php/dav/public-files/$token"; $this->response = HttpRequestHelper::sendRequest( $url, $this->getStepLineRef(), - "PROPFIND", - null, - null, - null + "PROPFIND" ); } @@ -2397,7 +2359,7 @@ public function userUploadsAFileAsyncToWithChunks( } /** - * sets the chunking version from human readable format + * sets the chunking version from human-readable format * * @param string $version (no|v1|v2|new|old) * @@ -3126,7 +3088,7 @@ public function userUploadsFollowingFilesWithContentTo( * @param string $user * @param string $source * @param string $destination - * @param string $mtime Time in human readable format is taken as input which is converted into milliseconds that is used by API + * @param string $mtime Time in human-readable format is taken as input which is converted into milliseconds that is used by API * * @return void * @throws Exception @@ -3490,7 +3452,7 @@ public function userHasDeletedFile(string $user, string $deletedOrUnshared, stri $this->userDeletesFile($user, $entry); // If the file or folder was there and got deleted then we get a 204 // That is good and the expected status - // If the file or folder was already not there then then we get a 404 + // If the file or folder was already not there then we get a 404 // That is not expected. Scenarios that use "Given user has deleted..." // should only be using such steps when it is a file that exists and needs // to be deleted. @@ -3633,7 +3595,7 @@ public function userOnDeletesFile(string $user, string $server, string $file):vo public function userOnHasDeletedFile(string $user, string $server, string $deletedOrUnshared, string $fileOrFolder, string $entry):void { $this->userOnDeletesFile($user, $server, $entry); // If the file was there and got deleted then we get a 204 - // If the file was already not there then then get a 404 + // If the file was already not there then we get a 404 // Either way, the outcome of the "given" step is OK if ($deletedOrUnshared === "deleted") { $deleteText = "delete"; @@ -4529,11 +4491,7 @@ public function theFollowingHeadersShouldNotBeSet(TableNode $table):void { $headerName = $header['header']; $headerValue = $this->response->getHeader($headerName); //Note: getHeader returns an empty array if the named header does not exist - if (isset($headerValue[0])) { - $headerValue0 = $headerValue[0]; - } else { - $headerValue0 = ''; - } + $headerValue0 = $headerValue[0] ?? ''; Assert::assertEmpty( $headerValue, "header $headerName should not exist " . @@ -4865,7 +4823,7 @@ public function userFileShouldHaveStoredId(string $user, string $fileOrFolder, s $currentFileID, $this->storedFileID, __METHOD__ - . " User '$user' $fileOrFolder '$path' does not have the previously stored id '{$this->storedFileID}', but has '$currentFileID'." + . " User '$user' $fileOrFolder '$path' does not have the previously stored id '$this->storedFileID', but has '$currentFileID'." ); } @@ -5025,11 +4983,11 @@ public function propfindResultShouldContainNumEntries(int $numFiles):void { $multistatusResults = []; } Assert::assertEquals( - (int) $numFiles, + $numFiles, \count($multistatusResults), __METHOD__ . " Expected result to contain '" - . (int) $numFiles + . $numFiles . "' files/entries, but got '" . \count($multistatusResults) . "' files/entries." @@ -5249,7 +5207,7 @@ public function getNumberOfEntriesInPropfindResponse( * * @return array */ - public function getMultistatusResultFromPropfindResult( + public function getMultiStatusResultFromPropfindResult( ?string $user = null ):array { //if we are using that step the second time in a scenario e.g. 'But ... should not' @@ -5342,17 +5300,15 @@ public function findEntryFromPropfindResponse( } $multistatusResults = $this->getMultistatusResultFromPropfindResult($user); $results = []; - if ($multistatusResults !== null) { - foreach ($multistatusResults as $multistatusResult) { - $entryPath = $multistatusResult['value'][0]['value']; - $entryName = \str_replace($topWebDavPath, "", $entryPath); - $entryName = \rawurldecode($entryName); - $entryName = \trim($entryName, "/"); - if ($trimmedEntryNameToSearch === $entryName) { - return $multistatusResult; - } - \array_push($results, $entryName); + foreach ($multistatusResults as $multistatusResult) { + $entryPath = $multistatusResult['value'][0]['value']; + $entryName = \str_replace($topWebDavPath, "", $entryPath); + $entryName = \rawurldecode($entryName); + $entryName = \trim($entryName, "/"); + if ($trimmedEntryNameToSearch === $entryName) { + return $multistatusResult; } + \array_push($results, $entryName); } if ($entryNameToSearch === null) { return $results; @@ -5459,7 +5415,7 @@ public function theAdministratorHasEnabledTheFileVersionStorage(string $enabledO } /** - * @Then the author of the noncurrent version with index :index should be :expectedUsername + * @Then the author of the non-current version with index :index should be :expectedUsername * * @param string $index * @param string $expectedUsername @@ -5467,7 +5423,7 @@ public function theAdministratorHasEnabledTheFileVersionStorage(string $enabledO * @return void * @throws Exception */ - public function theAuthorOfNoncurrentVersionFile(string $index, string $expectedUsername): void { + public function theAuthorOfNonCurrentVersionFile(string $index, string $expectedUsername): void { $expectedUserDisplayName = $this->getUserDisplayName($expectedUsername); $resXml = $this->getResponseXmlObject(); if ($resXml === null) { @@ -5482,7 +5438,7 @@ public function theAuthorOfNoncurrentVersionFile(string $index, string $expected $xmlPart = $resXml->xpath("//oc:meta-version-edited-by"); $authors = []; foreach ($xmlPart as $idx => $author) { - // The first element is the root path element (current version) which is not a noncurrent version + // The first element is the root path element (current version) which is not a non-current version // So skipping it if ($idx !== 0) { $authors[] = $author->__toString(); @@ -5506,7 +5462,7 @@ public function theAuthorOfNoncurrentVersionFile(string $index, string $expected $xmlPart = $resXml->xpath("//oc:meta-version-edited-by-name"); $displaynames = []; foreach ($xmlPart as $idx => $displayname) { - // The first element is the root path element (current version) which is not a noncurrent version + // The first element is the root path element (current version) which is not a non-current version // So skipping it if ($idx !== 0) { $displaynames[] = $displayname->__toString(); diff --git a/tests/acceptance/features/bootstrap/WebDavLockingContext.php b/tests/acceptance/features/bootstrap/WebDavLockingContext.php index dc9b92e2f938..34ba53547af9 100644 --- a/tests/acceptance/features/bootstrap/WebDavLockingContext.php +++ b/tests/acceptance/features/bootstrap/WebDavLockingContext.php @@ -36,23 +36,14 @@ * context containing API steps needed for the locking mechanism of webdav */ class WebDavLockingContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var PublicWebDavContext - */ - private $publicWebDavContext; + private FeatureContext $featureContext; + private PublicWebDavContext $publicWebDavContext; /** * * @var string[][] */ - private $tokenOfLastLock = []; + private array $tokenOfLastLock = []; /** * @@ -65,11 +56,11 @@ class WebDavLockingContext implements Context { * @return void */ private function lockFile( - $user, - $file, + string $user, + string $file, TableNode $properties, - $public = false, - $expectToSucceed = true + bool $public = false, + bool $expectToSucceed = true ) { $user = $this->featureContext->getActualUsername($user); $baseUrl = $this->featureContext->getBaseUrl(); @@ -131,7 +122,7 @@ private function lockFile( * * @return void */ - public function lockFileUsingWebDavAPI($user, $file, TableNode $properties) { + public function lockFileUsingWebDavAPI(string $user, string $file, TableNode $properties) { $this->lockFile($user, $file, $properties, false, false); } @@ -144,8 +135,8 @@ public function lockFileUsingWebDavAPI($user, $file, TableNode $properties) { * * @return void */ - public function userHasLockedFile($user, $file, TableNode $properties) { - $this->lockFile($user, $file, $properties, false, true); + public function userHasLockedFile(string $user, string $file, TableNode $properties) { + $this->lockFile($user, $file, $properties); } /** @@ -190,7 +181,7 @@ public function publicLocksLastSharedFile(TableNode $properties) { * @return void */ public function publicHasLockedFileLastSharedFolder( - $file, + string $file, TableNode $properties ) { $this->lockFile( @@ -211,8 +202,8 @@ public function publicHasLockedFileLastSharedFolder( * @return void */ public function publicLocksFileLastSharedFolder( - $file, - $publicWebDAVAPIVersion, + string $file, + string $publicWebDAVAPIVersion, TableNode $properties ) { $this->lockFile( @@ -232,7 +223,7 @@ public function publicLocksFileLastSharedFolder( * * @return void */ - public function unlockLastLockUsingWebDavAPI($user, $file) { + public function unlockLastLockUsingWebDavAPI(string $user, string $file) { $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( $user, $file, @@ -251,9 +242,9 @@ public function unlockLastLockUsingWebDavAPI($user, $file) { * @return void */ public function unlockItemWithLastLockOfOtherItemUsingWebDavAPI( - $user, - $itemToUnlock, - $itemToUseLockOf + string $user, + string $itemToUnlock, + string $itemToUseLockOf ) { $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( $user, @@ -273,9 +264,9 @@ public function unlockItemWithLastLockOfOtherItemUsingWebDavAPI( * @return void */ public function unlockItemWithLastPublicLockOfOtherItemUsingWebDavAPI( - $user, - $itemToUnlock, - $itemToUseLockOf + string $user, + string $itemToUnlock, + string $itemToUseLockOf ) { $lockOwner = $this->featureContext->getLastPublicShareToken(); $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( @@ -291,14 +282,14 @@ public function unlockItemWithLastPublicLockOfOtherItemUsingWebDavAPI( * @param string $user * @param string $itemToUnlock * - * @return int|void + * @return int * * @throws Exception|GuzzleException */ private function countLockOfResources( string $user, string $itemToUnlock - ) { + ): int { $user = $this->featureContext->getActualUsername($user); $baseUrl = $this->featureContext->getBaseUrl(); $password = $this->featureContext->getPasswordForUser($user); @@ -340,11 +331,11 @@ private function countLockOfResources( * @throws Exception|GuzzleException */ public function hasUnlockItemWithTheLastCreatedLock( - $user, - $itemToUnlock, - $lockOwner, - $itemToUseLockOf, - $public = false + string $user, + string $itemToUnlock, + string $lockOwner, + string $itemToUseLockOf, + bool $public = false ) { $lockCount = $this->countLockOfResources($user, $itemToUnlock); @@ -424,9 +415,9 @@ public function unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( * @return void */ public function unlockItemAsPublicWithLastLockOfUserAndItemUsingWebDavAPI( - $itemToUnlock, - $lockOwner, - $itemToUseLockOf + string $itemToUnlock, + string $lockOwner, + string $itemToUseLockOf ) { $user = $this->featureContext->getLastPublicShareToken(); $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( @@ -445,7 +436,7 @@ public function unlockItemAsPublicWithLastLockOfUserAndItemUsingWebDavAPI( * * @return void */ - public function unlockItemAsPublicUsingWebDavAPI($itemToUnlock) { + public function unlockItemAsPublicUsingWebDavAPI(string $itemToUnlock) { $user = $this->featureContext->getLastPublicShareToken(); $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI( $user, @@ -467,10 +458,10 @@ public function unlockItemAsPublicUsingWebDavAPI($itemToUnlock) { * @return void */ public function moveItemSendingLockToken( - $user, - $fileSource, - $fileDestination, - $itemToUseLockOf + string $user, + string $fileSource, + string $fileDestination, + string $itemToUseLockOf ) { $this->moveItemSendingLockTokenOfUser( $user, @@ -493,11 +484,11 @@ public function moveItemSendingLockToken( * @return void */ public function moveItemSendingLockTokenOfUser( - $user, - $fileSource, - $fileDestination, - $itemToUseLockOf, - $lockOwner + string $user, + string $fileSource, + string $fileDestination, + string $itemToUseLockOf, + string $lockOwner ) { $user = $this->featureContext->getActualUsername($user); $lockOwner = $this->featureContext->getActualUsername($lockOwner); @@ -533,10 +524,10 @@ public function moveItemSendingLockTokenOfUser( * @return void */ public function userUploadsAFileWithContentTo( - $user, - $content, - $destination, - $itemToUseLockOf + string $user, + string $content, + string $destination, + string $itemToUseLockOf ) { $user = $this->featureContext->getActualUsername($user); $token = $this->tokenOfLastLock[$user][$itemToUseLockOf]; @@ -565,11 +556,11 @@ public function userUploadsAFileWithContentTo( * */ public function publicUploadFileSendingLockTokenOfUser( - $filename, - $content, - $itemToUseLockOf, - $lockOwner, - $publicWebDAVAPIVersion + string $filename, + string $content, + string $itemToUseLockOf, + string $lockOwner, + string $publicWebDAVAPIVersion ) { $lockOwner = $this->featureContext->getActualUsername($lockOwner); $headers = [ @@ -596,10 +587,10 @@ public function publicUploadFileSendingLockTokenOfUser( * @return void */ public function publicUploadFileSendingLockTokenOfPublic( - $filename, - $content, - $itemToUseLockOf, - $publicWebDAVAPIVersion + string $filename, + string $content, + string $itemToUseLockOf, + string $publicWebDAVAPIVersion ) { $lockOwner = $this->featureContext->getLastPublicShareToken(); $this->publicUploadFileSendingLockTokenOfUser( @@ -621,7 +612,7 @@ public function publicUploadFileSendingLockTokenOfPublic( * @return void * @throws GuzzleException */ - public function numberOfLockShouldBeReported($count, $file, $user) { + public function numberOfLockShouldBeReported(int $count, string $file, string $user) { $lockCount = $this->countLockOfResources($user, $file); Assert::assertEquals( $count, @@ -639,7 +630,7 @@ public function numberOfLockShouldBeReported($count, $file, $user) { * * @throws Exception */ - public function groupShouldExistAsLockBreakerGroups($expectedGroup) { + public function groupShouldExistAsLockBreakerGroups(string $expectedGroup) { $baseUrl = $this->featureContext->getBaseUrl(); $admin = $this->featureContext->getAdminUsername(); $password = $this->featureContext->getAdminPassword(); diff --git a/tests/acceptance/features/bootstrap/WebDavPropertiesContext.php b/tests/acceptance/features/bootstrap/WebDavPropertiesContext.php index cb0ad8e13643..01b81270c154 100644 --- a/tests/acceptance/features/bootstrap/WebDavPropertiesContext.php +++ b/tests/acceptance/features/bootstrap/WebDavPropertiesContext.php @@ -34,17 +34,13 @@ * Steps that relate to managing file/folder properties via WebDav */ class WebDavPropertiesContext implements Context { - /** - * - * @var FeatureContext - */ - private $featureContext; + private FeatureContext $featureContext; /** * @var array map with user as key and another map as value, * which has path as key and etag as value */ - private $storedETAG = null; + private array $storedETAG = []; /** * @When /^user "([^"]*)" gets the properties of (?:file|folder|entry) "([^"]*)" using the WebDAV API$/ @@ -815,7 +811,7 @@ public function assertEntryWithHrefMatchingRegExpInResponseToUser(string $expect // expected href should be like: "remote.php/webdav/strängé folder/file.txt" $explodeDecoded = \explode('/', $decodedValue); // get the first item of the expected href. - // i.e remote.php from "remote.php/webdav/strängé folder/file.txt" + // i.e. remote.php from "remote.php/webdav/strängé folder/file.txt" // or dav from "dav/spaces/%spaceid%/C++ file.cpp" $explodeExpected = \explode('/', $expectedHref); $remotePhpIndex = \array_search($explodeExpected[0], $explodeDecoded); diff --git a/tests/acceptance/features/bootstrap/WebUIAdminAppsSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIAdminAppsSettingsContext.php index 7b7fdd851977..73a25e526558 100644 --- a/tests/acceptance/features/bootstrap/WebUIAdminAppsSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIAdminAppsSettingsContext.php @@ -32,13 +32,8 @@ * WebUI AdminAppsSettings context. */ class WebUIAdminAppsSettingsContext extends RawMinkContext implements Context { - private $adminAppsSettingsPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; + private AdminAppsSettingsPage $adminAppsSettingsPage; + private WebUIGeneralContext $webUIGeneralContext; /** * WebUIAdminAdminSettingsContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIAdminEncryptionSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIAdminEncryptionSettingsContext.php index f3fb6751a480..44790d30b93a 100644 --- a/tests/acceptance/features/bootstrap/WebUIAdminEncryptionSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIAdminEncryptionSettingsContext.php @@ -23,7 +23,6 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\MinkExtension\Context\RawMinkContext; -use Page\OwncloudPage; use Page\AdminEncryptionSettingsPage; require_once 'bootstrap.php'; @@ -32,40 +31,17 @@ * Context for admin encryption settings specific webUI steps */ class WebUIAdminEncryptionSettingsContext extends RawMinkContext implements Context { - /** - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var OwncloudPage - */ - private $owncloudPage; - - /** - * - * @var AdminEncryptionSettingsPage - */ - private $adminEncryptionSettingsPage; + private WebUIGeneralContext $webUIGeneralContext; + private AdminEncryptionSettingsPage $adminEncryptionSettingsPage; /** * WebUIAdminEncryptionSettingsContext constructor. * - * @param OwncloudPage $owncloudPage * @param AdminEncryptionSettingsPage $adminEncryptionSettingsPage */ public function __construct( - OwncloudPage $owncloudPage, AdminEncryptionSettingsPage $adminEncryptionSettingsPage ) { - $this->owncloudPage = $owncloudPage; $this->adminEncryptionSettingsPage = $adminEncryptionSettingsPage; } @@ -104,7 +80,6 @@ public function setUpScenario(BeforeScenarioScope $scope):void { // Get the environment $environment = $scope->getEnvironment(); // Get all the contexts you need in this context - $this->featureContext = $environment->getContext('FeatureContext'); $this->webUIGeneralContext = $environment->getContext('WebUIGeneralContext'); } } diff --git a/tests/acceptance/features/bootstrap/WebUIAdminGeneralSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIAdminGeneralSettingsContext.php index 327ab92526c1..dbdc4ed2fac5 100644 --- a/tests/acceptance/features/bootstrap/WebUIAdminGeneralSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIAdminGeneralSettingsContext.php @@ -36,22 +36,12 @@ * WebUI AdminGeneralSettings context. */ class WebUIAdminGeneralSettingsContext extends RawMinkContext implements Context { - private $adminGeneralSettingsPage; + private AdminGeneralSettingsPage $adminGeneralSettingsPage; + private WebUIGeneralContext $webUIGeneralContext; + private FeatureContext $featureContext; - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - private $appParameterValues = null; - private $logLevelValue = null; + private ?array $appParameterValues = null; + private ?string $logLevelValue = null; /** * WebUIAdminAdminSettingsContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIAdminSharingSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIAdminSharingSettingsContext.php index 45adb8f876d1..91cc0b7a29cb 100644 --- a/tests/acceptance/features/bootstrap/WebUIAdminSharingSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIAdminSharingSettingsContext.php @@ -35,19 +35,9 @@ * WebUI AdminSharingSettings context. */ class WebUIAdminSharingSettingsContext extends RawMinkContext implements Context { - private $adminSharingSettingsPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var FeatureContext - */ - private $featureContext; + private AdminSharingSettingsPage $adminSharingSettingsPage; + private WebUIGeneralContext $webUIGeneralContext; + private FeatureContext $featureContext; /** * WebUIAdminSharingSettingsContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIAdminStorageSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIAdminStorageSettingsContext.php index e04ebae05378..68553e55aa73 100644 --- a/tests/acceptance/features/bootstrap/WebUIAdminStorageSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIAdminStorageSettingsContext.php @@ -34,19 +34,9 @@ * WebUI AdminStorageSettings context. */ class WebUIAdminStorageSettingsContext extends RawMinkContext implements Context { - private $adminStorageSettingsPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var FeatureContext - */ - private $featureContext; + private AdminStorageSettingsPage $adminStorageSettingsPage; + private WebUIGeneralContext $webUIGeneralContext; + private FeatureContext $featureContext; /** * WebUIAdminStorageSettingsContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIFileActionsMenuContext.php b/tests/acceptance/features/bootstrap/WebUIFileActionsMenuContext.php index 51144b2e566c..b43555189049 100644 --- a/tests/acceptance/features/bootstrap/WebUIFileActionsMenuContext.php +++ b/tests/acceptance/features/bootstrap/WebUIFileActionsMenuContext.php @@ -31,11 +31,7 @@ * Context for file actions menu */ class WebUIFileActionsMenuContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; + private FilesPage $filesPage; /** * WebUIFileActionsMenuContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIFilesContext.php b/tests/acceptance/features/bootstrap/WebUIFilesContext.php index b0ec9b80f988..2e7a69f13817 100644 --- a/tests/acceptance/features/bootstrap/WebUIFilesContext.php +++ b/tests/acceptance/features/bootstrap/WebUIFilesContext.php @@ -39,7 +39,6 @@ use Page\TrashbinPage; use Page\FilesPageElement\ConflictDialog; use Page\FilesPageElement\FileActionsMenu; -use Page\GeneralExceptionPage; use PHPUnit\Framework\Assert; use SensioLabs\Behat\PageObjectExtension\PageObject\Exception\ElementNotFoundException; use TestHelpers\Asserts\WebDav as WebDavAssert; @@ -52,123 +51,52 @@ * WebUI Files context. */ class WebUIFilesContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var TrashbinPage - */ - private $trashbinPage; - - /** - * - * @var FavoritesPage - */ - private $favoritesPage; - - /** - * - * @var SharedWithYouPage - */ - private $sharedWithYouPage; - - /** - * - * @var SharedByLinkPage - */ - private $sharedByLinkPage; - - /** - * @var SharedWithOthersPage - */ - private $sharedWithOthersPage; - - /** - * - * @var TagsPage - */ - private $tagsPage; - - /** - * - * @var ConflictDialog - */ - private $conflictDialog; - - /** - * - * @var FileActionsMenu - */ - private $openedFileActionMenu; - - /** - * - * @var ExternalStoragePage - */ - private $externalStoragePage; + private FilesPage $filesPage; + private TrashbinPage $trashbinPage; + private FavoritesPage $favoritesPage; + private SharedWithYouPage $sharedWithYouPage; + private SharedByLinkPage $sharedByLinkPage; + private SharedWithOthersPage $sharedWithOthersPage; + private TagsPage $tagsPage; + private ConflictDialog $conflictDialog; + private FileActionsMenu $openedFileActionMenu; + private ExternalStoragePage $externalStoragePage; /** * Table of all files and folders that should have been deleted, stored so * that other steps can use the list to check if the deletion happened correctly * table headings: must be: |name| - * - * @var TableNode */ - private $deletedElementsTable = null; + private ?TableNode $deletedElementsTable = null; /** * Table of all files and folders that should have been moved, stored so * that other steps can use the list to check if the moving happened correctly * table headings: must be: |name| - * - * @var TableNode */ - private $movedElementsTable = null; + private ?TableNode $movedElementsTable = null; /** * variable to remember in which folder we are currently working - * - * @var string */ - private $currentFolder = ""; + private string $currentFolder = ""; /** * variable to remember with which file we are currently working - * - * @var string */ - private $currentFile = ""; + private string $currentFile = ""; /** * variable to remember the path of a received share that has been moved - * - * @var string */ - private $pathOfMovedReceivedShare = ""; + private string $pathOfMovedReceivedShare = ""; - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; + private FeatureContext $featureContext; - private $uploadConflictDialogTitle = "file conflict"; + private WebUIGeneralContext $webUIGeneralContext; - /** - * - * @var GeneralExceptionPage - */ - private $generalExceptionPage; + private string $uploadConflictDialogTitle = "file conflict"; + private FileRow $selectedFileRow; /** * WebUIFilesContext constructor. @@ -181,7 +109,6 @@ class WebUIFilesContext extends RawMinkContext implements Context { * @param TagsPage $tagsPage * @param SharedByLinkPage $sharedByLinkPage * @param SharedWithOthersPage $sharedWithOthersPage - * @param GeneralExceptionPage $generalExceptionPage * @param ExternalStoragePage $externalStoragePage * * @return void @@ -195,7 +122,6 @@ public function __construct( TagsPage $tagsPage, SharedByLinkPage $sharedByLinkPage, SharedWithOthersPage $sharedWithOthersPage, - GeneralExceptionPage $generalExceptionPage, ExternalStoragePage $externalStoragePage ) { $this->trashbinPage = $trashbinPage; @@ -206,7 +132,6 @@ public function __construct( $this->tagsPage = $tagsPage; $this->sharedByLinkPage = $sharedByLinkPage; $this->sharedWithOthersPage = $sharedWithOthersPage; - $this->generalExceptionPage = $generalExceptionPage; $this->externalStoragePage = $externalStoragePage; } @@ -256,8 +181,8 @@ public function resetFilesContext():void { } /** - * @When the user browses to the files page - * @Given the user has browsed to the files page + * @When the user/administrator browses to the files page + * @Given the user/administrator has browsed to the files page * * @return void * @throws Exception @@ -816,7 +741,7 @@ public function deleteTheFileUsingTheWebUI(string $name, bool $expectToDeleteFil } /** - * for a folder or individual file that is shared, the receiver of the share + * For a folder or individual file that is shared, the receiver of the share * has an "Unshare" entry in the file actions menu. Clicking it works just * like delete. * @@ -832,7 +757,7 @@ public function theUserDeletesFileUsingTheWebUI(string $name):void { } /** - * for a folder or individual file that is shared as federated share, the receiver of the share + * For a folder or individual file that is shared as federated share, the receiver of the share * has an "Unshare" entry in the file actions menu of the share in the * sharedwithme page. Clicking it works just like delete. * @@ -1075,7 +1000,7 @@ public function theFollowingElementsShouldBeListedAsUploadedFilesOnTheWebUI(Tabl $this->featureContext->verifyTableNodeColumns($table, ["uploaded-elements"]); $expectedElements = []; foreach ($table as $row) { - \array_push($expectedElements, $row["uploaded-elements"]); + $expectedElements[] = $row["uploaded-elements"]; } $pageObject = $this->getCurrentPageObject(); $currentUploadedElements = $pageObject->getCompletelyUploadedElements(); @@ -1467,7 +1392,7 @@ public function theUserOpensTheFileOrFolderUsingTheWebUI( } if (\count($breadCrumbs)) { $this->currentFolder .= "/" . \implode('/', $breadCrumbs); - }; + } } } @@ -1546,7 +1471,7 @@ public function fileFolderShouldBeListedOnTheWebUI( * @param string $typeOfFilesPage * @param string $folder * @param string $path if set, name and path (shown on the webUI) of the file to match - * @param FilesPageBasic $pageObject if not null use this pageObject and ignore $typeOfFilesPage + * @param FilesPageBasic|null $pageObject if not null use this pageObject and ignore $typeOfFilesPage * * @return void * @throws Exception @@ -1560,7 +1485,6 @@ public function checkIfFileFolderIsListedOnTheWebUI( FilesPageBasic $pageObject = null ) { $should = ($shouldOrNot !== "not"); - $exceptionMessage = null; switch ($typeOfFilesPage) { case "files page": $this->theUserBrowsesToThePage($this->filesPage); @@ -1742,8 +1666,8 @@ public function theFollowingFileFolderShouldBeListedInTheFollowingFolderOnTheWeb * @param string $shouldOrNot * @param string $typeOfFilesPage * @param string $folder - * @param TableNode $namePartsTable table of parts of the file name - * table headings: must be: |name-parts | + * @param TableNode|null $namePartsTable table of parts of the file name + * table headings: must be: |name-parts | * * @return void * @throws Exception @@ -1866,7 +1790,7 @@ public function itShouldNotBePossibleToDeleteFileFolderUsingTheWebUI(string $nam * @throws Exception */ public function itShouldBePossibleToDeleteFileFolderUsingTheWebUI(string $name):void { - $this->deleteTheFileUsingTheWebUI($name, true); + $this->deleteTheFileUsingTheWebUI($name); } /** @@ -2361,15 +2285,15 @@ public function userDownloadsFile(string $fileName):void { $this->openedFileActionMenu = $this->selectedFileRow->openFileActionsMenu($session); $url = $this->openedFileActionMenu->getDownloadUrlForFile(); $baseUrl = $this->featureContext->getBaseUrlWithoutPath(); - $this->response = HttpRequestHelper::get( + $response = HttpRequestHelper::get( $baseUrl . $url, $this->featureContext->getStepLineRef() ); Assert::assertEquals( 200, - $this->response->getStatusCode() + $response->getStatusCode() ); - $this->featureContext->setResponse($this->response); + $this->featureContext->setResponse($response); } /** @@ -2466,7 +2390,7 @@ public function folderShouldBeDownloaded(string $expectedFolder):void { * @return void * @throws Exception */ - public function theUserUnzipsTheFolder(string $file):void { + public function theUserUnzipsTheFile(string $file):void { $zip = new ZipArchive; $directory = getenv("DOWNLOADS_DIRECTORY"); if (!$directory) { @@ -2477,7 +2401,6 @@ public function theUserUnzipsTheFolder(string $file):void { if ($res === true) { $zip->extractTo($directory); $zip->close(); - $files = array_diff(scandir($directory), ['.', '..']); // get all file names and remove '.', '..' } else { throw new Exception("Couldn't open the file $zipFile"); } @@ -2649,7 +2572,7 @@ public function theVersionsListShouldContainEntries(int $num):void { } /** - * @Then the author(s) of the current and noncurrent version(s) of file/folder :resource should be: + * @Then the author(s) of the current and non-current version(s) of file/folder :resource should be: * * @param string $resource * @param TableNode $versionTable @@ -2657,7 +2580,7 @@ public function theVersionsListShouldContainEntries(int $num):void { * @return void * @throws Exception */ - public function theAuthorsOfCurrentAndNoncurrentVersionsOfFileShouldBe(string $resource, TableNode $versionTable):void { + public function theAuthorsOfCurrentAndNonCurrentVersionsOfFileShouldBe(string $resource, TableNode $versionTable):void { $this->featureContext->verifyTableNodeColumns( $versionTable, ['index', 'author'] @@ -2782,9 +2705,9 @@ public function deleteUnzippedAndDownloadedResources():void { RecursiveIteratorIterator::CHILD_FIRST ); - foreach ($files as $fileinfo) { - $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); - $todo($fileinfo->getRealPath()); + foreach ($files as $fileInfo) { + $todo = ($fileInfo->isDir() ? 'rmdir' : 'unlink'); + $todo($fileInfo->getRealPath()); } } } diff --git a/tests/acceptance/features/bootstrap/WebUIGeneralContext.php b/tests/acceptance/features/bootstrap/WebUIGeneralContext.php index 814f9201a927..3278fb9b8f3f 100644 --- a/tests/acceptance/features/bootstrap/WebUIGeneralContext.php +++ b/tests/acceptance/features/bootstrap/WebUIGeneralContext.php @@ -43,66 +43,33 @@ * WebUI General context. */ class WebUIGeneralContext extends RawMinkContext implements Context { - private $owncloudPage; + private OwncloudPage $owncloudPage; + private GeneralErrorPage $generalErrorPage; + private GeneralExceptionPage $generalExceptionPage; + private LoginPage $loginPage; - /** - * - * @var GeneralErrorPage - */ - private $generalErrorPage; - - /** - * - * @var GeneralExceptionPage - */ - private $generalExceptionPage; - - /** - * - * @var LoginPage - */ - private $loginPage; - - private $oldCSRFSetting = null; - private $oldPreviewSetting = []; - - /** - * - * @var FeatureContext - */ - private $featureContext = null; + private ?string $oldCSRFSetting = null; + private array $oldPreviewSetting = []; + private ?FeatureContext $featureContext = null; + private ?WebUIFilesContext $webUIFilesContext = null; + private ?OwncloudPage $currentPageObject = null; + private ?string $currentServer = null; /** - * - * @var WebUIFilesContext + * the original capabilities in XML format */ - private $webUIFilesContext = null; + private array $savedCapabilitiesXml; /** - * - * @var OwncloudPage + * the changes made to capabilities for the test scenario */ - private $currentPageObject = null; - - private $currentServer = null; + private array $savedCapabilitiesChanges = []; /** - * @var array the original capabilities in XML format - */ - private $savedCapabilitiesXml; - - /** - * @var array the changes made to capabilities for the test scenario - */ - private $savedCapabilitiesChanges = []; - - /** - * table of capabilities to map the human readable terms from the settings page + * table of capabilities to map the human-readable terms from the settings page * to terms in the capabilities XML and testing app - * - * @var array */ - private $capabilities = [ + private array $capabilities = [ 'sharing' => [ 'Allow apps to use the Share API' => [ 'capabilitiesApp' => 'files_sharing', @@ -364,6 +331,7 @@ public function notificationsShouldBeDisplayedOnTheWebUIWithTheText( foreach ($expectedNotifications as $expectedNotification) { $expectedNotificationText = $expectedNotification[0]; $matchingSucceeded = false; + $latestActualNotificationText = "unknown"; foreach ($actualNotifications as $key => $actualNotificationText) { $latestActualNotificationText = $actualNotificationText; if ((($matching !== "matching") && ($expectedNotificationText === $actualNotificationText)) @@ -826,7 +794,7 @@ function ($server) { } /** - * enable the previews on all tests tagged with '@enablePreviews' + * Enable the previews on all tests tagged with '@enablePreviews' * * Sometimes when testing locally, or if the `enable_previews` is turned off, * the tests such as the one testing thumbnails may fail. This enables the preview @@ -863,8 +831,7 @@ function ($server) { public function getSessionId():string { $url = $this->getSession()->getDriver()->getWebDriverSession()->getUrl(); $parts = \explode('/', $url); - $sessionId = \array_pop($parts); - return $sessionId; + return \array_pop($parts); } /** diff --git a/tests/acceptance/features/bootstrap/WebUIHelpAndTipsContext.php b/tests/acceptance/features/bootstrap/WebUIHelpAndTipsContext.php index f3cb2b2e5168..07becd8befa7 100644 --- a/tests/acceptance/features/bootstrap/WebUIHelpAndTipsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIHelpAndTipsContext.php @@ -34,19 +34,9 @@ * WebUI HelpAndTips context. */ class WebUIHelpAndTipsContext extends RawMinkContext implements Context { - private $helpAndTipsPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var FeatureContext - */ - private $featureContext; + private HelpAndTipsPage $helpAndTipsPage; + private WebUIGeneralContext $webUIGeneralContext; + private FeatureContext $featureContext; /** * WebUIHelpAndTips constructor. @@ -60,7 +50,7 @@ public function __construct( } /** - * return actual link from help and tips page + * return the actual link from the help and tips page * * @param string $to * @@ -73,7 +63,7 @@ protected function generateHelpLinks(string $to):string { $this->featureContext->getStepLineRef() ); $version = \explode(".", $version); - $version = (string) $version[0] . "." . (string) $version[1]; + $version = $version[0] . "." . $version[1]; return "https://doc.owncloud.com/server/$version/go.php?to=$to"; } @@ -159,7 +149,7 @@ public function theAdministratorOpensTheLinkFor(string $linkTitle):void { $link = $this->helpAndTipsPage->getLinkByTitle($linkTitle); $link->click(); - // switch to next tab as the link opens in new tab + // switch to the next tab as the link opens in the new tab $windowNames = $this->getSession()->getWindowNames(); if (\count($windowNames) > 1) { $this->getSession()->switchToWindow($windowNames[1]); diff --git a/tests/acceptance/features/bootstrap/WebUILoginContext.php b/tests/acceptance/features/bootstrap/WebUILoginContext.php index 700230deba9d..6790659b0633 100644 --- a/tests/acceptance/features/bootstrap/WebUILoginContext.php +++ b/tests/acceptance/features/bootstrap/WebUILoginContext.php @@ -25,8 +25,10 @@ use Behat\Gherkin\Node\PyStringNode; use Behat\Mink\Exception\ElementNotFoundException; use Behat\MinkExtension\Context\RawMinkContext; +use GuzzleHttp\Exception\GuzzleException; use Page\LoginPage; use PHPUnit\Framework\Assert; +use SensioLabs\Behat\PageObjectExtension\PageObject\Page; require_once 'bootstrap.php'; @@ -34,21 +36,10 @@ * WebUI Login context. */ class WebUILoginContext extends RawMinkContext implements Context { - private $loginPage; - private $filesPage; - private $expectedPage; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; + private LoginPage $loginPage; + private Page $filesPage; + private FeatureContext $featureContext; + private WebUIGeneralContext $webUIGeneralContext; /** * WebUILoginContext constructor. @@ -68,7 +59,7 @@ private function getExpectedLoginSuccessPageTitle():string { } /** - * after a successful login we always end up on the Files Page + * after a successful login, we always end up on the Files Page * * @return void */ @@ -458,7 +449,7 @@ public function userLogInWithUsernameAndPasswordAfterRedirectFromPage( string $password, string $page ):void { - $this->expectedPage = $this->webUIGeneralContext->loginAs( + $this->webUIGeneralContext->loginAs( $username, $password, \str_replace(' ', '', \ucwords($page)) . 'Page' @@ -688,7 +679,7 @@ public function theUserFollowsThePasswordResetLinkFromTheirEmail(string $user):v } /** - * @When the user follows the password reset link from email address of the user :user but supplying invalid user name :username + * @When the user follows the password reset link from email address of the user :user but supplying invalid username :username * * @param string $user * @param string $username @@ -712,7 +703,7 @@ public function theUserFollowsThePasswordResetLinkFromTheirEmailUsingInvalidUser // pop off the last part and replace it with the invalid username $linkParts = \explode('/', $link); \array_pop($linkParts); - \array_push($linkParts, $username); + $linkParts[] = $username; $adjustedLink = \implode('/', $linkParts); $this->visitPath($adjustedLink); } @@ -743,7 +734,7 @@ public function theUserFollowsThePasswordResetLinkFromTheirEmailUsingInvalidToke // reverse the token string, an easy way to make the token invalid $invalidToken = \strrev($goodToken); \array_push($linkParts, $invalidToken); - \array_push($linkParts, $username); + $linkParts[] = $username; $adjustedLink = \implode('/', $linkParts); $this->visitPath($adjustedLink); } @@ -814,7 +805,7 @@ public function theUserShouldBeRedirectedToTheLoginPage():void { * * @return void * @throws Exception - * @throws \GuzzleHttp\Exception\GuzzleException + * @throws GuzzleException */ public function theUserFollowsThePasswordSetLinkReceivedByEmail(string $emailAddress, int $numEmails = 1):void { $this->featureContext->pushEmailRecipientAsMailBox($emailAddress); diff --git a/tests/acceptance/features/bootstrap/WebUINewFileMenuContext.php b/tests/acceptance/features/bootstrap/WebUINewFileMenuContext.php index 000ef9dd3cc0..a7ea5a887eaf 100644 --- a/tests/acceptance/features/bootstrap/WebUINewFileMenuContext.php +++ b/tests/acceptance/features/bootstrap/WebUINewFileMenuContext.php @@ -23,7 +23,6 @@ use Behat\Behat\Context\Context; use Behat\MinkExtension\Context\RawMinkContext; -use Page\FilesPage; use Page\FilesPageElement\NewFileMenu; use PHPUnit\Framework\Assert; @@ -33,31 +32,17 @@ * Context for new file menu */ class WebUINewFileMenuContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var NewFileMenu - */ - private $newFileMenu; + private NewFileMenu $newFileMenu; /** * WebUINewFileMenuContext constructor. * - * @param FilesPage $filesPage * @param NewFileMenu $newFileMenu * - * @return void */ public function __construct( - FilesPage $filesPage, NewFileMenu $newFileMenu ) { - $this->filesPage = $filesPage; $this->newFileMenu = $newFileMenu; } @@ -66,7 +51,7 @@ public function __construct( * * @return void */ - public function theUserOpensTheNewfilemenuUsingTheWebUI():void { + public function theUserOpensTheNewFileMenuUsingTheWebUI():void { $this->newFileMenu->openNewFileMenu(); } @@ -75,7 +60,7 @@ public function theUserOpensTheNewfilemenuUsingTheWebUI():void { * * @return void */ - public function theNewFilemenuShouldBeDisplayedOnTheWebUI():void { + public function theNewFileMenuShouldBeDisplayedOnTheWebUI():void { Assert::assertNotNull( $this->newFileMenu->getNewFileMenu(), 'New file menu is expected to be visible but is not' diff --git a/tests/acceptance/features/bootstrap/WebUINotificationsContext.php b/tests/acceptance/features/bootstrap/WebUINotificationsContext.php index 80c79c4e062a..c751c9f1fe56 100644 --- a/tests/acceptance/features/bootstrap/WebUINotificationsContext.php +++ b/tests/acceptance/features/bootstrap/WebUINotificationsContext.php @@ -26,6 +26,7 @@ use Behat\Gherkin\Node\TableNode; use Behat\Mink\Session; use Behat\MinkExtension\Context\RawMinkContext; +use Page\Notification; use Page\NotificationsEnabledOwncloudPage; use PHPUnit\Framework\Assert; @@ -34,17 +35,8 @@ * */ class WebUINotificationsContext extends RawMinkContext implements Context { - /** - * - * @var NotificationsEnabledOwncloudPage - */ - private $owncloudPage; - - /** - * - * @var FeatureContext - */ - private $featureContext; + private NotificationsEnabledOwncloudPage $owncloudPage; + private FeatureContext $featureContext; /** * diff --git a/tests/acceptance/features/bootstrap/WebUIPersonalEncryptionSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIPersonalEncryptionSettingsContext.php index c63db7c2edcf..985eda73ee66 100644 --- a/tests/acceptance/features/bootstrap/WebUIPersonalEncryptionSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIPersonalEncryptionSettingsContext.php @@ -21,10 +21,8 @@ */ use Behat\Behat\Context\Context; -use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\MinkExtension\Context\RawMinkContext; use Page\PersonalEncryptionSettingsPage; -use Page\OwncloudPage; require_once 'bootstrap.php'; @@ -32,40 +30,16 @@ * Context for personal encryption settings specific webUI steps */ class WebUIPersonalEncryptionSettingsContext extends RawMinkContext implements Context { - /** - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var OwncloudPage - */ - private $owncloudPage; - - /** - * - * @var PersonalEncryptionSettingsPage - */ - private $personalEncryptionSettingsPage; + private PersonalEncryptionSettingsPage $personalEncryptionSettingsPage; /** * WebUIPersonalEncryptionSettingsContext constructor. * - * @param OwncloudPage $owncloudPage * @param PersonalEncryptionSettingsPage $personalEncryptionSettingsPage */ public function __construct( - OwncloudPage $owncloudPage, PersonalEncryptionSettingsPage $personalEncryptionSettingsPage ) { - $this->owncloudPage = $owncloudPage; $this->personalEncryptionSettingsPage = $personalEncryptionSettingsPage; } @@ -89,19 +63,4 @@ public function theUserHasEnabledPasswordRecovery():void { $this->personalEncryptionSettingsPage->enablePasswordRecovery(); $this->personalEncryptionSettingsPage->waitForAjaxCallsToStartAndFinish($this->getSession()); } - - /** - * @BeforeScenario - * - * @param BeforeScenarioScope $scope - * - * @return void - */ - public function setUpScenario(BeforeScenarioScope $scope):void { - // Get the environment - $environment = $scope->getEnvironment(); - // Get all the contexts you need in this context - $this->featureContext = $environment->getContext('FeatureContext'); - $this->webUIGeneralContext = $environment->getContext('WebUIGeneralContext'); - } } diff --git a/tests/acceptance/features/bootstrap/WebUIPersonalGeneralSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIPersonalGeneralSettingsContext.php index b18152d896a2..09f3c669a654 100644 --- a/tests/acceptance/features/bootstrap/WebUIPersonalGeneralSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIPersonalGeneralSettingsContext.php @@ -33,19 +33,9 @@ * WebUI PersonalGeneralSettings context. */ class WebUIPersonalGeneralSettingsContext extends RawMinkContext implements Context { - private $personalGeneralSettingsPage; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; + private PersonalGeneralSettingsPage $personalGeneralSettingsPage; + private FeatureContext $featureContext; + private WebUIGeneralContext $webUIGeneralContext; /** * WebUIPersonalGeneralSettingsContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIPersonalSecuritySettingsContext.php b/tests/acceptance/features/bootstrap/WebUIPersonalSecuritySettingsContext.php index dd54c4530bae..6fb66e552d6d 100644 --- a/tests/acceptance/features/bootstrap/WebUIPersonalSecuritySettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIPersonalSecuritySettingsContext.php @@ -33,14 +33,13 @@ * WebUI PersonalSecuritySettings context. */ class WebUIPersonalSecuritySettingsContext extends RawMinkContext implements Context { - private $personalSecuritySettingsPage; + private PersonalSecuritySettingsPage $personalSecuritySettingsPage; private $appName; - private $strForAppName = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - private $webUILoginContext; - private $featureContext; - private $webUIGeneralContext; - private $newAppPassword = null; - private $loginPage; + private string $strForAppName = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + private WebUILoginContext $webUILoginContext; + private WebUIGeneralContext $webUIGeneralContext; + private ?string $newAppPassword = null; + private LoginPage $loginPage; /** * WebUIPersonalSecuritySettingsContext constructor. @@ -167,7 +166,6 @@ public function before(BeforeScenarioScope $scope):void { // Get the environment $environment = $scope->getEnvironment(); // Get all the contexts you need in this context - $this->featureContext = $environment->getContext('FeatureContext'); $this->webUILoginContext = $environment->getContext('WebUILoginContext'); $this->webUIGeneralContext = $environment->getContext('WebUIGeneralContext'); } diff --git a/tests/acceptance/features/bootstrap/WebUIPersonalSharingSettingsContext.php b/tests/acceptance/features/bootstrap/WebUIPersonalSharingSettingsContext.php index 6fec88b4f9e0..96bf0b1b5b08 100644 --- a/tests/acceptance/features/bootstrap/WebUIPersonalSharingSettingsContext.php +++ b/tests/acceptance/features/bootstrap/WebUIPersonalSharingSettingsContext.php @@ -31,7 +31,7 @@ * steps for personal sharing settings */ class WebUIPersonalSharingSettingsContext extends RawMinkContext implements Context { - private $personalSharingSettingsPage; + private PersonalSharingSettingsPage $personalSharingSettingsPage; /** * diff --git a/tests/acceptance/features/bootstrap/WebUISearchContext.php b/tests/acceptance/features/bootstrap/WebUISearchContext.php index 8f8a9d847cef..a757c45526d1 100644 --- a/tests/acceptance/features/bootstrap/WebUISearchContext.php +++ b/tests/acceptance/features/bootstrap/WebUISearchContext.php @@ -32,28 +32,10 @@ * WebUI Search context. */ class WebUISearchContext extends RawMinkContext implements Context { - /** - * - * @var SearchResultInOtherFoldersPage - */ - private $searchResultInOtherFoldersPage; - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var WebUIFilesContext - */ - private $webUIFilesContext; + private SearchResultInOtherFoldersPage $searchResultInOtherFoldersPage; + private FilesPage $filesPage; + private WebUIGeneralContext $webUIGeneralContext; + private WebUIFilesContext $webUIFilesContext; /** * WebUILoginContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUISharingContext.php b/tests/acceptance/features/bootstrap/WebUISharingContext.php index c87695ec482b..3271adeb94c3 100644 --- a/tests/acceptance/features/bootstrap/WebUISharingContext.php +++ b/tests/acceptance/features/bootstrap/WebUISharingContext.php @@ -26,15 +26,14 @@ use Behat\MinkExtension\Context\RawMinkContext; use Psr\Http\Message\ResponseInterface; use Page\FilesPage; -use Page\FilesPageElement\SharingDialog; use Page\FilesPageElement\SharingDialogElement\EditPublicLinkPopup; use Page\FilesPageElement\SharingDialogElement\PublicLinkTab; use Page\GeneralErrorPage; use Page\PublicLinkFilesPage; -use Page\SharedWithOthersPage; use Page\SharedWithYouPage; use PHPUnit\Framework\Assert; use SensioLabs\Behat\PageObjectExtension\PageObject\Exception\ElementNotFoundException; +use SensioLabs\Behat\PageObjectExtension\PageObject\Page; use TestHelpers\EmailHelper; use TestHelpers\HttpRequestHelper; use TestHelpers\SetupHelper; @@ -45,73 +44,19 @@ * WebUI SharingContext context. */ class WebUISharingContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var PublicLinkFilesPage - */ - private $publicLinkFilesPage; - - /** - * - * @var SharedWithYouPage - */ - private $sharedWithYouPage; - - /** - * @var SharedWithOthersPage - */ - private $sharedWithOthersPage; - - /** - * - * @var GeneralErrorPage - */ - private $generalErrorPage; - - /** - * - * @var SharingDialog - */ - private $sharingDialog; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var WebUIFilesContext - */ - private $webUIFilesContext; - - private $oldMinCharactersForAutocomplete = null; - private $oldFedSharingFallbackSetting = null; - - /** - * @var PublicLinkTab - */ - private $publicShareTab; - - /** - * - * @var EditPublicLinkPopup - */ - private $publicSharingPopup; - private $linkName; + private FilesPage $filesPage; + private PublicLinkFilesPage $publicLinkFilesPage; + private SharedWithYouPage $sharedWithYouPage; + private GeneralErrorPage $generalErrorPage; + private ?Page $sharingDialog = null; + private FeatureContext $featureContext; + private WebUIGeneralContext $webUIGeneralContext; + private WebUIFilesContext $webUIFilesContext; + private ?string $oldMinCharactersForAutocomplete = null; + private ?string $oldFedSharingFallbackSetting = null; + private PublicLinkTab $publicShareTab; + private EditPublicLinkPopup $publicSharingPopup; + private string $linkName; /** * WebUISharingContext constructor. @@ -120,20 +65,17 @@ class WebUISharingContext extends RawMinkContext implements Context { * @param PublicLinkFilesPage $publicLinkFilesPage * @param SharedWithYouPage $sharedWithYouPage * @param GeneralErrorPage $generalErrorPage - * @param SharedWithOthersPage $sharedWithOthersPage */ public function __construct( FilesPage $filesPage, PublicLinkFilesPage $publicLinkFilesPage, SharedWithYouPage $sharedWithYouPage, - GeneralErrorPage $generalErrorPage, - SharedWithOthersPage $sharedWithOthersPage + GeneralErrorPage $generalErrorPage ) { $this->filesPage = $filesPage; $this->publicLinkFilesPage = $publicLinkFilesPage; $this->sharedWithYouPage = $sharedWithYouPage; $this->generalErrorPage = $generalErrorPage; - $this->sharedWithOthersPage = $sharedWithOthersPage; } /** @@ -434,6 +376,7 @@ public function theUserSharesUsingWebUIWithoutClosingDialog( // open each of the folders until the last resource should be displayed. $resourceParts = \explode("/", $resource); $numberOfResourceParts = \count($resourceParts); + $finalResource = ''; foreach ($resourceParts as $key => $resourcePart) { // open each folder in the path, so that the last item should be listed if ($key === ($numberOfResourceParts - 1)) { @@ -511,9 +454,9 @@ public function theUserSharesUsingWebUIWithoutClosingDialog( $sharePath = (string) $shareItem->path; $slashSharePath = "/" . \trim($sharePath, "/"); // The user might have navigated down multiple folders /a/b/c and shared "d". - // Normally the share path will be /a/b/c/d + // Normally, the share path will be /a/b/c/d // But the user might have received "a" as a share, but also "b" as a separate share. - // (maybe the two shares were to two different groups and the user is a member of both) + // (Maybe the two shares were to two different groups and the user is a member of both) // Then the user will also have a path to "d" that is b/c/d only. // And the share response actually provides that path. // So match any share path like /b/c/d or /c/d if it appears at the end of the expected path, @@ -629,7 +572,7 @@ public function shouldBeListedInTheSharedWithList( $should = ($shouldOrNot !== "not"); // The capturing groups of the regex include the quotes at each // end of the captured string, so trim them. - $groupName = \trim($groupName, '""'); + $groupName = \trim($groupName, '"'); $presence = $this->sharingDialog->isGroupPresentInShareWithList($groupName); if ($should) { PHPUnit\Framework\Assert::assertTrue( @@ -666,7 +609,7 @@ public function theUserHasOpenedThePublicLinkShareTab():void { * @return void */ public function theUserDeleteShareWithUser(string $userOrGroup, string $name):void { - $name = \trim($name, '""'); + $name = \trim($name, '"'); if ($userOrGroup === "user") { $name = $this->featureContext->getDisplayNameForUser($name); } @@ -915,7 +858,7 @@ public function theUserCreatesAReadOnlyPublicLinkForFolderUsingTheQuickActionBut * possible settings: name, permission, * password, expiration, email, emailToSelf, personalMessage * the permissions values has to be written exactly - * the way its written in the UI + * the way it's written in the UI * Setting emailToSelf will send a copy of email to the link creator * * @return void @@ -927,6 +870,7 @@ public function theUserCreatesANewPublicLinkForFileFolderUsingTheWebUIWith( ):void { $nameParts = \explode("/", $name); $numberOfNameParts = \count($nameParts); + $finalName = ''; foreach ($nameParts as $key => $namePart) { // open each folder in the path, so that the last item should be listed if ($key === ($numberOfNameParts - 1)) { @@ -977,8 +921,8 @@ public function theUserCreatesANewPublicLinkForFileFolderUsingTheWebUIWith( * @param TableNode|null $settings table with the settings and no header * possible settings: name, permission, * password, expiration, email - * the permissions values has to be written exactly - * the way its written in the UI + * the permission values have to be written exactly + * the way they are written in the UI * * @return void * @throws Exception @@ -1097,7 +1041,7 @@ public function theUserSetsTheSharingPermissionsOfForOnTheWebUI( ); // The capturing groups of the regex include the quotes at each // end of the captured string, so trim them. - $userName = $this->featureContext->substituteInLineCodes(\trim($userName, '""')); + $userName = $this->featureContext->substituteInLineCodes(\trim($userName, '"')); $userAdditionalInfoFromAppConfig = \TestHelpers\AppConfigHelper::getAppConfig( $this->featureContext->getBaseUrl(), $this->featureContext->getAdminUsername(), @@ -1113,7 +1057,7 @@ public function theUserSetsTheSharingPermissionsOfForOnTheWebUI( $userName = $userName . " (" . $userNameActual . ")"; } } - $this->theUserOpensTheShareDialogForFileFolder(\trim($fileName, '""')); + $this->theUserOpensTheShareDialogForFileFolder(\trim($fileName, '"')); $this->sharingDialog->setSharingPermissions( $userOrGroup, $userName, @@ -1146,11 +1090,11 @@ public function theFollowingPermissionsAreSeenForInTheSharingDialogFor( ):void { $this->featureContext->verifyTableNodeRows($permissionsTable, [], ['share', 'edit', 'create', 'change', 'delete']); - $userName = $this->featureContext->substituteInLineCodes(\trim($userName, '""')); + $userName = $this->featureContext->substituteInLineCodes(\trim($userName, '"')); if ($userOrGroup === "user") { $userName = $this->featureContext->getDisplayNameForUser($userName); } - $this->theUserOpensTheShareDialogForFileFolder(\trim($fileName, '""')); + $this->theUserOpensTheShareDialogForFileFolder(\trim($fileName, '"')); $this->sharingDialog->checkSharingPermissions( $userOrGroup, $userName, @@ -1891,7 +1835,7 @@ public function fileFolderShouldBeMarkedAsSharedBy( $sharingBtn = $row->findSharingButton(); $mobileResolution = getenv("MOBILE_RESOLUTION"); // checking if MOBILE_RESOLUTION is set and skip this step if true as - // in mobile resolution sharer name is not displayed in file row + // in mobile resolution sharer name is not displayed in the file row if (empty($mobileResolution)) { Assert::assertSame( $sharerName, @@ -2160,7 +2104,7 @@ public function thePublicShouldSeeAnErrorMessageWhileAccessingLastCreatedPublicL * @param TableNode|null $settings table with the settings and no header * possible settings: name, permission, * password, expiration, email, personalMessage - * the permissions values have to be written + * the permission values have to be written * exactly the way they are written in the UI * * @return string diff --git a/tests/acceptance/features/bootstrap/WebUITagsContext.php b/tests/acceptance/features/bootstrap/WebUITagsContext.php index 9213f11140ad..5cb6af8efbfb 100644 --- a/tests/acceptance/features/bootstrap/WebUITagsContext.php +++ b/tests/acceptance/features/bootstrap/WebUITagsContext.php @@ -25,7 +25,6 @@ use Behat\MinkExtension\Context\RawMinkContext; use Behat\Gherkin\Node\TableNode; use Page\FilesPage; -use Page\TagsPage; use PHPUnit\Framework\Assert; require_once 'bootstrap.php'; @@ -34,44 +33,21 @@ * WebUI Tags context. */ class WebUITagsContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - /** - * - * @var TagsPage - */ - private $tagsPage; - - /** - * - * @var TagsContext - */ - private $tagsContext; + private FilesPage $filesPage; + private FeatureContext $featureContext; + private TagsContext $tagsContext; /** * WebUITagsContext constructor. * * @param FilesPage $filesPage - * @param TagsPage $tagsPage * * @return void */ public function __construct( - FilesPage $filesPage, - TagsPage $tagsPage + FilesPage $filesPage ) { $this->filesPage = $filesPage; - $this->tagsPage = $tagsPage; } /** @@ -86,14 +62,14 @@ public function assertTheExpectedTagsAreDisplayed(array $results, TableNode $Exp $displayedTags = []; foreach ($results as $tagResult) { $tag = $tagResult->getText(); - \array_push($displayedTags, $tag); - }; + $displayedTags[] = $tag; + } foreach ($ExpectedTags as $tag) { $tagName = $tag['name']; Assert::assertContains( $tagName, $displayedTags, - "Tagname $tagName was not displayed in the tag list" + "Tag name $tagName was not displayed in the tag list" ); } } diff --git a/tests/acceptance/features/bootstrap/WebUIUserContext.php b/tests/acceptance/features/bootstrap/WebUIUserContext.php index f67b043aa808..451f464ae44f 100644 --- a/tests/acceptance/features/bootstrap/WebUIUserContext.php +++ b/tests/acceptance/features/bootstrap/WebUIUserContext.php @@ -32,11 +32,7 @@ * Context for steps associated with the user logged in to the WebUI */ class WebUIUserContext extends RawMinkContext implements Context { - /** - * - * @var OwncloudPage - */ - private $owncloudPage; + private OwncloudPage $owncloudPage; /** * WebUIUserContext constructor. diff --git a/tests/acceptance/features/bootstrap/WebUIUsersContext.php b/tests/acceptance/features/bootstrap/WebUIUsersContext.php index 46b8c7c85fbb..5fa3745f9597 100644 --- a/tests/acceptance/features/bootstrap/WebUIUsersContext.php +++ b/tests/acceptance/features/bootstrap/WebUIUsersContext.php @@ -26,6 +26,7 @@ use Behat\Gherkin\Node\TableNode; use Behat\Mink\Exception\ElementNotFoundException; use Behat\MinkExtension\Context\RawMinkContext; +use Page\DisabledUserPage; use Page\GeneralErrorPage; use Page\LoginPage; use Page\UsersPage; @@ -40,39 +41,13 @@ * WebUI Users context. */ class WebUIUsersContext extends RawMinkContext implements Context { - private $usersPage; - - /** - * - * @var LoginPage - */ - private $loginPage; - - /** - * - * @var OwncloudPage - */ - private $owncloudPage; - - /** - * - * @var GeneralErrorPage - */ - private $generalErrorPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; - - /** - * - * @var FeatureContext - */ - private $featureContext; - - private $appParameterValues = null; + private UsersPage $usersPage; + private LoginPage $loginPage; + private OwncloudPage $owncloudPage; + private GeneralErrorPage $generalErrorPage; + private WebUIGeneralContext $webUIGeneralContext; + private FeatureContext $featureContext; + private ?array $appParameterValues = null; /** * WebUIUsersContext constructor. @@ -183,7 +158,6 @@ public function theAdminCreatesAUserUsingTheWebUI( $password, $username, $email, - null, $shouldExist ); if (\is_array($groups)) { @@ -366,7 +340,7 @@ public function theAdminDeletesTheseGroupsUsingTheWebUI(TableNode $table):void { } /** - * @When the administrator deletes these groups and and cancels the deletion using the webUI: + * @When the administrator deletes these groups and cancels the deletion using the webUI: * expects a table of groups with the heading "groupname" * * @param TableNode $table @@ -374,7 +348,7 @@ public function theAdminDeletesTheseGroupsUsingTheWebUI(TableNode $table):void { * @return void * @throws Exception */ - public function theAdminDeletesDoesNotTheseGroupsUsingTheWebUI(TableNode $table):void { + public function theAdminDeletesTheseGroupsAndCancelsUsingTheWebUI(TableNode $table):void { $this->featureContext->verifyTableNodeColumns($table, ['groupname']); foreach ($table as $row) { $this->theAdminDeletesDoesNotDeleteGroupUsingWebUI($row['groupname']); @@ -546,7 +520,7 @@ public function theDeletedUserTriesToLogin(string $username, string $password):v * @return void */ public function enableOrDisableSettings(string $action, string $setting):void { - $value = ($action === 'enables' || $action === 'enabled') ? true : false; + $value = $action === 'enables' || $action === 'enabled'; $this->usersPage->setSetting($setting, $value); } @@ -610,8 +584,7 @@ public function theAdministratorShouldBeAbleToSeeQuotaOfTheseUsers(TableNode $ta foreach ($table as $row) { $user = $this->featureContext->getActualUsername($row['username']); $visible = $this->usersPage->isQuotaColumnOfUserVisible($user); - Assert::assertEquals( - true, + Assert::assertTrue( $visible, __METHOD__ . " The quota of user '" @@ -634,8 +607,7 @@ public function theAdministratorShouldNotBeAbleToSeeQuotaOfTheseUsers(TableNode foreach ($table as $row) { $user = $this->featureContext->getActualUsername($row['username']); $visible = $this->usersPage->isQuotaColumnOfUserVisible($user); - Assert::assertEquals( - false, + Assert::assertFalse( $visible, __METHOD__ . " The quota of user '" @@ -648,7 +620,7 @@ public function theAdministratorShouldNotBeAbleToSeeQuotaOfTheseUsers(TableNode /** * @Then /^the administrator should be able to see the password of these users in the User Management page:$/ * - * @param TableNode $table table of usernames column with a heading | username | + * @param TableNode $table table of usernames with a heading | username | * * @return void * @throws Exception @@ -658,8 +630,7 @@ public function theAdministratorShouldBeAbleToSeePasswordColumnOfTheseUsers(Tabl foreach ($table as $row) { $user = $this->featureContext->getActualUsername($row['username']); $visible = $this->usersPage->isPasswordColumnOfUserVisible($user); - Assert::assertEquals( - true, + Assert::assertTrue( $visible, __METHOD__ . " The password of user '" @@ -672,7 +643,7 @@ public function theAdministratorShouldBeAbleToSeePasswordColumnOfTheseUsers(Tabl /** * @Then /^the administrator should not be able to see the password of these users in the User Management page:$/ * - * @param TableNode $table table of usernames column with a heading | username | + * @param TableNode $table table of usernames with a heading | username | * * @return void * @throws Exception @@ -682,8 +653,7 @@ public function theAdministratorShouldNotBeAbleToSeePasswordColumnOfTheseUsers(T foreach ($table as $row) { $user = $this->featureContext->getActualUsername($row['username']); $visible = $this->usersPage->isPasswordColumnOfUserVisible($user); - Assert::assertEquals( - false, + Assert::assertFalse( $visible, __METHOD__ . " The password of user '" @@ -758,6 +728,31 @@ public function theAdministratorShouldBeAbleToSeeLastLoginOfTheseUsers( } } + /** + * @Then /^the administrator should not be able to see the last login of these users in the User Management page:$/ + * + * @param TableNode $table table of usernames and last logins with a heading | username | and | last logins | + * + * @return void + * @throws Exception + */ + public function theAdministratorShouldNotBeAbleToSeeLastLoginOfTheseUsers( + TableNode $table + ):void { + $this->featureContext->verifyTableNodeColumns($table, ['username']); + foreach ($table as $row) { + $user = $this->featureContext->getActualUsername($row['username']); + + Assert::assertFalse( + $this->usersPage->isLastLoginColumnOfUserVisible($user), + __METHOD__ + . " The last login of user '" + . $user + . "' was expected not to be visible to the administrator in the User Management page, but is visible." + ); + } + } + /** * @Then /^the administrator should be able to see the creation time of these users in the User Management page:$/ * @@ -980,7 +975,7 @@ public function theUserCountOfGroupShouldNotBeDisplayedOnTheWebUI(string $group) * @return void */ public function theUserCountOfGroupShouldDisplayUsersOnTheWebUI(string $group, int $count):void { - $expectedCount = (int) $count; + $expectedCount = $count; $actualCount = $this->usersPage->getUserCountOfGroup($group); Assert::assertEquals( $expectedCount, diff --git a/tests/acceptance/features/bootstrap/WebUIWebDavLockingContext.php b/tests/acceptance/features/bootstrap/WebUIWebDavLockingContext.php index 6fb547037716..36121dc54f81 100644 --- a/tests/acceptance/features/bootstrap/WebUIWebDavLockingContext.php +++ b/tests/acceptance/features/bootstrap/WebUIWebDavLockingContext.php @@ -23,8 +23,6 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\MinkExtension\Context\RawMinkContext; -use Page\FilesPage; -use Page\SharedWithYouPage; use PHPUnit\Framework\Assert; use SensioLabs\Behat\PageObjectExtension\PageObject\Exception\ElementNotFoundException; @@ -34,38 +32,15 @@ * context containing webUI steps needed for the locking mechanism of webdav */ class WebUIWebDavLockingContext extends RawMinkContext implements Context { - /** - * - * @var FilesPage - */ - private $filesPage; - - /** - * - * @var SharedWithYouPage - */ - private $sharedWithYouPage; - - /** - * - * @var WebUIGeneralContext - */ - private $webUIGeneralContext; + private WebUIGeneralContext $webUIGeneralContext; /** * WebUIFilesContext constructor. * - * @param FilesPage $filesPage - * @param SharedWithYouPage $sharedWithYouPage - * * @return void */ public function __construct( - FilesPage $filesPage, - SharedWithYouPage $sharedWithYouPage ) { - $this->filesPage = $filesPage; - $this->sharedWithYouPage = $sharedWithYouPage; } /** @@ -195,7 +170,7 @@ private function closeDetailsDialog():void { try { $pageObject->closeDetailsDialog(); } catch (Exception $e) { - //ignore if dialog cannot be closed + //ignore if dialog cannot be closed, //most likely there is no dialog open } } diff --git a/tests/acceptance/features/cliBackground/backgroundQueue.feature b/tests/acceptance/features/cliBackground/backgroundQueue.feature index ee635f2e0270..f23f36e5f84b 100644 --- a/tests/acceptance/features/cliBackground/backgroundQueue.feature +++ b/tests/acceptance/features/cliBackground/backgroundQueue.feature @@ -1,8 +1,8 @@ @cli @files_trashbin-app-required @files_sharing-app-required @skipOnLDAP Feature: get status, delete and execute jobs in background queue As an admin - I want to be able to see, delete and execute the jobs in background queue - So that I have control over background job queue + I want to be able to see, delete and execute jobs in the background queue + So that I have control over the background job queue Scenario: get the list of jobs in background queue @@ -24,9 +24,23 @@ Feature: get status, delete and execute jobs in background queue | OC\Authentication\Token\DefaultTokenCleanupJob | - Scenario: delete one of the job in background queue + Scenario: delete one of the jobs in the background queue Given user "Alice" has been created with default attributes and small skeleton files And user "Alice" has deleted file "/textfile0.txt" When the administrator deletes the last background job "OC\Command\CommandJob" using the occ command Then the command should have been successful And the last deleted background job "OC\Command\CommandJob" should not be listed in the background jobs queue + + + Scenario: execute one of the jobs in the background queue + Given user "Alice" has been created with default attributes and small skeleton files + And user "Alice" has deleted file "/textfile0.txt" + And the owncloud log level has been set to debug + When the administrator executes the last background job "OCA\Files\BackgroundJob\ScanFiles" using the occ command + Then the command should have been successful + And the command output should contain the text "Found job: OCA\Files\BackgroundJob\ScanFiles with ID" + And the command output should contain the text "Forcing run, resetting last run value to 0" + And the command output should contain the text "Running job..." + And the command output should contain the text "Started background job of class : OCA\Files\BackgroundJob\ScanFiles with arguments :" + And the command output should contain the text "Finished background job" + And the command output should contain the text "this job is an instance of class : OCA\Files\BackgroundJob\ScanFiles with arguments :" diff --git a/tests/acceptance/features/cliTrashbin/previewsCleanup.feature b/tests/acceptance/features/cliTrashbin/previewsCleanup.feature new file mode 100644 index 000000000000..a751970b768e --- /dev/null +++ b/tests/acceptance/features/cliTrashbin/previewsCleanup.feature @@ -0,0 +1,94 @@ +@cli @files_trashbin-app-required @preview-extension-required @skipOnOcV10.11 @skipOnOcV10.12 +Feature: orphaned previews can be deleted + As an admin + I want to delete previews whose original file no longer exists + So that I can save storage space + + Background: + Given user "Alice" has been created with default attributes and without skeleton files + And user "Alice" has uploaded file with content "text file zero" to "/textfile0.txt" + And user "Alice" has uploaded file with content "text file one" to "/textfile1.txt" + And user "Alice" has created folder "FOLDER" + And user "Alice" has uploaded file with content "folder text" to "/FOLDER/folder.txt" + And user "Alice" has created folder "PARENT" + And user "Alice" has created folder "PARENT/CHILD" + And user "Alice" has uploaded file with content "parent text" to "/PARENT/parent.txt" + And user "Alice" has uploaded file with content "child text" to "/PARENT/CHILD/child.txt" + And user "Alice" has downloaded the preview of "/textfile0.txt" with width "32" and height "32" + And user "Alice" has downloaded the preview of "/textfile1.txt" with width "32" and height "32" + And user "Alice" has downloaded the preview of "/FOLDER/folder.txt" with width "32" and height "32" + And user "Alice" has downloaded the preview of "/PARENT/parent.txt" with width "32" and height "32" + And user "Alice" has downloaded the preview of "/PARENT/CHILD/child.txt" with width "32" and height "32" + And user "Alice" has deleted file "/textfile1.txt" + And user "Alice" has deleted folder "/PARENT" + + + Scenario: previews of existing files in regular storage or the trashbin are not deleted + When the administrator cleans up previews using the occ command + Then the command should have been successful + And the command output should contain the text '0 orphaned previews deleted' + + + Scenario: after a file is deleted from the trashbin, its preview is cleaned up + When user "Alice" deletes the file with original path "textfile1.txt" from the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + And the command output should contain the text '1 orphaned previews deleted' + + + Scenario: after a folder is deleted from the trashbin, the previews are cleaned up + When user "Alice" deletes the folder with original path "PARENT" from the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + And the command output should contain the text '2 orphaned previews deleted' + + + Scenario: after the trashbin has been emptied, the previews are cleaned up + When user "Alice" empties the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + And the command output should contain the text '3 orphaned previews deleted' + + + Scenario: the previews of multiple users are cleaned up + Given user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has uploaded file with content "text file zero" to "/textfile0.txt" + And user "Brian" has uploaded file with content "text file one" to "/textfile1.txt" + And user "Brian" has downloaded the preview of "/textfile0.txt" with width "32" and height "32" + And user "Brian" has downloaded the preview of "/textfile1.txt" with width "32" and height "32" + And user "Brian" has deleted file "/textfile1.txt" + When user "Alice" empties the trashbin using the trashbin API + And user "Brian" empties the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + And the command output should contain the text '4 orphaned previews deleted' + + + Scenario: the previews from shared files are cleaned up + Given user "Brian" has been created with default attributes and without skeleton files + And user "Brian" has uploaded file with content "text file zero" to "/textfile0.txt" + And user "Brian" has downloaded the preview of "/textfile0.txt" with width "32" and height "32" + And user "Alice" has shared folder "/FOLDER" with user "Brian" + And user "Brian" has uploaded file with content "text from Brian" to "/FOLDER/fromBrian.txt" + And user "Brian" has downloaded the preview of "/FOLDER/folder.txt" with width "32" and height "32" + And user "Brian" has downloaded the preview of "/FOLDER/fromBrian.txt" with width "32" and height "32" + And user "Alice" has downloaded the preview of "/FOLDER/fromBrian.txt" with width "32" and height "32" + And user "Brian" has deleted file "/FOLDER/folder.txt" + And user "Brian" has deleted file "/FOLDER/fromBrian.txt" + When user "Brian" deletes the file with original path "FOLDER/folder.txt" from the trashbin using the trashbin API + And user "Brian" deletes the file with original path "FOLDER/fromBrian.txt" from the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + # The files are still in Alice's trashbin. + # Preview cleanup could delete the preview that is in Brian's file-system. + # But it does not do that level of optimization. + And the command output should contain the text '0 orphaned previews deleted' + When user "Alice" deletes the file with original path "FOLDER/folder.txt" from the trashbin using the trashbin API + And user "Alice" deletes the file with original path "FOLDER/fromBrian.txt" from the trashbin using the trashbin API + And the administrator cleans up previews using the occ command + Then the command should have been successful + # The two files have been deleted from both trashbins, so now there are four + # previews to delete (2 stored for Brian, 2 stored for Alice) + # The command also reports 'Brian: cache cleared' twice. + # And so it says that it deleted 6 orphaned previews. + And the command output should contain the text '6 orphaned previews deleted' diff --git a/tests/acceptance/features/lib/OwncloudPage.php b/tests/acceptance/features/lib/OwncloudPage.php index 6cec564bec7e..f0a541462415 100644 --- a/tests/acceptance/features/lib/OwncloudPage.php +++ b/tests/acceptance/features/lib/OwncloudPage.php @@ -24,6 +24,8 @@ namespace Page; use Behat\Mink\Element\NodeElement; +use Behat\Mink\Exception\DriverException; +use Behat\Mink\Exception\UnsupportedDriverActionException; use Behat\Mink\Session; use Exception; use InvalidArgumentException; @@ -490,6 +492,21 @@ public function scrollToPosition(string $jQuerySelector, $position, Session $ses ); } + /** + * scrolls to a position in a specified element + * + * @param string $jQuerySelector e.g. "#app-content" + * + * @return void + * @throws DriverException + * @throws UnsupportedDriverActionException + */ + public function scrollInToView(string $jQuerySelector): void { + $this->getDriver()->executeScript( + 'jQuery("' . $jQuerySelector . '").get(0).scrollIntoView();' + ); + } + /** * waits till all ajax calls are finished * diff --git a/tests/acceptance/features/lib/UsersPage.php b/tests/acceptance/features/lib/UsersPage.php index c786b127b797..28415ae923f2 100644 --- a/tests/acceptance/features/lib/UsersPage.php +++ b/tests/acceptance/features/lib/UsersPage.php @@ -268,6 +268,31 @@ public function isQuotaColumnOfUserVisible(string $username): bool { return true; } + /** + * @param string $username + * + * @return bool + * @throws ElementNotFoundException + * @throws Exception + */ + public function isLastLoginColumnOfUserVisible(string $username): bool { + $userTr = $this->findUserInTable($username); + $userLastLogin = $userTr->find('xpath', $this->lastLoginXpath); + + if ($userLastLogin === null) { + throw new ElementNotFoundException( + __METHOD__ . + " xpath $this->lastLoginXpath " . + "last login column of user " . $username . " not found" + ); + } + + if (!$userLastLogin->isVisible()) { + return false; + } + return true; + } + /** * @param string $username * diff --git a/tests/acceptance/features/webUIFiles/versions.feature b/tests/acceptance/features/webUIFiles/versions.feature index 136023828b84..04baf6559be4 100644 --- a/tests/acceptance/features/webUIFiles/versions.feature +++ b/tests/acceptance/features/webUIFiles/versions.feature @@ -101,7 +101,7 @@ Feature: Versions of a file And user "Alice" has logged in using the webUI And the user has browsed to the files page When the user browses directly to display the "versions" details of file "randomfile.txt" in folder "/" - Then the authors of the current and noncurrent versions of file "randomfile.txt" should be: + Then the authors of the current and non-current versions of file "randomfile.txt" should be: | index | author | | 1 | Alice | | 2 | Alice | @@ -120,7 +120,7 @@ Feature: Versions of a file And user "Carol" has logged in using the webUI And the user has browsed to the files page When the user browses directly to display the "versions" details of file "randomfile.txt" in folder "/" - Then the authors of the current and noncurrent versions of file "randomfile.txt" should be: + Then the authors of the current and non-current versions of file "randomfile.txt" should be: | index | author | | 1 | Brian | | 2 | Brian | @@ -141,14 +141,14 @@ Feature: Versions of a file And user "Carol" has logged in using the webUI And the user has browsed to the files page When the user browses directly to display the "versions" details of file "randomfile.txt" in folder "/" - Then the authors of the current and noncurrent versions of file "randomfile.txt" should be: + Then the authors of the current and non-current versions of file "randomfile.txt" should be: | index | author | | 1 | Carol | | 2 | Alice | | 3 | Brian | | 4 | Alice | When the user restores the file to last version using the webUI - Then the authors of the current and noncurrent versions of file "randomfile.txt" should be: + Then the authors of the current and non-current versions of file "randomfile.txt" should be: | index | author | | 1 | Carol | | 2 | Carol | diff --git a/tests/acceptance/features/webUILogin/resetPassword.feature b/tests/acceptance/features/webUILogin/resetPassword.feature index 229e54d52cdc..9dc55c0ea367 100644 --- a/tests/acceptance/features/webUILogin/resetPassword.feature +++ b/tests/acceptance/features/webUILogin/resetPassword.feature @@ -53,7 +53,7 @@ Feature: reset the password @skipOnEncryption Scenario: using the password reset token plus invalid username does not work When the user requests the password reset link using the webUI - And the user follows the password reset link from email address of the user "Alice" but supplying invalid user name "qwerty" + And the user follows the password reset link from email address of the user "Alice" but supplying invalid username "qwerty" Then the user should be redirected to a webUI page with the title "%productname%" And a lost password reset error message with this text should be displayed on the webUI: """ diff --git a/tests/acceptance/features/webUIManageUsersGroups/manageGroups.feature b/tests/acceptance/features/webUIManageUsersGroups/manageGroups.feature index aeaf688e5dc3..506d22b57682 100644 --- a/tests/acceptance/features/webUIManageUsersGroups/manageGroups.feature +++ b/tests/acceptance/features/webUIManageUsersGroups/manageGroups.feature @@ -172,7 +172,7 @@ Feature: manage groups | do-not-delete2 | | a\slash | And the administrator has browsed to the users page - When the administrator deletes these groups and and cancels the deletion using the webUI: + When the administrator deletes these groups and cancels the deletion using the webUI: | groupname | | grp1 | | space group | diff --git a/tests/acceptance/features/webUISettingsMenu/settingsMenu.feature b/tests/acceptance/features/webUISettingsMenu/settingsMenu.feature index ee0426bd4323..651c1a1e6438 100644 --- a/tests/acceptance/features/webUISettingsMenu/settingsMenu.feature +++ b/tests/acceptance/features/webUISettingsMenu/settingsMenu.feature @@ -49,6 +49,24 @@ Feature: add users | Alice | seconds ago | | Brian | never | + @skipOnOcV10.10 @skipOnOcV10.11 @skipOnOcV10.12 + Scenario: administrator should not be able to see last login of a user when the UI setting is disabled + When the administrator disables the setting "Show last log in" in the User Management page using the webUI + Then the administrator should not be able to see the last login of these users in the User Management page: + | username | + | Alice | + | Brian | + + @skipOnOcV10.10 @skipOnOcV10.11 @skipOnOcV10.12 + Scenario: administrator should not be able to see last login of a user when the UI setting is disabled + When the administrator disables the setting "Show last log in" in the User Management page using the webUI + And the user browses to the files page + And the administrator browses to the users page + Then the administrator should not be able to see the last login of these users in the User Management page: + | username | + | Alice | + | Brian | + @skipOnOcV10.10 @skipOnOcV10.11 Scenario: administrator should be able to see creation time of a user When the administrator enables the setting "Show creation time" in the User Management page using the webUI diff --git a/tests/data/apptheme/apps/files/l10n/en_GB.js b/tests/data/apptheme/apps/files/l10n/en_GB.js index b59f761f81ea..2728de27e078 100644 --- a/tests/data/apptheme/apps/files/l10n/en_GB.js +++ b/tests/data/apptheme/apps/files/l10n/en_GB.js @@ -32,6 +32,7 @@ OC.L10N.register( "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -40,7 +41,12 @@ OC.L10N.register( "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -68,7 +74,10 @@ OC.L10N.register( "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -79,6 +88,7 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -100,18 +110,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/tests/data/apptheme/apps/files/l10n/en_GB.json b/tests/data/apptheme/apps/files/l10n/en_GB.json index ddb33a3c76f7..eafd36e0f6dd 100644 --- a/tests/data/apptheme/apps/files/l10n/en_GB.json +++ b/tests/data/apptheme/apps/files/l10n/en_GB.json @@ -30,6 +30,7 @@ "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -38,7 +39,12 @@ "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -66,7 +72,10 @@ "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -77,6 +86,7 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -98,18 +108,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/tests/data/apptheme/apps/files/l10n/es_AR.js b/tests/data/apptheme/apps/files/l10n/es_AR.js index 8816d4343a4b..00bb6516ea80 100644 --- a/tests/data/apptheme/apps/files/l10n/es_AR.js +++ b/tests/data/apptheme/apps/files/l10n/es_AR.js @@ -57,6 +57,7 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/tests/data/apptheme/apps/files/l10n/es_AR.json b/tests/data/apptheme/apps/files/l10n/es_AR.json index 32234ffe7b30..bf2225b0796f 100644 --- a/tests/data/apptheme/apps/files/l10n/es_AR.json +++ b/tests/data/apptheme/apps/files/l10n/es_AR.json @@ -55,6 +55,7 @@ "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/tests/data/apptheme/apps/files/l10n/he.js b/tests/data/apptheme/apps/files/l10n/he.js index 7fa7a9daf71f..d67f5270639d 100644 --- a/tests/data/apptheme/apps/files/l10n/he.js +++ b/tests/data/apptheme/apps/files/l10n/he.js @@ -41,6 +41,10 @@ OC.L10N.register( "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -105,18 +109,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/tests/data/apptheme/apps/files/l10n/he.json b/tests/data/apptheme/apps/files/l10n/he.json index a86a58598d91..8c8d331e7135 100644 --- a/tests/data/apptheme/apps/files/l10n/he.json +++ b/tests/data/apptheme/apps/files/l10n/he.json @@ -39,6 +39,10 @@ "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -103,18 +107,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/tests/data/apptheme/apps/files/l10n/zh-Hans.js b/tests/data/apptheme/apps/files/l10n/zh-Hans.js new file mode 100644 index 000000000000..14da401f67fb --- /dev/null +++ b/tests/data/apptheme/apps/files/l10n/zh-Hans.js @@ -0,0 +1,6 @@ +OC.L10N.register( + "files", + { + "Close" : "关闭" +}, +"nplurals=1; plural=0;"); diff --git a/tests/data/apptheme/apps/files/l10n/zh-Hans.json b/tests/data/apptheme/apps/files/l10n/zh-Hans.json new file mode 100644 index 000000000000..2b2dddd2ce0b --- /dev/null +++ b/tests/data/apptheme/apps/files/l10n/zh-Hans.json @@ -0,0 +1,4 @@ +{ "translations": { + "Close" : "关闭" +},"pluralForm" :"nplurals=1; plural=0;" +} \ No newline at end of file diff --git a/tests/data/themes/abc/apps/files/l10n/en_GB.js b/tests/data/themes/abc/apps/files/l10n/en_GB.js index b59f761f81ea..2728de27e078 100644 --- a/tests/data/themes/abc/apps/files/l10n/en_GB.js +++ b/tests/data/themes/abc/apps/files/l10n/en_GB.js @@ -32,6 +32,7 @@ OC.L10N.register( "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -40,7 +41,12 @@ OC.L10N.register( "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -68,7 +74,10 @@ OC.L10N.register( "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -79,6 +88,7 @@ OC.L10N.register( "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -100,18 +110,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/tests/data/themes/abc/apps/files/l10n/en_GB.json b/tests/data/themes/abc/apps/files/l10n/en_GB.json index ddb33a3c76f7..eafd36e0f6dd 100644 --- a/tests/data/themes/abc/apps/files/l10n/en_GB.json +++ b/tests/data/themes/abc/apps/files/l10n/en_GB.json @@ -30,6 +30,7 @@ "Delete" : "Delete", "Disconnect storage" : "Disconnect storage", "Unshare" : "Unshare", + "How do you want to open this file?" : "How do you want to open this file?", "Could not load info for file \"{file}\"" : "Could not load info for file \"{file}\"", "Files" : "Files", "Details" : "Details", @@ -38,7 +39,12 @@ "Unable to determine date" : "Unable to determine date", "Invalid path" : "Invalid path", "This operation is forbidden" : "This operation is forbidden", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "Directory \"{dir}\" is unavailable, please contact the administrator", + "Storage for \"{dir}\" is temporarily not available" : "Storage for \"{dir}\" is temporarily not available", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare.", + "Directory \"{dir}\" not found" : "Directory \"{dir}\" not found", "group" : "group", + "Federated share" : "Federated share", "via" : "via", "Could not move \"{file}\", target exists" : "Could not move \"{file}\", target exists", "Could not move \"{file}\" because either the file or the target are locked." : "Could not move \"{file}\" because either the file or the target are locked.", @@ -66,7 +72,10 @@ "New" : "New", "Unknown user" : "Unknown user", "Lock status" : "Lock status", + "Lock file" : "Lock file", + "Failed to lock." : "Failed to lock.", "This resource is locked. Click to see more details." : "This resource is locked. Click to see more details.", + "Encountered problem accessing the folder {name}" : "Encountered problem accessing the folder {name}", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", "File name cannot contain \"/\"." : "File name cannot contain \"/\".", @@ -77,6 +86,7 @@ "Your storage is almost full ({usedSpacePercent}%)" : "Your storage is almost full ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["matches '{filter}'","match '{filter}'"], "{owner} has locked this resource via {path}" : "{owner} has locked this resource via {path}", + "Unlock" : "Unlock", "Could not unlock, please contact the lock owner {owner}" : "Could not unlock, please contact the lock owner {owner}", "Unlock failed with status {status}" : "Unlock failed with status {status}", "Locks" : "Locks", @@ -98,18 +108,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "Limit notifications about creation and changes to your favourite files (Stream only)", "A file or folder has been deleted" : "A file or folder has been deleted", "A file or folder has been restored" : "A file or folder has been restored", + "A file or folder has been renamed" : "A file or folder has been renamed", + "A file or folder has been moved" : "A file or folder has been moved", "You created %1$s" : "You created %1$s", "%2$s created %1$s" : "%2$s created %1$s", "%1$s was created in a public folder" : "%1$s was created in a public folder", "You changed %1$s" : "You changed %1$s", "%2$s changed %1$s" : "%2$s changed %1$s", "You deleted %1$s" : "You deleted %1$s", + "%1$s was deleted due to automation rule" : "%1$s was deleted due to automation rule", "%2$s deleted %1$s" : "%2$s deleted %1$s", "You restored %1$s" : "You restored %1$s", "%2$s restored %1$s" : "%2$s restored %1$s", + "You renamed %2$s to %1$s" : "You renamed %2$s to %1$s", + "%2$s renamed %3$s to %1$s" : "%2$s renamed %3$s to %1$s", + "You moved %2$s to %1$s" : "You moved %2$s to %1$s", + "%2$s moved %3$s to %1$s" : "%2$s moved %3$s to %1$s", "Changed by %2$s" : "Changed by %2$s", "Deleted by %2$s" : "Deleted by %2$s", "Restored by %2$s" : "Restored by %2$s", + "You moved this file to %1$s" : "You moved this file to %1$s", + "%2$s moved this file to %1$s" : "%2$s moved this file to %1$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "You don't have permissions to access this file/folder - Please contact the owner to share it with you.", "Upload (max. %s)" : "Upload (max. %s)", "Settings" : "Settings", diff --git a/tests/data/themes/abc/apps/files/l10n/es_AR.js b/tests/data/themes/abc/apps/files/l10n/es_AR.js index 8816d4343a4b..00bb6516ea80 100644 --- a/tests/data/themes/abc/apps/files/l10n/es_AR.js +++ b/tests/data/themes/abc/apps/files/l10n/es_AR.js @@ -57,6 +57,7 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/tests/data/themes/abc/apps/files/l10n/es_AR.json b/tests/data/themes/abc/apps/files/l10n/es_AR.json index 32234ffe7b30..bf2225b0796f 100644 --- a/tests/data/themes/abc/apps/files/l10n/es_AR.json +++ b/tests/data/themes/abc/apps/files/l10n/es_AR.json @@ -55,6 +55,7 @@ "%2$s deleted %1$s" : "%2$s eliminó %1$s", "Upload (max. %s)" : "Subir (máx. %s)", "Settings" : "Configuración", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", "No entries found in this folder" : "No se encontraron entradas en esta carpeta", "Select all" : "Seleccionar todos", diff --git a/tests/data/themes/abc/apps/files/l10n/he.js b/tests/data/themes/abc/apps/files/l10n/he.js index 7fa7a9daf71f..d67f5270639d 100644 --- a/tests/data/themes/abc/apps/files/l10n/he.js +++ b/tests/data/themes/abc/apps/files/l10n/he.js @@ -41,6 +41,10 @@ OC.L10N.register( "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -105,18 +109,27 @@ OC.L10N.register( "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/tests/data/themes/abc/apps/files/l10n/he.json b/tests/data/themes/abc/apps/files/l10n/he.json index a86a58598d91..8c8d331e7135 100644 --- a/tests/data/themes/abc/apps/files/l10n/he.json +++ b/tests/data/themes/abc/apps/files/l10n/he.json @@ -39,6 +39,10 @@ "Unable to determine date" : "לא ניתן לקבוע תאריך", "Invalid path" : "נתיב לא חוקי", "This operation is forbidden" : "פעולה זו אסורה", + "Directory \"{dir}\" is unavailable, please contact the administrator" : "התיקייה „{dir}” אינה זמינה, נא ליצור קשר עם ההנהלה", + "Storage for \"{dir}\" is temporarily not available" : "האחסון עבור „{dir}” אינו זמין זמנית", + "Shared directory \"{dir}\" is not available, remove the share or contact it's owner to reshare." : "התיקייה המשותפת „{dir}” אינה זמינה, יש להסיר את השיתוף או ליצור קשר עם הבעלים כדי לשתף מחדש.", + "Directory \"{dir}\" not found" : "התיקייה „{dir}” לא נמצאה", "group" : "קבוצה", "via" : "באמצעות", "Could not move \"{file}\", target exists" : "לא ניתן להעביר \"{file}\", קובץ מטרה קיים", @@ -103,18 +107,27 @@ "Limit notifications about creation and changes to your favorite files (Stream only)" : "הגבלת הודעות על יצירת או שינוי הקבצים המועדפים שלך (Stream only)", "A file or folder has been deleted" : "קובץ או תיקייה נמחקו", "A file or folder has been restored" : "קובץ או תיקייה שוחזר", + "A file or folder has been renamed" : "שם של קובץ או תיקייה נערכו", + "A file or folder has been moved" : "קובץ או תיקייה הועברו", "You created %1$s" : "יצרת %1$s", "%2$s created %1$s" : "%2$s נוצרו %1$s", "%1$s was created in a public folder" : "%1$s נוצר בתיקייה ציבורית", "You changed %1$s" : "שינית %1$s", "%2$s changed %1$s" : "%2$s שונו %1$s", "You deleted %1$s" : "מחקת %1$s", + "%1$s was deleted due to automation rule" : "%1$s נמחקה עקב כלל אוטומטי", "%2$s deleted %1$s" : "%2$s נמחקו %1$s", "You restored %1$s" : "שחזרת %1$s", "%2$s restored %1$s" : "%2$s שוחזרו %1$s", + "You renamed %2$s to %1$s" : "שיניתם את השם %2$s לשם %1$s", + "%2$s renamed %3$s to %1$s" : "השם של %3$s השתנה לשם %1$s על ידי %2$s", + "You moved %2$s to %1$s" : "העברת את %2$s אל %1$s", + "%2$s moved %3$s to %1$s" : "%3$s הועבר אל %1$s על ידי %2$s", "Changed by %2$s" : "שונו על ידי %2$s", "Deleted by %2$s" : "נמחקו על ידי %2$s", "Restored by %2$s" : "שוחזרו על ידי %2$s", + "You moved this file to %1$s" : "העברת את הקובץ הזה אל %1$s", + "%2$s moved this file to %1$s" : "הקובץ הזה הועבר אל %1$s על ידי %2$s", "You don't have permissions to access this file/folder - Please contact the owner to share it with you." : "אין לך הרשאות לגשת לקובץ/תיקייה - יש ליצור קשר עם הבעלים לשיתופם איתך.", "Upload (max. %s)" : "העלאה (מקסימום %s)", "Settings" : "הגדרות", diff --git a/tests/data/themes/abc/apps/files/l10n/zh-Hans.js b/tests/data/themes/abc/apps/files/l10n/zh-Hans.js new file mode 100644 index 000000000000..14da401f67fb --- /dev/null +++ b/tests/data/themes/abc/apps/files/l10n/zh-Hans.js @@ -0,0 +1,6 @@ +OC.L10N.register( + "files", + { + "Close" : "关闭" +}, +"nplurals=1; plural=0;"); diff --git a/tests/data/themes/abc/apps/files/l10n/zh-Hans.json b/tests/data/themes/abc/apps/files/l10n/zh-Hans.json new file mode 100644 index 000000000000..2b2dddd2ce0b --- /dev/null +++ b/tests/data/themes/abc/apps/files/l10n/zh-Hans.json @@ -0,0 +1,4 @@ +{ "translations": { + "Close" : "关闭" +},"pluralForm" :"nplurals=1; plural=0;" +} \ No newline at end of file diff --git a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php index 271fa500549d..07aee1ceb9ca 100644 --- a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php @@ -40,6 +40,7 @@ use OCP\ISession; use OCP\AppFramework\Controller; use OCP\IUserSession; +use ReflectionException; use Test\TestCase; use OCP\AppFramework\Http\Response; use OCP\IConfig; @@ -135,7 +136,7 @@ private function getMiddleware($isLoggedIn, $isAdminUser) { * @PublicPage * @NoCSRFRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testSetNavigationEntry() { $this->navigationManager->expects($this->once()) @@ -150,7 +151,7 @@ public function testSetNavigationEntry() { * @param string $method * @param string $test * @param $status - * @throws \ReflectionException + * @throws ReflectionException */ private function ajaxExceptionStatus($method, $test, $status) { $isLoggedIn = false; @@ -178,7 +179,7 @@ private function ajaxExceptionStatus($method, $test, $status) { } /** - * @throws \ReflectionException + * @throws ReflectionException */ public function testAjaxStatusLoggedInCheck() { $this->ajaxExceptionStatus( @@ -190,7 +191,7 @@ public function testAjaxStatusLoggedInCheck() { /** * @NoCSRFRequired - * @throws \ReflectionException + * @throws ReflectionException */ public function testAjaxNotAdminCheck() { $this->ajaxExceptionStatus( @@ -202,7 +203,7 @@ public function testAjaxNotAdminCheck() { /** * @PublicPage - * @throws \ReflectionException + * @throws ReflectionException */ public function testAjaxStatusCSRFCheck() { $this->ajaxExceptionStatus( @@ -215,10 +216,7 @@ public function testAjaxStatusCSRFCheck() { /** * @PublicPage * @NoCSRFRequired - * @throws \ReflectionException - * @throws \ReflectionException - * @throws \ReflectionException - * @throws \ReflectionException + * @throws ReflectionException */ public function testAjaxStatusAllGood() { $this->ajaxExceptionStatus( @@ -247,7 +245,7 @@ public function testAjaxStatusAllGood() { * @PublicPage * @NoCSRFRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testNoChecks() { $this->request->expects($this->never()) @@ -265,7 +263,7 @@ public function testNoChecks() { * @param string $expects * @param bool $shouldFail * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ private function securityCheck($method, $expects, $shouldFail=false) { // admin check requires login @@ -292,10 +290,10 @@ private function securityCheck($method, $expects, $shouldFail=false) { /** * @PublicPage * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testCsrfCheck() { - $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException::class); + $this->expectException(CrossSiteRequestForgeryException::class); $this->request->expects($this->once()) ->method('passesCSRFCheck') @@ -309,7 +307,7 @@ public function testCsrfCheck() { * @PublicPage * @NoCSRFRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testNoCsrfCheck() { $this->request->expects($this->never()) @@ -323,7 +321,7 @@ public function testNoCsrfCheck() { /** * @PublicPage * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testFailCsrfCheck() { $this->request->expects($this->once()) @@ -334,11 +332,29 @@ public function testFailCsrfCheck() { $this->middleware->beforeController(__CLASS__, __FUNCTION__); } + /** + * @PublicPage + * @throws SecurityException + * @throws ReflectionException + */ + public function testFailCsrfCheckWithoutAuthHeader(): void { + $this->expectException(CrossSiteRequestForgeryException::class); + $this->request->expects($this->once()) + ->method('passesCSRFCheck') + ->willReturn(false); + $this->request + ->method('getHeader') + ->willReturn(''); + + $this->reader->reflect(__CLASS__, __FUNCTION__); + $this->middleware->beforeController(__CLASS__, __FUNCTION__); + } + /** * @NoCSRFRequired * @NoAdminRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testLoggedInCheck() { $this->securityCheck(__FUNCTION__, 'isLoggedIn'); @@ -348,7 +364,7 @@ public function testLoggedInCheck() { * @NoCSRFRequired * @NoAdminRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testFailLoggedInCheck() { $this->securityCheck(__FUNCTION__, 'isLoggedIn', true); @@ -357,7 +373,7 @@ public function testFailLoggedInCheck() { /** * @NoCSRFRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testIsAdminCheck() { $this->securityCheck(__FUNCTION__, 'isAdminUser'); @@ -366,7 +382,7 @@ public function testIsAdminCheck() { /** * @NoCSRFRequired * @throws SecurityException - * @throws \ReflectionException + * @throws ReflectionException */ public function testFailIsAdminCheck() { $this->securityCheck(__FUNCTION__, 'isAdminUser', true); diff --git a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php index d8116691cea0..9e7b332ab11a 100644 --- a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php +++ b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php @@ -23,6 +23,7 @@ namespace Test\Authentication\TwoFactorAuth; use OC\Authentication\TwoFactorAuth\Manager; +use OCP\IGroupManager; use Test\TestCase; class ManagerTest extends TestCase { @@ -35,6 +36,9 @@ class ManagerTest extends TestCase { /** @var \OCP\ISession|\PHPUnit\Framework\MockObject\MockObject */ private $session; + /** @var IGroupManager */ + private $groupManager; + /** @var Manager */ private $manager; @@ -58,12 +62,13 @@ protected function setUp(): void { ->disableOriginalConstructor() ->getMock(); $this->session = $this->createMock('\OCP\ISession'); + $this->groupManager = $this->createMock(IGroupManager::class); $this->config = $this->createMock('\OCP\IConfig'); $this->request = $this->createMock('\OCP\IRequest'); $this->logger = $this->createMock('\OCP\ILogger'); $this->manager = $this->getMockBuilder('\OC\Authentication\TwoFactorAuth\Manager') - ->setConstructorArgs([$this->appManager, $this->session, $this->config, $this->request, $this->logger]) + ->setConstructorArgs([$this->appManager, $this->session, $this->groupManager, $this->config, $this->request, $this->logger]) ->setMethods(['loadTwoFactorApp']) // Do not actually load the apps ->getMock(); @@ -139,6 +144,100 @@ public function testIsTwoFactorAuthenticated() { $this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user)); } + public function testIsTwoFactorAuthenticatedEnforcedNotExcluded() { + $this->prepareProviders(); + + $this->user->expects($this->never()) + ->method('getUID') + ->will($this->returnValue('user123')); + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '[]'], + ])); + $this->config->expects($this->never()) + ->method('getUserValue'); + + $this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user)); + } + + public function testIsTwoFactorAuthenticatedEnforcedButExcludedAndDisabled() { + $this->user->method('getUID') + ->will($this->returnValue('user123')); + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '["not2faGroup"]'], + ])); + $this->config->expects($this->once()) + ->method('getUserValue') + ->with('user123', 'core', 'two_factor_auth_disabled', 0) + ->will($this->returnValue(1)); + $this->groupManager->method('isInGroup') + ->with('user123', 'not2faGroup') + ->willReturn(true); + + $this->assertFalse($this->manager->isTwoFactorAuthenticated($this->user)); + } + + public function testIsTwoFactorAuthenticatedEnforcedButExcludedAndNotDisabled() { + $this->prepareProviders(); + + $this->user->method('getUID') + ->will($this->returnValue('user123')); + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '["not2faGroup"]'], + ])); + $this->config->expects($this->once()) + ->method('getUserValue') + ->with('user123', 'core', 'two_factor_auth_disabled', 0) + ->will($this->returnValue(0)); + $this->groupManager->method('isInGroup') + ->with('user123', 'not2faGroup') + ->willReturn(true); + + $this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user)); + } + + public function testIsTwoFactorEnforcedForUser() { + $this->user->method('getUID') + ->will($this->returnValue('user123')); + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '[]'], + ])); + + $this->assertTrue($this->manager->isTwoFactorEnforcedForUser($this->user)); + } + + public function testIsTwoFactorEnforcedForUserInExcludedGroup() { + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'no'], + ['core', 'enforce_2fa_excluded_groups', '[]', '["not2faGroup"]'], + ])); + + $this->assertFalse($this->manager->isTwoFactorEnforcedForUser($this->user)); + } + + public function testIsTwoFactorEnforcedForUserNotEnforced() { + $this->user->method('getUID') + ->will($this->returnValue('user123')); + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'enforce_2fa', 'no', 'yes'], + ['core', 'enforce_2fa_excluded_groups', '[]', '["not2faGroup"]'], + ])); + $this->groupManager->method('isInGroup') + ->with('user123', 'not2faGroup') + ->willReturn(true); + + $this->assertFalse($this->manager->isTwoFactorEnforcedForUser($this->user)); + } + public function testGetProvider() { $this->prepareProviders(); diff --git a/tests/lib/Command/Integrity/SignAppTest.php b/tests/lib/Command/Integrity/SignAppTest.php index bf7924e43b88..74de88b6a0d9 100644 --- a/tests/lib/Command/Integrity/SignAppTest.php +++ b/tests/lib/Command/Integrity/SignAppTest.php @@ -164,7 +164,7 @@ public function testExecuteWithNotExistingPrivateKey() { $outputInterface ->expects($this->once()) ->method('writeln') - ->with('Private key "privateKey" does not exists.'); + ->with('Private key "privateKey" does not exist.'); $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]); } @@ -201,7 +201,7 @@ public function testExecuteWithNotExistingCertificate() { $outputInterface ->expects($this->once()) ->method('writeln') - ->with('Certificate "certificate" does not exists.'); + ->with('Certificate "certificate" does not exist.'); $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]); } diff --git a/tests/lib/Command/Integrity/SignCoreTest.php b/tests/lib/Command/Integrity/SignCoreTest.php index e960de824ff4..94a4ab8ff803 100644 --- a/tests/lib/Command/Integrity/SignCoreTest.php +++ b/tests/lib/Command/Integrity/SignCoreTest.php @@ -123,7 +123,7 @@ public function testExecuteWithNotExistingPrivateKey() { $outputInterface ->expects($this->once()) ->method('writeln') - ->with('Private key "privateKey" does not exists.'); + ->with('Private key "privateKey" does not exist.'); $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]); } @@ -160,7 +160,7 @@ public function testExecuteWithNotExistingCertificate() { $outputInterface ->expects($this->once()) ->method('writeln') - ->with('Certificate "certificate" does not exists.'); + ->with('Certificate "certificate" does not exist.'); $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]); } diff --git a/tests/lib/Encryption/DecryptAllTest.php b/tests/lib/Encryption/DecryptAllTest.php index da42efc78e7f..8978a19ca568 100644 --- a/tests/lib/Encryption/DecryptAllTest.php +++ b/tests/lib/Encryption/DecryptAllTest.php @@ -102,8 +102,11 @@ public function setUp(): void { $this->userInterface = $this->getMockBuilder(UserInterface::class) ->disableOriginalConstructor()->getMock(); + $outputFormatterInterface = $this->createMock(OutputFormatterInterface::class); + $outputFormatterInterface->expects($this->any())->method('isDecorated') + ->willReturn(false); $this->outputInterface->expects($this->any())->method('getFormatter') - ->willReturn($this->createMock(OutputFormatterInterface::class)); + ->willReturn($outputFormatterInterface); $this->instance = new DecryptAll($this->encryptionManager, $this->userManager, $this->view, $this->logger); diff --git a/tests/lib/Files/Stream/ChecksumTest.php b/tests/lib/Files/Stream/ChecksumTest.php index db731158f66c..da7b845cb557 100644 --- a/tests/lib/Files/Stream/ChecksumTest.php +++ b/tests/lib/Files/Stream/ChecksumTest.php @@ -53,7 +53,7 @@ public function testRead() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename, 'rb'); $contentRead = stream_get_contents($fp); \fclose($fp); @@ -74,7 +74,7 @@ public function testSkipRead() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename, 'rb'); \fseek($fp, 10, SEEK_SET); $contentRead = stream_get_contents($fp); @@ -97,7 +97,7 @@ public function testUnfinishedRead() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename, 'rb'); $contentRead = \fread($fp, 10); \fclose($fp); @@ -121,7 +121,7 @@ public function testUnfinishedReadButFullChunk() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename, 'rb'); $contentRead = \fread($fp, 10); \fclose($fp); @@ -144,7 +144,7 @@ public function testJumpRead() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb'), $filename, 'rb'); $contentRead = \fread($fp, 10); \fseek($fp, 3, SEEK_CUR); @@ -164,7 +164,7 @@ public function testWrite() { $filename = 'test001.txt'; $file = $this->getVfsFile($filename); - $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename, 'wb'); $contentWritten = \fwrite($fp, $content); \fclose($fp); @@ -187,7 +187,7 @@ public function testAppend() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'ab'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'ab'), $filename, 'ab'); $contentWritten = \fwrite($fp, "{$content}zzz"); \fclose($fp); @@ -205,7 +205,7 @@ public function testReadAndWrite() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb+'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb+'), $filename, 'rb+'); $contentWritten = \fwrite($fp, 'zzz'); $contentRead = \fread($fp, 1000); @@ -228,7 +228,7 @@ public function testReadAndWrite2() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'rb+'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'rb+'), $filename, 'rb+'); $contentWritten = \fwrite($fp, 'zzz'); \fclose($fp); @@ -247,7 +247,7 @@ public function testWriteNotTruncate() { $file = $this->getVfsFile($filename); $file->setContent($content); - $fp = Checksum::wrap(\fopen($file->url(), 'cb+'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'cb+'), $filename, 'cb+'); $contentWritten = \fwrite($fp, 'zzz'); \fclose($fp); @@ -266,7 +266,7 @@ public function testWriteJumpBack() { $filename = 'test001.txt'; $file = $this->getVfsFile($filename); - $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename, 'wb'); $contentWritten = \fwrite($fp, $content); \fseek($fp, 7, SEEK_SET); @@ -290,7 +290,7 @@ public function testWriteJumpBeginning() { $filename = 'test001.txt'; $file = $this->getVfsFile($filename); - $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename); + $fp = Checksum::wrap(\fopen($file->url(), 'wb'), $filename, 'wb'); $contentWritten = \fwrite($fp, $content); \fseek($fp, 0, SEEK_SET); diff --git a/tests/lib/PreviewCleanupTest.php b/tests/lib/PreviewCleanupTest.php index 247acff6c82b..2e777db5fa1c 100644 --- a/tests/lib/PreviewCleanupTest.php +++ b/tests/lib/PreviewCleanupTest.php @@ -97,6 +97,18 @@ public function test(): void { # create preview $thumbnailFolderUser2 = $this->createPreview($sharedTextFile, $rootFolder, $sharedTextFileId); + # assert thumbnail exists after createPreview + self::assertTrue($thumbnailFolderUser1->nodeExists($textFileId)); + self::assertTrue($thumbnailFolderUser2->nodeExists($sharedTextFileId)); + + # run cleanup command + $cmd = new PreviewCleanup(\OC::$server->getDatabaseConnection()); + $cmd->process(); + + # assert thumbnail still exists after cleanup run without deleting + self::assertTrue($thumbnailFolderUser1->nodeExists($textFileId)); + self::assertTrue($thumbnailFolderUser2->nodeExists($sharedTextFileId)); + # delete file $textFile->delete(); diff --git a/tests/lib/Repair/AppsTest.php b/tests/lib/Repair/AppsTest.php index 2c4287beecc4..f7b48e4c9c6a 100644 --- a/tests/lib/Repair/AppsTest.php +++ b/tests/lib/Repair/AppsTest.php @@ -49,6 +49,12 @@ protected function setUp(): void { $this->appManager = $this->createMock(IAppManager::class); $this->defaults = $this->createMock(\OC_Defaults::class); $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $this->eventDispatcher->expects($this->any())->method('dispatch') + ->will( + $this->returnCallback(function ($object) { + return $object; + }) + ); $this->config = $this->createMock(IConfig::class); $this->repair = new Apps( $this->appManager, diff --git a/tests/lib/TempManagerTest.php b/tests/lib/TempManagerTest.php index ea39d2f6108f..c11876544217 100644 --- a/tests/lib/TempManagerTest.php +++ b/tests/lib/TempManagerTest.php @@ -10,6 +10,7 @@ namespace Test; use OC\Log; +use OCP\IConfig; class NullLogger extends Log { public function __construct($logger = null) { @@ -21,13 +22,13 @@ public function log($level, $message, array $context = []) { } } -class TempManagerTest extends \Test\TestCase { - protected $baseDir = null; +class TempManagerTest extends TestCase { + protected $baseDir; protected function setUp(): void { parent::setUp(); - $this->baseDir = $this->getManager()->getTempBaseDir() . $this->getUniqueID('/oc_tmp_test'); + $this->baseDir = $this->getManager()->getTempBaseDir() . self::getUniqueID('/oc_tmp_test'); if (!\is_dir($this->baseDir)) { \mkdir($this->baseDir); } @@ -39,17 +40,12 @@ protected function tearDown(): void { parent::tearDown(); } - /** - * @param \OCP\ILogger $logger - * @param \OCP\IConfig $config - * @return \OC\TempManager - */ - protected function getManager($logger = null, $config = null) { + protected function getManager(\OCP\ILogger $logger = null, IConfig $config = null): \OC\TempManager { if (!$logger) { $logger = new NullLogger(); } if (!$config) { - $config = $this->createMock('\OCP\IConfig'); + $config = $this->createMock(IConfig::class); $config->method('getSystemValue') ->with('tempdirectory', null) ->willReturn('/tmp'); @@ -61,7 +57,7 @@ protected function getManager($logger = null, $config = null) { return $manager; } - public function testGetFile() { + public function testGetFile(): void { $manager = $this->getManager(); $file = $manager->getTemporaryFile('txt'); $this->assertStringEndsWith('.txt', $file); @@ -72,18 +68,18 @@ public function testGetFile() { $this->assertStringEqualsFile($file, 'bar'); } - public function testGetFolder() { + public function testGetFolder(): void { $manager = $this->getManager(); $folder = $manager->getTemporaryFolder(); $this->assertStringEndsWith('/', $folder); - $this->assertTrue(\is_dir($folder)); + $this->assertDirectoryExists($folder); $this->assertTrue(\is_writable($folder)); \file_put_contents($folder . 'foo.txt', 'bar'); $this->assertStringEqualsFile($folder . 'foo.txt', 'bar'); } - public function testCleanFiles() { + public function testCleanFiles(): void { $manager = $this->getManager(); $file1 = $manager->getTemporaryFile('txt'); $file2 = $manager->getTemporaryFile('txt'); @@ -96,7 +92,7 @@ public function testCleanFiles() { $this->assertFileDoesNotExist($file2); } - public function testCleanFolder() { + public function testCleanFolder(): void { $manager = $this->getManager(); $folder1 = $manager->getTemporaryFolder(); $folder2 = $manager->getTemporaryFolder(); @@ -115,7 +111,7 @@ public function testCleanFolder() { $this->assertFileDoesNotExist($folder1 . 'bar.txt'); } - public function testCleanOld() { + public function testCleanOld(): void { $manager = $this->getManager(); $oldFile = $manager->getTemporaryFile('txt'); $newFile = $manager->getTemporaryFile('txt'); @@ -136,11 +132,11 @@ public function testCleanOld() { $this->assertFileExists($newFile); } - public function testLogCantCreateFile() { + public function testLogCantCreateFile(): void { if ($this->getCurrentUser() === 'root') { $this->markTestSkipped('You are running tests as root - this test will not work in this case.'); } - $logger = $this->createMock('\Test\NullLogger'); + $logger = $this->createMock(NullLogger::class); $manager = $this->getManager($logger); \chmod($this->baseDir, 0500); $logger->expects($this->once()) @@ -149,11 +145,11 @@ public function testLogCantCreateFile() { $this->assertFalse($manager->getTemporaryFile('txt')); } - public function testLogCantCreateFolder() { + public function testLogCantCreateFolder(): void { if ($this->getCurrentUser() === 'root') { $this->markTestSkipped('You are running tests as root - this test will not work in this case.'); } - $logger = $this->createMock('\Test\NullLogger'); + $logger = $this->createMock(NullLogger::class); $manager = $this->getManager($logger); \chmod($this->baseDir, 0500); $logger->expects($this->once()) @@ -162,8 +158,8 @@ public function testLogCantCreateFolder() { $this->assertFalse($manager->getTemporaryFolder()); } - public function testBuildFileNameWithPostfix() { - $logger = $this->createMock('\Test\NullLogger'); + public function testBuildFileNameWithPostfix(): void { + $logger = $this->createMock(NullLogger::class); $tmpManager = self::invokePrivate( $this->getManager($logger), 'buildFileNameWithSuffix', @@ -173,8 +169,8 @@ public function testBuildFileNameWithPostfix() { $this->assertEquals('/tmp/myTemporaryFile-.postfix', $tmpManager); } - public function testBuildFileNameWithoutPostfix() { - $logger = $this->createMock('\Test\NullLogger'); + public function testBuildFileNameWithoutPostfix(): void { + $logger = $this->createMock(NullLogger::class); $tmpManager = self::invokePrivate( $this->getManager($logger), 'buildFileNameWithSuffix', @@ -184,8 +180,8 @@ public function testBuildFileNameWithoutPostfix() { $this->assertEquals('/tmp/myTemporaryFile', $tmpManager); } - public function testBuildFileNameWithSuffixPathTraversal() { - $logger = $this->createMock('\Test\NullLogger'); + public function testBuildFileNameWithSuffixPathTraversal(): void { + $logger = $this->createMock(NullLogger::class); $tmpManager = self::invokePrivate( $this->getManager($logger), 'buildFileNameWithSuffix', @@ -196,10 +192,10 @@ public function testBuildFileNameWithSuffixPathTraversal() { $this->assertStringEndsWith('.Traversal..FileName', $tmpManager); } - public function testGetTempBaseDirFromConfig() { + public function testGetTempBaseDirFromConfig(): void { $dir = $this->getManager()->getTemporaryFolder(); - $config = $this->createMock('\OCP\IConfig'); + $config = $this->createMock(IConfig::class); $config->expects($this->once()) ->method('getSystemValue') ->with('tempdirectory', null) diff --git a/vendor-bin/behat/composer.json b/vendor-bin/behat/composer.json index cc3d1a0c91e8..9ca3d73187b3 100644 --- a/vendor-bin/behat/composer.json +++ b/vendor-bin/behat/composer.json @@ -1,6 +1,6 @@ { "require": { - "behat/behat": "^3.11", + "behat/behat": "^3.13", "behat/gherkin": "^4.9", "behat/mink": "1.7.1", "behat/mink-extension": "^2.3", @@ -8,10 +8,10 @@ "ciaranmcnulty/behat-stepthroughextension" : "dev-master", "rdx/behat-variables": "^1.2", "sensiolabs/behat-page-object-extension": "^2.3", - "symfony/translation": "^4.4", + "symfony/translation": "^5.4", "sabre/xml": "^2.2", - "guzzlehttp/guzzle": "^7.5", - "phpunit/phpunit": "^9.5", + "guzzlehttp/guzzle": "^7.7", + "phpunit/phpunit": "^9.6", "laminas/laminas-ldap": "^2.15", "ankitpokhrel/tus-php": "^2.3", "helmich/phpunit-json-assert": "^3.4" diff --git a/vendor-bin/owncloud-codestyle/composer.json b/vendor-bin/owncloud-codestyle/composer.json index 381cb6308ab6..01654042f6d3 100644 --- a/vendor-bin/owncloud-codestyle/composer.json +++ b/vendor-bin/owncloud-codestyle/composer.json @@ -1,5 +1,5 @@ { "require": { - "owncloud/coding-standard": "^4.0" + "owncloud/coding-standard": "^4.2" } } diff --git a/vendor-bin/phpstan/composer.json b/vendor-bin/phpstan/composer.json index 06273a8e46d9..90c99dfdb777 100644 --- a/vendor-bin/phpstan/composer.json +++ b/vendor-bin/phpstan/composer.json @@ -1,5 +1,5 @@ { "require": { - "phpstan/phpstan": "^1.9" + "phpstan/phpstan": "^1.10" } } diff --git a/version.php b/version.php index a70a567bda66..8789d7316679 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = [10, 12, 1, 3]; +$OC_Version = [10, 13, 0, 0]; // The human-readable string -$OC_VersionString = '10.12.1'; +$OC_VersionString = '10.13.0 prealpha'; $OC_VersionCanBeUpgradedFrom = [[8, 2, 11],[9, 0, 9],[9, 1]];