mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-24 14:50:39 -05:00
Compare commits
60 Commits
caseSearch
...
adjust-fro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b3e6751c1 | ||
|
|
be06000c13 | ||
|
|
b0809eab95 | ||
|
|
bcba82414f | ||
|
|
6aee5d17f7 | ||
|
|
ca9ccf65af | ||
|
|
0cfc7eb549 | ||
|
|
d7c87a0dd5 | ||
|
|
f0971d9fe4 | ||
|
|
be1e328ded | ||
|
|
d2f28c3464 | ||
|
|
07fa4b9aa3 | ||
|
|
72bc94d0c9 | ||
|
|
4d52257558 | ||
|
|
abd6773fbd | ||
|
|
990426ca68 | ||
|
|
96cbff74b7 | ||
|
|
cacba3ee39 | ||
|
|
80926aef0a | ||
|
|
4ad12a842f | ||
|
|
32d694a3e2 | ||
|
|
38169e60ae | ||
|
|
1e8ddbbf46 | ||
|
|
0e0cf3f30d | ||
|
|
715e27f728 | ||
|
|
a9449a816a | ||
|
|
db508d52b6 | ||
|
|
675d310067 | ||
|
|
094b5ee3eb | ||
|
|
573e87b8c3 | ||
|
|
adf9580431 | ||
|
|
ec7643eeb7 | ||
|
|
77e538f177 | ||
|
|
ee2ca4455c | ||
|
|
9b4d07e8fc | ||
|
|
ab0821956f | ||
|
|
b08cfb8271 | ||
|
|
abc4a8de8c | ||
|
|
9e5f0debe8 | ||
|
|
64867a5dc8 | ||
|
|
eb41616a98 | ||
|
|
f6c4d9f526 | ||
|
|
558343dacd | ||
|
|
8824201bb4 | ||
|
|
ab6cf63efe | ||
|
|
308f801f03 | ||
|
|
7c8174bb80 | ||
|
|
c659ac6972 | ||
|
|
fac80402bf | ||
|
|
dcf78f7f3d | ||
|
|
eb1ee57db9 | ||
|
|
102e92fd73 | ||
|
|
95f28baa52 | ||
|
|
b41ff0f424 | ||
|
|
b05deb8a5e | ||
|
|
0a04c7ac43 | ||
|
|
62bc7313da | ||
|
|
e7d4551b05 | ||
|
|
452d40dad7 | ||
|
|
0e758c687b |
@@ -132,6 +132,7 @@ config = {
|
||||
"suites": [
|
||||
"apiGraph",
|
||||
"apiServiceAvailability",
|
||||
"collaborativePosix",
|
||||
],
|
||||
"skip": False,
|
||||
"withRemotePhp": [True],
|
||||
@@ -900,7 +901,7 @@ def localApiTestPipeline(ctx):
|
||||
for storage in params["storages"]:
|
||||
for run_with_remote_php in params["withRemotePhp"]:
|
||||
pipeline = {
|
||||
"name": "%s-%s%s-%s" % ("CLI" if name.startswith("cli") else "API", name, "-withoutRemotePhp" if not run_with_remote_php else "", storage),
|
||||
"name": "%s-%s%s-%s" % ("CLI" if name.startswith("cli") else "API", name, "-withoutRemotePhp" if not run_with_remote_php else "", "decomposed" if name.startswith("cli") else storage),
|
||||
"steps": restoreBuildArtifactCache(ctx, dirs["opencloudBinArtifact"], dirs["opencloudBinPath"]) +
|
||||
(tikaService() if params["tikaNeeded"] else []) +
|
||||
(waitForServices("online-offices", ["collabora:9980", "onlyoffice:443", "fakeoffice:8080"]) if params["collaborationServiceNeeded"] else []) +
|
||||
@@ -931,7 +932,7 @@ def localApiTestPipeline(ctx):
|
||||
|
||||
def localApiTests(name, suites, storage = "decomposed", extra_environment = {}, with_remote_php = False):
|
||||
test_dir = "%s/tests/acceptance" % dirs["base"]
|
||||
expected_failures_file = "%s/expected-failures-localAPI-on-decomposed-storage.md" % test_dir
|
||||
expected_failures_file = "%s/expected-failures-localAPI-on-%s-storage.md" % (test_dir, storage)
|
||||
|
||||
environment = {
|
||||
"TEST_SERVER_URL": OC_URL,
|
||||
@@ -939,12 +940,13 @@ def localApiTests(name, suites, storage = "decomposed", extra_environment = {},
|
||||
"SEND_SCENARIO_LINE_REFERENCES": True,
|
||||
"STORAGE_DRIVER": storage,
|
||||
"BEHAT_SUITES": ",".join(suites),
|
||||
"BEHAT_FILTER_TAGS": "~@skip&&~@skipOnGraph&&~@skipOnOpencloud-%s-Storage" % storage,
|
||||
"BEHAT_FILTER_TAGS": "~@skip&&~@skipOnOpencloud-%s-Storage" % storage,
|
||||
"EXPECTED_FAILURES_FILE": expected_failures_file,
|
||||
"UPLOAD_DELETE_WAIT_TIME": "1" if storage == "owncloud" else 0,
|
||||
"OC_WRAPPER_URL": "http://%s:5200" % OC_SERVER_NAME,
|
||||
"WITH_REMOTE_PHP": with_remote_php,
|
||||
"COLLABORATION_SERVICE_URL": "http://wopi-fakeoffice:9300",
|
||||
"OC_STORAGE_PATH": "$HOME/.opencloud/storage/users",
|
||||
}
|
||||
|
||||
for item in extra_environment:
|
||||
@@ -1107,7 +1109,7 @@ def coreApiTests(ctx, part_number = 1, number_of_parts = 1, with_remote_php = Fa
|
||||
storage = "posix"
|
||||
if "[decomposed]" in ctx.build.title.lower():
|
||||
storage = "decomposed"
|
||||
filterTags = "~@skipOnGraph&&~@skipOnOpencloud-%s-Storage" % storage
|
||||
filterTags = "~@skipOnOpencloud-%s-Storage" % storage
|
||||
test_dir = "%s/tests/acceptance" % dirs["base"]
|
||||
expected_failures_file = "%s/expected-failures-API-on-%s-storage.md" % (test_dir, storage)
|
||||
|
||||
@@ -2001,6 +2003,8 @@ def opencloudServer(storage = "decomposed", accounts_hash_difficulty = 4, depend
|
||||
},
|
||||
},
|
||||
"commands": [
|
||||
"apt-get update",
|
||||
"apt-get install -y inotify-tools",
|
||||
"%s init --insecure true" % dirs["opencloudBin"],
|
||||
"cat $OC_CONFIG_DIR/opencloud.yaml",
|
||||
"cp tests/config/woodpecker/app-registry.yaml $OC_CONFIG_DIR/app-registry.yaml",
|
||||
|
||||
@@ -182,7 +182,7 @@ COLLABORA=:collabora.yml
|
||||
# Domain of Collabora, where you can find the frontend.
|
||||
# Defaults to "collabora.opencloud.test"
|
||||
COLLABORA_DOMAIN=
|
||||
# Domain of the wopiserver which handles OnlyOffice.
|
||||
# Domain of the wopiserver which handles Collabora.
|
||||
# Defaults to "wopiserver.opencloud.test"
|
||||
WOPISERVER_DOMAIN=
|
||||
# Admin user for Collabora.
|
||||
@@ -225,19 +225,10 @@ COLLABORA_SSL_VERIFICATION=false
|
||||
# Defaults to "partial"
|
||||
#ANTIVIRUS_MAX_SCAN_SIZE_MODE=
|
||||
# Image version of the ClamAV container.
|
||||
# Defaults to "latest"
|
||||
# Defaults to "latest"y
|
||||
CLAMAV_DOCKER_TAG=
|
||||
|
||||
|
||||
### OnlyOffice Settings ###
|
||||
# Note: the leading colon is required to enable the service.
|
||||
#ONLYOFFICE=:onlyoffice.yml
|
||||
# Domain for OnlyOffice. Defaults to "onlyoffice.opencloud.test".
|
||||
ONLYOFFICE_DOMAIN=
|
||||
# Domain for the wopiserver which handles OnlyOffice.
|
||||
WOPISERVER_ONLYOFFICE_DOMAIN=
|
||||
|
||||
|
||||
### Inbucket Settings ###
|
||||
# Inbucket is a mail catcher tool for testing purposes.
|
||||
# DO NOT use in Production.
|
||||
@@ -294,8 +285,23 @@ KEYCLOAK_ADMIN_PASSWORD=
|
||||
# Autoprovisioning mode. Defaults to "true"
|
||||
#KEYCLOAK_AUTOPROVISIONING=:keycloak-autoprovisioning.yml
|
||||
|
||||
### Radicale Setting ###
|
||||
# Radicale is a small open-source CalDAV (calendars, to-do lists) and CardDAV (contacts) server.
|
||||
# When enabled OpenCloud is configured as a reverse proxy for Radicale, providing all authenticated
|
||||
# OpenCloud users access to a Personal Calendar and Addressbook
|
||||
#RADICALE=:radicale.yml
|
||||
# Docker image to use for the Radicale Container
|
||||
#RADICALE_DOCKER_IMAGE=opencloudeu/radicale
|
||||
# Docker tag to pull for the Radicale Container
|
||||
#RADICALE_DOCKER_TAG=latest
|
||||
# Define the storage location for the Radicale data. Set the path to a local path.
|
||||
# Ensure that the configuration and data directories are owned by the user and group with ID 1000:1000.
|
||||
# This matches the default user inside the container and avoids permission issues when accessing files.
|
||||
# Leaving it default stores data in docker internal volumes.
|
||||
#RADICALE_DATA_DIR=/your/local/radicale/data
|
||||
|
||||
## IMPORTANT ##
|
||||
# This MUST be the last line as it assembles the supplemental compose files to be used.
|
||||
# ALL supplemental configs must be added here, whether commented or not.
|
||||
# Each var must either be empty or contain :path/file.yml
|
||||
COMPOSE_FILE=docker-compose.yml${OPENCLOUD:-}${TIKA:-}${DECOMPOSEDS3:-}${DECOMPOSEDS3_MINIO:-}${DECOMPOSED:-}${COLLABORA:-}${MONITORING:-}${IMPORTER:-}${CLAMAV:-}${ONLYOFFICE:-}${INBUCKET:-}${EXTENSIONS:-}${UNZIP:-}${DRAWIO:-}${JSONVIEWER:-}${PROGRESSBARS:-}${EXTERNALSITES:-}${KEYCLOAK:-}${LDAP:-}${KEYCLOAK_AUTOPROVISIONING:-}${LDAP_MANAGER:-}
|
||||
COMPOSE_FILE=docker-compose.yml${OPENCLOUD:-}${TIKA:-}${DECOMPOSEDS3:-}${DECOMPOSEDS3_MINIO:-}${DECOMPOSED:-}${COLLABORA:-}${MONITORING:-}${IMPORTER:-}${CLAMAV:-}${INBUCKET:-}${EXTENSIONS:-}${UNZIP:-}${DRAWIO:-}${JSONVIEWER:-}${PROGRESSBARS:-}${EXTERNALSITES:-}${KEYCLOAK:-}${LDAP:-}${KEYCLOAK_AUTOPROVISIONING:-}${LDAP_MANAGER:-}${RADICALE:-}
|
||||
|
||||
@@ -53,7 +53,7 @@ services:
|
||||
restart: always
|
||||
|
||||
collabora:
|
||||
image: collabora/code:24.04.13.2.1
|
||||
image: collabora/code:25.04.1.1.1
|
||||
# release notes: https://www.collaboraonline.com/release-notes/
|
||||
networks:
|
||||
opencloud-net:
|
||||
@@ -83,4 +83,5 @@ services:
|
||||
entrypoint: ['/bin/bash', '-c']
|
||||
command: ['coolconfig generate-proof-key && /start-collabora-online.sh']
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-f", "http://localhost:9980/hosting/discovery" ]
|
||||
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/9980 && echo -e 'GET /hosting/discovery HTTP/1.1\r\nHost: localhost:9980\r\n\r\n' >&3 && head -n 1 <&3 | grep '200 OK'"]
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# we can't mount it directly because the run-document-server.sh script wants to move it
|
||||
cp /etc/onlyoffice/documentserver/local.dist.json /etc/onlyoffice/documentserver/local.json
|
||||
|
||||
/app/ds/run-document-server.sh
|
||||
@@ -1,71 +0,0 @@
|
||||
{
|
||||
"services": {
|
||||
"CoAuthoring": {
|
||||
"sql": {
|
||||
"type": "postgres",
|
||||
"dbHost": "localhost",
|
||||
"dbPort": "5432",
|
||||
"dbName": "onlyoffice",
|
||||
"dbUser": "onlyoffice",
|
||||
"dbPass": "onlyoffice"
|
||||
},
|
||||
"token": {
|
||||
"enable": {
|
||||
"request": {
|
||||
"inbox": true,
|
||||
"outbox": true
|
||||
},
|
||||
"browser": true
|
||||
},
|
||||
"inbox": {
|
||||
"header": "Authorization"
|
||||
},
|
||||
"outbox": {
|
||||
"header": "Authorization"
|
||||
}
|
||||
},
|
||||
"secret": {
|
||||
"inbox": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
},
|
||||
"outbox": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
},
|
||||
"session": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rabbitmq": {
|
||||
"url": "amqp://guest:guest@localhost"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
"inputLimits": [
|
||||
{
|
||||
"type": "docx;dotx;docm;dotm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "xlsx;xltx;xlsm;xltm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "pptx;ppsx;potx;pptm;ppsm;potm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ directives:
|
||||
- 'blob:'
|
||||
- 'https://embed.diagrams.net/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice.opencloud.test}/'
|
||||
- 'https://${COLLABORA_DOMAIN|collabora.opencloud.test}/'
|
||||
# This is needed for the external-sites web extension when embedding sites
|
||||
- 'https://docs.opencloud.eu'
|
||||
@@ -29,7 +28,6 @@ directives:
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/opencloud-eu/awesome-apps/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice.opencloud.test}/'
|
||||
- 'https://${COLLABORA_DOMAIN|collabora.opencloud.test}/'
|
||||
manifest-src:
|
||||
- '''self'''
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# This adds four additional routes to the proxy. Forwarding
|
||||
# request on '/carddav/', '/caldav/' and the respective '/.well-knwown'
|
||||
# endpoints to the radicale container and setting the required headers.
|
||||
additional_policies:
|
||||
- name: default
|
||||
routes:
|
||||
- endpoint: /caldav/
|
||||
backend: http://radicale:5232
|
||||
remote_user_header: X-Remote-User
|
||||
skip_x_access_token: true
|
||||
additional_headers:
|
||||
- X-Script-Name: /caldav
|
||||
- endpoint: /.well-known/caldav
|
||||
backend: http://radicale:5232
|
||||
remote_user_header: X-Remote-User
|
||||
skip_x_access_token: true
|
||||
additional_headers:
|
||||
- X-Script-Name: /caldav
|
||||
- endpoint: /carddav/
|
||||
backend: http://radicale:5232
|
||||
remote_user_header: X-Remote-User
|
||||
skip_x_access_token: true
|
||||
additional_headers:
|
||||
- X-Script-Name: /carddav
|
||||
- endpoint: /.well-known/carddav
|
||||
backend: http://radicale:5232
|
||||
remote_user_header: X-Remote-User
|
||||
skip_x_access_token: true
|
||||
additional_headers:
|
||||
- X-Script-Name: /carddav
|
||||
# To enable the radicale web UI add this rule.
|
||||
# "unprotected" is True because the Web UI itself ask for
|
||||
# the password.
|
||||
# Also set "type" to "internal" in the config/radicale/config
|
||||
# - endpoint: /caldav/.web/
|
||||
# backend: http://radicale:5232/
|
||||
# unprotected: true
|
||||
# skip_x_access_token: true
|
||||
# additional_headers:
|
||||
# - X-Script-Name: /caldav
|
||||
325
deployments/examples/opencloud_full/config/radicale/config
Normal file
325
deployments/examples/opencloud_full/config/radicale/config
Normal file
@@ -0,0 +1,325 @@
|
||||
# -*- mode: conf -*-
|
||||
# vim:ft=cfg
|
||||
|
||||
# Config file for Radicale - A simple calendar server
|
||||
#
|
||||
# Place it into /etc/radicale/config (global)
|
||||
# or ~/.config/radicale/config (user)
|
||||
#
|
||||
# The current values are the default ones
|
||||
|
||||
|
||||
[server]
|
||||
|
||||
# CalDAV server hostnames separated by a comma
|
||||
# IPv4 syntax: address:port
|
||||
# IPv6 syntax: [address]:port
|
||||
# Hostname syntax (using "getaddrinfo" to resolve to IPv4/IPv6 adress(es)): hostname:port
|
||||
# For example: 0.0.0.0:9999, [::]:9999, localhost:9999
|
||||
hosts = 0.0.0.0:5232
|
||||
|
||||
# Max parallel connections
|
||||
#max_connections = 8
|
||||
|
||||
# Max size of request body (bytes)
|
||||
#max_content_length = 100000000
|
||||
|
||||
# Socket timeout (seconds)
|
||||
#timeout = 30
|
||||
|
||||
# SSL flag, enable HTTPS protocol
|
||||
#ssl = False
|
||||
|
||||
# SSL certificate path
|
||||
#certificate = /etc/ssl/radicale.cert.pem
|
||||
|
||||
# SSL private key
|
||||
#key = /etc/ssl/radicale.key.pem
|
||||
|
||||
# CA certificate for validating clients. This can be used to secure
|
||||
# TCP traffic between Radicale and a reverse proxy
|
||||
#certificate_authority =
|
||||
|
||||
# SSL protocol, secure configuration: ALL -SSLv3 -TLSv1 -TLSv1.1
|
||||
#protocol = (default)
|
||||
|
||||
# SSL ciphersuite, secure configuration: DHE:ECDHE:-NULL:-SHA (see also "man openssl-ciphers")
|
||||
#ciphersuite = (default)
|
||||
|
||||
# script name to strip from URI if called by reverse proxy
|
||||
#script_name = (default taken from HTTP_X_SCRIPT_NAME or SCRIPT_NAME)
|
||||
|
||||
|
||||
[encoding]
|
||||
|
||||
# Encoding for responding requests
|
||||
#request = utf-8
|
||||
|
||||
# Encoding for storing local collections
|
||||
#stock = utf-8
|
||||
|
||||
|
||||
[auth]
|
||||
|
||||
# Authentication method
|
||||
# Value: none | htpasswd | remote_user | http_x_remote_user | dovecot | ldap | oauth2 | pam | denyall
|
||||
type = http_x_remote_user
|
||||
|
||||
# Cache logins for until expiration time
|
||||
#cache_logins = false
|
||||
|
||||
# Expiration time for caching successful logins in seconds
|
||||
#cache_successful_logins_expiry = 15
|
||||
|
||||
## Expiration time of caching failed logins in seconds
|
||||
#cache_failed_logins_expiry = 90
|
||||
|
||||
# Ignore modifyTimestamp and createTimestamp attributes. Required e.g. for Authentik LDAP server
|
||||
#ldap_ignore_attribute_create_modify_timestamp = false
|
||||
|
||||
# URI to the LDAP server
|
||||
#ldap_uri = ldap://localhost
|
||||
|
||||
# The base DN where the user accounts have to be searched
|
||||
#ldap_base = ##BASE_DN##
|
||||
|
||||
# The reader DN of the LDAP server
|
||||
#ldap_reader_dn = CN=ldapreader,CN=Users,##BASE_DN##
|
||||
|
||||
# Password of the reader DN
|
||||
#ldap_secret = ldapreader-secret
|
||||
|
||||
# Path of the file containing password of the reader DN
|
||||
#ldap_secret_file = /run/secrets/ldap_password
|
||||
|
||||
# the attribute to read the group memberships from in the user's LDAP entry (default: not set)
|
||||
#ldap_groups_attribute = memberOf
|
||||
|
||||
# The filter to find the DN of the user. This filter must contain a python-style placeholder for the login
|
||||
#ldap_filter = (&(objectClass=person)(uid={0}))
|
||||
|
||||
# the attribute holding the value to be used as username after authentication
|
||||
#ldap_user_attribute = cn
|
||||
|
||||
# Use ssl on the ldap connection
|
||||
# Soon to be deprecated, use ldap_security instead
|
||||
#ldap_use_ssl = False
|
||||
|
||||
# the encryption mode to be used: tls, starttls, default is none
|
||||
#ldap_security = none
|
||||
|
||||
# The certificate verification mode. Works for ssl and starttls. NONE, OPTIONAL, default is REQUIRED
|
||||
#ldap_ssl_verify_mode = REQUIRED
|
||||
|
||||
# The path to the CA file in pem format which is used to certificate the server certificate
|
||||
#ldap_ssl_ca_file =
|
||||
|
||||
# Connection type for dovecot authentication (AF_UNIX|AF_INET|AF_INET6)
|
||||
# Note: credentials are transmitted in cleartext
|
||||
#dovecot_connection_type = AF_UNIX
|
||||
|
||||
# The path to the Dovecot client authentication socket (eg. /run/dovecot/auth-client on Fedora). Radicale must have read / write access to the socket.
|
||||
#dovecot_socket = /var/run/dovecot/auth-client
|
||||
|
||||
# Host of via network exposed dovecot socket
|
||||
#dovecot_host = localhost
|
||||
|
||||
# Port of via network exposed dovecot socket
|
||||
#dovecot_port = 12345
|
||||
|
||||
# IMAP server hostname
|
||||
# Syntax: address | address:port | [address]:port | imap.server.tld
|
||||
#imap_host = localhost
|
||||
|
||||
# Secure the IMAP connection
|
||||
# Value: tls | starttls | none
|
||||
#imap_security = tls
|
||||
|
||||
# OAuth2 token endpoint URL
|
||||
#oauth2_token_endpoint = <URL>
|
||||
|
||||
# PAM service
|
||||
#pam_serivce = radicale
|
||||
|
||||
# PAM group user should be member of
|
||||
#pam_group_membership =
|
||||
|
||||
# Htpasswd filename
|
||||
#htpasswd_filename = /etc/radicale/users
|
||||
|
||||
# Htpasswd encryption method
|
||||
# Value: plain | bcrypt | md5 | sha256 | sha512 | autodetect
|
||||
# bcrypt requires the installation of 'bcrypt' module.
|
||||
#htpasswd_encryption = autodetect
|
||||
|
||||
# Enable caching of htpasswd file based on size and mtime_ns
|
||||
#htpasswd_cache = False
|
||||
|
||||
# Incorrect authentication delay (seconds)
|
||||
#delay = 1
|
||||
|
||||
# Message displayed in the client when a password is needed
|
||||
#realm = Radicale - Password Required
|
||||
|
||||
# Convert username to lowercase, must be true for case-insensitive auth providers
|
||||
#lc_username = False
|
||||
|
||||
# Strip domain name from username
|
||||
#strip_domain = False
|
||||
|
||||
|
||||
[rights]
|
||||
|
||||
# Rights backend
|
||||
# Value: authenticated | owner_only | owner_write | from_file
|
||||
#type = owner_only
|
||||
|
||||
# File for rights management from_file
|
||||
#file = /etc/radicale/rights
|
||||
|
||||
# Permit delete of a collection (global)
|
||||
#permit_delete_collection = True
|
||||
|
||||
# Permit overwrite of a collection (global)
|
||||
#permit_overwrite_collection = True
|
||||
|
||||
|
||||
[storage]
|
||||
|
||||
# Storage backend
|
||||
# Value: multifilesystem | multifilesystem_nolock
|
||||
#type = multifilesystem
|
||||
|
||||
# Folder for storing local collections, created if not present
|
||||
#filesystem_folder = /var/lib/radicale/collections
|
||||
|
||||
# Folder for storing cache of local collections, created if not present
|
||||
# Note: only used in case of use_cache_subfolder_* options are active
|
||||
# Note: can be used on multi-instance setup to cache files on local node (see below)
|
||||
#filesystem_cache_folder = (filesystem_folder)
|
||||
|
||||
# Use subfolder 'collection-cache' for 'item' cache file structure instead of inside collection folder
|
||||
# Note: can be used on multi-instance setup to cache 'item' on local node
|
||||
#use_cache_subfolder_for_item = False
|
||||
|
||||
# Use subfolder 'collection-cache' for 'history' cache file structure instead of inside collection folder
|
||||
# Note: use only on single-instance setup, will break consistency with client in multi-instance setup
|
||||
#use_cache_subfolder_for_history = False
|
||||
|
||||
# Use subfolder 'collection-cache' for 'sync-token' cache file structure instead of inside collection folder
|
||||
# Note: use only on single-instance setup, will break consistency with client in multi-instance setup
|
||||
#use_cache_subfolder_for_synctoken = False
|
||||
|
||||
# Use last modifiction time (nanoseconds) and size (bytes) for 'item' cache instead of SHA256 (improves speed)
|
||||
# Note: check used filesystem mtime precision before enabling
|
||||
# Note: conversion is done on access, bulk conversion can be done offline using storage verification option: radicale --verify-storage
|
||||
#use_mtime_and_size_for_item_cache = False
|
||||
|
||||
# Use configured umask for folder creation (not applicable for OS Windows)
|
||||
# Useful value: 0077 | 0027 | 0007 | 0022
|
||||
#folder_umask = (system default, usual 0022)
|
||||
|
||||
# Delete sync token that are older (seconds)
|
||||
#max_sync_token_age = 2592000
|
||||
|
||||
# Skip broken item instead of triggering an exception
|
||||
#skip_broken_item = True
|
||||
|
||||
# Command that is run after changes to storage, default is emtpy
|
||||
# Supported placeholders:
|
||||
# %(user)s: logged-in user
|
||||
# %(cwd)s : current working directory
|
||||
# %(path)s: full path of item
|
||||
# Command will be executed with base directory defined in filesystem_folder
|
||||
# For "git" check DOCUMENTATION.md for bootstrap instructions
|
||||
# Example(test): echo \"user=%(user)s path=%(path)s cwd=%(cwd)s\"
|
||||
# Example(git): git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
|
||||
#hook =
|
||||
|
||||
# Create predefined user collections
|
||||
#
|
||||
# json format:
|
||||
#
|
||||
# {
|
||||
# "def-addressbook": {
|
||||
# "D:displayname": "Personal Address Book",
|
||||
# "tag": "VADDRESSBOOK"
|
||||
# },
|
||||
# "def-calendar": {
|
||||
# "C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO",
|
||||
# "D:displayname": "Personal Calendar",
|
||||
# "tag": "VCALENDAR"
|
||||
# }
|
||||
# }
|
||||
#
|
||||
predefined_collections = {
|
||||
"def-addressbook": {
|
||||
"D:displayname": "Personal Address Book",
|
||||
"tag": "VADDRESSBOOK"
|
||||
},
|
||||
"def-calendar": {
|
||||
"C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO",
|
||||
"D:displayname": "Personal Calendar",
|
||||
"tag": "VCALENDAR"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[web]
|
||||
|
||||
# Web interface backend
|
||||
# Value: none | internal
|
||||
type = none
|
||||
|
||||
|
||||
[logging]
|
||||
|
||||
# Threshold for the logger
|
||||
# Value: debug | info | warning | error | critical
|
||||
#level = info
|
||||
|
||||
# Don't include passwords in logs
|
||||
#mask_passwords = True
|
||||
|
||||
# Log bad PUT request content
|
||||
#bad_put_request_content = False
|
||||
|
||||
# Log backtrace on level=debug
|
||||
#backtrace_on_debug = False
|
||||
|
||||
# Log request header on level=debug
|
||||
#request_header_on_debug = False
|
||||
|
||||
# Log request content on level=debug
|
||||
#request_content_on_debug = False
|
||||
|
||||
# Log response content on level=debug
|
||||
#response_content_on_debug = False
|
||||
|
||||
# Log rights rule which doesn't match on level=debug
|
||||
#rights_rule_doesnt_match_on_debug = False
|
||||
|
||||
# Log storage cache actions on level=debug
|
||||
#storage_cache_actions_on_debug = False
|
||||
|
||||
[headers]
|
||||
|
||||
# Additional HTTP headers
|
||||
#Access-Control-Allow-Origin = *
|
||||
|
||||
|
||||
[hook]
|
||||
|
||||
# Hook types
|
||||
# Value: none | rabbitmq
|
||||
#type = none
|
||||
#rabbitmq_endpoint =
|
||||
#rabbitmq_topic =
|
||||
#rabbitmq_queue_type = classic
|
||||
|
||||
|
||||
[reporting]
|
||||
|
||||
# When returning a free-busy report, limit the number of returned
|
||||
# occurences per event to prevent DOS attacks.
|
||||
#max_freebusy_occurrence = 10000
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
services:
|
||||
traefik:
|
||||
networks:
|
||||
opencloud-net:
|
||||
aliases:
|
||||
- ${ONLYOFFICE_DOMAIN:-onlyoffice.opencloud.test}
|
||||
- ${WOPISERVER_ONLYOFFICE_DOMAIN:-wopiserver-oo.opencloud.test}
|
||||
|
||||
collaboration-oo:
|
||||
image: ${OC_DOCKER_IMAGE:-opencloudeu/opencloud-rolling}:${OC_DOCKER_TAG:-latest}
|
||||
networks:
|
||||
opencloud-net:
|
||||
depends_on:
|
||||
opencloud:
|
||||
condition: service_started
|
||||
onlyoffice:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command: [ "-c", "opencloud collaboration server" ]
|
||||
environment:
|
||||
COLLABORATION_GRPC_ADDR: 0.0.0.0:9301
|
||||
COLLABORATION_HTTP_ADDR: 0.0.0.0:9300
|
||||
MICRO_REGISTRY: "nats-js-kv"
|
||||
MICRO_REGISTRY_ADDRESS: "opencloud:9233"
|
||||
COLLABORATION_WOPI_SRC: https://${WOPISERVER_ONLYOFFICE_DOMAIN:-wopiserver-oo.opencloud.test}
|
||||
COLLABORATION_APP_NAME: "OnlyOffice"
|
||||
COLLABORATION_APP_PRODUCT: "OnlyOffice"
|
||||
COLLABORATION_APP_ADDR: https://${ONLYOFFICE_DOMAIN:-onlyoffice.opencloud.test}
|
||||
COLLABORATION_APP_ICON: https://${ONLYOFFICE_DOMAIN:-onlyoffice.opencloud.test}/web-apps/apps/documenteditor/main/resources/img/favicon.ico
|
||||
COLLABORATION_APP_INSECURE: "${INSECURE:-true}"
|
||||
COLLABORATION_CS3API_DATAGATEWAY_INSECURE: "${INSECURE:-true}"
|
||||
COLLABORATION_LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
COLLABORATION_APP_PROOF_DISABLE: "true"
|
||||
OC_URL: https://${OC_DOMAIN:-cloud.opencloud.test}
|
||||
volumes:
|
||||
# configure the .env file to use own paths instead of docker internal volumes
|
||||
- ${OC_CONFIG_DIR:-opencloud-config}:/etc/opencloud
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.collaboration-oo.entrypoints=https"
|
||||
- "traefik.http.routers.collaboration-oo.rule=Host(`${WOPISERVER_ONLYOFFICE_DOMAIN:-wopiserver-oo.opencloud.test}`)"
|
||||
- "traefik.http.routers.collaboration-oo.tls.certresolver=http"
|
||||
- "traefik.http.routers.collaboration-oo.service=collaboration-oo"
|
||||
- "traefik.http.services.collaboration-oo.loadbalancer.server.port=9300"
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
onlyoffice:
|
||||
# if you want to use oo enterprise edition, use: onlyoffice/documentserver-ee:<version>
|
||||
# note, you also need to add a volume, see below
|
||||
image: onlyoffice/documentserver:8.2.2
|
||||
# changelog https://github.com/ONLYOFFICE/DocumentServer/releases
|
||||
networks:
|
||||
opencloud-net:
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- /entrypoint-override.sh
|
||||
environment:
|
||||
WOPI_ENABLED: "true"
|
||||
# self-signed certificates
|
||||
USE_UNAUTHORIZED_STORAGE: "${INSECURE:-false}"
|
||||
volumes:
|
||||
# paths are relative to the main compose file
|
||||
- ./config/onlyoffice/entrypoint-override.sh:/entrypoint-override.sh
|
||||
- ./config/onlyoffice/local.json:/etc/onlyoffice/documentserver/local.dist.json
|
||||
# if you want to use oo enterprise edition, you need to add a volume for the license file
|
||||
# for details see: Registering your Enterprise Edition version -->
|
||||
# https://helpcenter.onlyoffice.com/installation/docs-enterprise-install-docker.aspx
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.onlyoffice.entrypoints=https"
|
||||
- "traefik.http.routers.onlyoffice.rule=Host(`${ONLYOFFICE_DOMAIN:-onlyoffice.opencloud.test}`)"
|
||||
- "traefik.http.routers.onlyoffice.tls.certresolver=http"
|
||||
- "traefik.http.routers.onlyoffice.service=onlyoffice"
|
||||
- "traefik.http.services.onlyoffice.loadbalancer.server.port=80"
|
||||
# websockets can't be opened when this is omitted
|
||||
- "traefik.http.middlewares.onlyoffice.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
- "traefik.http.routers.onlyoffice.middlewares=onlyoffice"
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/hosting/discovery"]
|
||||
@@ -53,7 +53,6 @@ services:
|
||||
PROXY_CSP_CONFIG_FILE_LOCATION: /etc/opencloud/csp.yaml
|
||||
# these three vars are needed to the csp config file to include the web office apps and the importer
|
||||
COLLABORA_DOMAIN: ${COLLABORA_DOMAIN:-collabora.opencloud.test}
|
||||
ONLYOFFICE_DOMAIN: ${ONLYOFFICE_DOMAIN:-onlyoffice.opencloud.test}
|
||||
COMPANION_DOMAIN: ${COMPANION_DOMAIN:-companion.opencloud.test}
|
||||
# enable to allow using the banned passwords list
|
||||
OC_PASSWORD_POLICY_BANNED_PASSWORDS_LIST: banned-password-list.txt
|
||||
|
||||
18
deployments/examples/opencloud_full/radicale.yml
Normal file
18
deployments/examples/opencloud_full/radicale.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
services:
|
||||
opencloud:
|
||||
volumes:
|
||||
# external sites needs to have additional routes configured in the proxy
|
||||
- ./config/opencloud/proxy.yaml:/etc/opencloud/proxy.yaml
|
||||
radicale:
|
||||
image: ${RADICALE_DOCKER_IMAGE:-opencloudeu/radicale}:${RADICALE_DOCKER_TAG:-latest}
|
||||
networks:
|
||||
opencloud-net:
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
volumes:
|
||||
- ./config/radicale/config:/etc/radicale/config
|
||||
- ${RADICALE_DATA_DIR:-radicale-data}:/var/lib/radicale
|
||||
volumes:
|
||||
radicale-data:
|
||||
43
go.mod
43
go.mod
@@ -3,14 +3,14 @@ module github.com/opencloud-eu/opencloud
|
||||
go 1.24.1
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1
|
||||
github.com/CiscoM31/godata v1.0.10
|
||||
github.com/KimMachineGun/automemlimit v0.7.1
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/CiscoM31/godata v1.0.11
|
||||
github.com/KimMachineGun/automemlimit v0.7.2
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/MicahParks/keyfunc/v2 v2.1.0
|
||||
github.com/Nerzal/gocloak/v13 v13.9.0
|
||||
github.com/bbalet/stopwords v1.0.0
|
||||
github.com/beevik/etree v1.5.0
|
||||
github.com/beevik/etree v1.5.1
|
||||
github.com/blevesearch/bleve/v2 v2.5.0
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.14.1
|
||||
@@ -40,7 +40,7 @@ require (
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-tika v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/config/v2 v2.2.5
|
||||
github.com/gookit/config/v2 v2.2.6
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
|
||||
github.com/invopop/validation v0.8.0
|
||||
@@ -51,18 +51,18 @@ require (
|
||||
github.com/kovidgoyal/imaging v1.6.4
|
||||
github.com/leonelquinteros/gotext v1.7.1
|
||||
github.com/libregraph/idm v0.5.0
|
||||
github.com/libregraph/lico v0.65.2-0.20250428103211-356e98f98457
|
||||
github.com/libregraph/lico v0.66.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/mna/pigeon v1.3.0
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/nats-io/nats-server/v2 v2.11.1
|
||||
github.com/nats-io/nats.go v1.41.2
|
||||
github.com/nats-io/nats-server/v2 v2.11.3
|
||||
github.com/nats-io/nats.go v1.42.0
|
||||
github.com/oklog/run v1.1.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.23.4
|
||||
github.com/onsi/gomega v1.37.0
|
||||
github.com/open-policy-agent/opa v1.3.0
|
||||
github.com/open-policy-agent/opa v1.4.2
|
||||
github.com/opencloud-eu/reva/v2 v2.32.0
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/owncloud/libre-graph-api-go v1.0.5-0.20240829135935-80dc00d6f5ea
|
||||
@@ -96,14 +96,14 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0
|
||||
go.opentelemetry.io/otel/sdk v1.35.0
|
||||
go.opentelemetry.io/otel/trace v1.35.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
|
||||
golang.org/x/image v0.26.0
|
||||
golang.org/x/image v0.27.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/term v0.31.0
|
||||
golang.org/x/text v0.24.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.14.0
|
||||
golang.org/x/term v0.32.0
|
||||
golang.org/x/text v0.25.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
@@ -167,6 +167,7 @@ require (
|
||||
github.com/deckarep/golang-set v1.8.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
@@ -206,7 +207,7 @@ require (
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.11.2 // indirect
|
||||
github.com/goccy/go-yaml v1.12.0 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
@@ -219,7 +220,7 @@ require (
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/renameio/v2 v2.0.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gookit/goutil v0.6.15 // indirect
|
||||
github.com/gookit/goutil v0.6.18 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/schema v1.4.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
@@ -261,7 +262,7 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.3 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.4 // indirect
|
||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
@@ -322,7 +323,7 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.23.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
@@ -341,10 +342,10 @@ replace github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-2
|
||||
|
||||
replace github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
|
||||
|
||||
replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90
|
||||
|
||||
replace go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3
|
||||
|
||||
// exclude the v2 line of go-sqlite3 which was released accidentally and prevents pulling in newer versions of go-sqlite3
|
||||
// see https://github.com/mattn/go-sqlite3/issues/965 for more details
|
||||
exclude github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
|
||||
replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a
|
||||
|
||||
92
go.sum
92
go.sum
@@ -36,8 +36,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
@@ -64,12 +64,12 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CiscoM31/godata v1.0.10 h1:DZdJ6M8QNh4HquvDDOqNLu6h77Wl86KGK7Qlbmb90sk=
|
||||
github.com/CiscoM31/godata v1.0.10/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
|
||||
github.com/CiscoM31/godata v1.0.11 h1:w7y8twuW02LdH6mak3/GJ5i0GrCv2IoZUJVqa/g5Yeo=
|
||||
github.com/CiscoM31/godata v1.0.11/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
|
||||
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c h1:ocsNvQ2tNHme4v/lTs17HROamc7mFzZfzWcg4m+UXN0=
|
||||
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
github.com/KimMachineGun/automemlimit v0.7.1 h1:QcG/0iCOLChjfUweIMC3YL5Xy9C3VBeNmCZHrZfJMBw=
|
||||
github.com/KimMachineGun/automemlimit v0.7.1/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||
github.com/KimMachineGun/automemlimit v0.7.2 h1:DyfHI7zLWmZPn2Wqdy2AgTiUvrGPmnYWgwhHXtAegX4=
|
||||
github.com/KimMachineGun/automemlimit v0.7.2/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
@@ -130,8 +130,8 @@ github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk
|
||||
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/bbalet/stopwords v1.0.0 h1:0TnGycCtY0zZi4ltKoOGRFIlZHv0WqpoIGUsObjztfo=
|
||||
github.com/bbalet/stopwords v1.0.0/go.mod h1:sAWrQoDMfqARGIn4s6dp7OW7ISrshUD8IP2q3KoqPjc=
|
||||
github.com/beevik/etree v1.5.0 h1:iaQZFSDS+3kYZiGoc9uKeOkUY3nYMXOKLl6KIJxiJWs=
|
||||
github.com/beevik/etree v1.5.0/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs=
|
||||
github.com/beevik/etree v1.5.1 h1:TC3zyxYp+81wAmbsi8SWUpZCurbxa6S8RITYRSkNRwo=
|
||||
github.com/beevik/etree v1.5.1/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -257,15 +257,15 @@ github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS3
|
||||
github.com/deepmap/oapi-codegen v1.3.11/go.mod h1:suMvK7+rKlx3+tpa8ByptmvoXbAV70wERKTOGH3hLp0=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
|
||||
github.com/dgraph-io/badger/v4 v4.6.0 h1:acOwfOOZ4p1dPRnYzvkVm7rUk2Y21TgPVepCy5dJdFQ=
|
||||
github.com/dgraph-io/badger/v4 v4.6.0/go.mod h1:KSJ5VTuZNC3Sd+YhvVjk2nYua9UZnnTr/SkXvdtiPgI=
|
||||
github.com/dgraph-io/badger/v4 v4.7.0 h1:Q+J8HApYAY7UMpL8d9owqiB+odzEc0zn/aqOD9jhc6Y=
|
||||
github.com/dgraph-io/badger/v4 v4.7.0/go.mod h1:He7TzG3YBy3j4f5baj5B7Zl2XyfNe5bl4Udl0aPemVA=
|
||||
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
|
||||
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I=
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4=
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
|
||||
github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38=
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
@@ -438,8 +438,8 @@ github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ=
|
||||
github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
|
||||
github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM=
|
||||
github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
@@ -552,10 +552,10 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gookit/config/v2 v2.2.5 h1:RECbYYbtherywmzn3LNeu9NA5ZqhD7MSKEMsJ7l+MpU=
|
||||
github.com/gookit/config/v2 v2.2.5/go.mod h1:NeX+yiNYn6Ei10eJvCQFXuHEPIE/IPS8bqaFIsszzaM=
|
||||
github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo=
|
||||
github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY=
|
||||
github.com/gookit/config/v2 v2.2.6 h1:8ZbkSr3gnFg1En8za9X3vldnZca3y3C7kaBLGsdLghE=
|
||||
github.com/gookit/config/v2 v2.2.6/go.mod h1:++APDf3Ebj6mjzW1ALkegvg1evQKyx4FpuQqQZ2s2WM=
|
||||
github.com/gookit/goutil v0.6.18 h1:MUVj0G16flubWT8zYVicIuisUiHdgirPAkmnfD2kKgw=
|
||||
github.com/gookit/goutil v0.6.18/go.mod h1:AY/5sAwKe7Xck+mEbuxj0n/bc3qwrGNe3Oeulln7zBA=
|
||||
github.com/gookit/ini/v2 v2.2.3 h1:nSbN+x9OfQPcMObTFP+XuHt8ev6ndv/fWWqxFhPMu2E=
|
||||
github.com/gookit/ini/v2 v2.2.3/go.mod h1:Vu6p7P7xcfmb8KYu3L0ek8bqu/Im63N81q208SCCZY4=
|
||||
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||
@@ -690,8 +690,6 @@ github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 h1:A1xJ2NKgiYFiaHiLl9B5yw/gUBACSs9crDykTS3GuQI=
|
||||
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||
github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90 h1:pfI8Z5yavO6fU6vDGlWhZ4BgDlvj8c6xB7J57HfTPwA=
|
||||
github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
|
||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -720,8 +718,8 @@ github.com/leonelquinteros/gotext v1.7.1 h1:/JNPeE3lY5JeVYv2+KBpz39994W3W9fmZCGq
|
||||
github.com/leonelquinteros/gotext v1.7.1/go.mod h1:I0WoFDn9u2D3VbPnnDPT8mzZu0iSXG8iih+AH2fHHqg=
|
||||
github.com/libregraph/idm v0.5.0 h1:tDMwKbAOZzdeDYMxVlY5PbSqRKO7dbAW9KT42A51WSk=
|
||||
github.com/libregraph/idm v0.5.0/go.mod h1:BGMwIQ/6orJSPVzJ1x6kgG2JyG9GY05YFmbsnaD80k0=
|
||||
github.com/libregraph/lico v0.65.2-0.20250428103211-356e98f98457 h1:cwmUM+mSeqWYtZKAHn8QN7ns1nNf3Pc8nUfShka9+x0=
|
||||
github.com/libregraph/lico v0.65.2-0.20250428103211-356e98f98457/go.mod h1:2s2UkO0pY7/k1UlenXwio1qenfHZ217Npx22YyZJfSA=
|
||||
github.com/libregraph/lico v0.66.0 h1:7T6fD1YF0Ep9n0g4KN6dvWHTlDC3awrQpgsP5GdYCF4=
|
||||
github.com/libregraph/lico v0.66.0/go.mod h1:QI7NfmAkAWQ2y97iVfLv10S8tcvPQjc630uyfHGjIOw=
|
||||
github.com/libregraph/oidc-go v1.1.0 h1:RyudjL3UyQblqeBQI06W53PniWobqODeeyAy6v/HumA=
|
||||
github.com/libregraph/oidc-go v1.1.0/go.mod h1:qW9ubcXvZrfbbWZBaLMuk7bt5qAUMYyt9/NtXQt07Cw=
|
||||
github.com/linode/linodego v0.25.3/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE=
|
||||
@@ -820,12 +818,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||
github.com/nats-io/jwt/v2 v2.7.3 h1:6bNPK+FXgBeAqdj4cYQ0F8ViHRbi7woQLq4W29nUAzE=
|
||||
github.com/nats-io/jwt/v2 v2.7.3/go.mod h1:GvkcbHhKquj3pkioy5put1wvPxs78UlZ7D/pY+BgZk4=
|
||||
github.com/nats-io/nats-server/v2 v2.11.1 h1:LwdauqMqMNhTxTN3+WFTX6wGDOKntHljgZ+7gL5HCnk=
|
||||
github.com/nats-io/nats-server/v2 v2.11.1/go.mod h1:leXySghbdtXSUmWem8K9McnJ6xbJOb0t9+NQ5HTRZjI=
|
||||
github.com/nats-io/nats.go v1.41.2 h1:5UkfLAtu/036s99AhFRlyNDI1Ieylb36qbGjJzHixos=
|
||||
github.com/nats-io/nats.go v1.41.2/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
|
||||
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
|
||||
github.com/nats-io/nats-server/v2 v2.11.3 h1:AbGtXxuwjo0gBroLGGr/dE0vf24kTKdRnBq/3z/Fdoc=
|
||||
github.com/nats-io/nats-server/v2 v2.11.3/go.mod h1:6Z6Fd+JgckqzKig7DYwhgrE7bJ6fypPHnGPND+DqgMY=
|
||||
github.com/nats-io/nats.go v1.42.0 h1:ynIMupIOvf/ZWH/b2qda6WGKGNSjwOUutTpWRvAmhaM=
|
||||
github.com/nats-io/nats.go v1.42.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
@@ -858,8 +856,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
||||
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||
github.com/open-policy-agent/opa v1.3.0 h1:zVvQvQg+9+FuSRBt4LgKNzJwsWl/c85kD5jPozJTydY=
|
||||
github.com/open-policy-agent/opa v1.3.0/go.mod h1:t9iPNhaplD2qpiBqeudzJtEX3fKHK8zdA29oFvofAHo=
|
||||
github.com/open-policy-agent/opa v1.4.2 h1:ag4upP7zMsa4WE2p1pwAFeG4Pn3mNwfAx9DLhhJfbjU=
|
||||
github.com/open-policy-agent/opa v1.4.2/go.mod h1:DNzZPKqKh4U0n0ANxcCVlw8lCSv2c+h5G/3QvSYdWZ8=
|
||||
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a h1:Sakl76blJAaM6NxylVkgSzktjo2dS504iDotEFJsh3M=
|
||||
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
|
||||
github.com/opencloud-eu/reva/v2 v2.32.0 h1:JRWPleHiEl0film95Gkh1iBEhc6eikEsx5FKLfVx6l8=
|
||||
github.com/opencloud-eu/reva/v2 v2.32.0/go.mod h1:FDhGVC+ZsRRWdC3am4EbuILBtviTbCDVrTUjFECOqvg=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
@@ -1223,8 +1223,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1240,8 +1240,8 @@ golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScy
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
|
||||
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -1331,8 +1331,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1350,8 +1350,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1432,8 +1432,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -1445,8 +1445,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1462,8 +1462,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -42,7 +42,7 @@ func ExtractAccountUUID(opts ...account.Option) func(http.Handler) http.Handler
|
||||
}
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.Header.Get("x-access-token")
|
||||
token := r.Header.Get(revactx.TokenHeader)
|
||||
if len(token) == 0 {
|
||||
roleIDsJSON, _ := json.Marshal([]string{})
|
||||
ctx := metadata.Set(r.Context(), RoleIDs, string(roleIDsJSON))
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *ActivitylogService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// HandleGetItemActivities handles the request to get the activities of an item.
|
||||
func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, r.Header.Get("X-Access-Token"))
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, r.Header.Get(revactx.TokenHeader))
|
||||
|
||||
activeUser, ok := revactx.ContextGetUser(ctx)
|
||||
if !ok {
|
||||
|
||||
@@ -278,7 +278,7 @@ func (a *AuthAppService) authenticateUser(userID, userName string, gwc gateway.G
|
||||
|
||||
func getContext(r *http.Request) context.Context {
|
||||
ctx := r.Context()
|
||||
return metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, r.Header.Get("X-Access-Token"))
|
||||
return metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, r.Header.Get(ctxpkg.TokenHeader))
|
||||
}
|
||||
|
||||
func buildClientID(userID, userName string) string {
|
||||
|
||||
@@ -108,7 +108,7 @@ func DefaultConfig() *config.Config {
|
||||
OCS: config.OCS{
|
||||
Prefix: "ocs",
|
||||
SharePrefix: "/Shares",
|
||||
HomeNamespace: "/users/{{.Id.OpaqueId}}",
|
||||
HomeNamespace: "/users/`{{.Id.OpaqueId}}`",
|
||||
AdditionalInfoAttribute: "{{.Mail}}",
|
||||
StatCacheType: "memory",
|
||||
StatCacheNodes: []string{"127.0.0.1:9233"},
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
opkgm "github.com/opencloud-eu/opencloud/pkg/middleware"
|
||||
"github.com/opencloud-eu/opencloud/services/graph/pkg/errorcode"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/auth/scope"
|
||||
ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/token/manager/jwt"
|
||||
)
|
||||
@@ -43,7 +42,7 @@ func Auth(opts ...account.Option) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
t := r.Header.Get("x-access-token")
|
||||
t := r.Header.Get(revactx.TokenHeader)
|
||||
if t == "" {
|
||||
errorcode.InvalidAuthenticationToken.Render(w, r, http.StatusUnauthorized, "Access token is empty.")
|
||||
/* msgraph error for GET https://graph.microsoft.com/v1.0/me
|
||||
@@ -84,10 +83,10 @@ func Auth(opts ...account.Option) func(http.Handler) http.Handler {
|
||||
}
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, t)
|
||||
|
||||
initiatorID := r.Header.Get(ctxpkg.InitiatorHeader)
|
||||
initiatorID := r.Header.Get(revactx.InitiatorHeader)
|
||||
if initiatorID != "" {
|
||||
ctx = ctxpkg.ContextSetInitiator(ctx, initiatorID)
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.InitiatorHeader, initiatorID)
|
||||
ctx = revactx.ContextSetInitiator(ctx, initiatorID)
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, revactx.InitiatorHeader, initiatorID)
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
|
||||
@@ -496,7 +496,8 @@ var _ = Describe("Users", func() {
|
||||
},
|
||||
Entry("with invalid filter", "invalid", http.StatusBadRequest),
|
||||
Entry("with unsupported filter for user property", "mail eq 'unsupported'", http.StatusNotImplemented),
|
||||
Entry("with unsupported filter operation", "mail add 10", http.StatusNotImplemented),
|
||||
// This error is caugh by godata's parser already
|
||||
Entry("with unsupported filter operation", "mail add 10", http.StatusBadRequest),
|
||||
Entry("with unsupported logical operation", "memberOf/any(n:n/id eq 1) or memberOf/any(n:n/id eq 2)", http.StatusNotImplemented),
|
||||
Entry("with unsupported lambda query ", `drives/any(n:n/id eq '1')`, http.StatusNotImplemented),
|
||||
Entry("with unsupported lambda token ", "memberOf/all(n:n/id eq 1)", http.StatusNotImplemented),
|
||||
|
||||
@@ -226,7 +226,28 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(10),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSecureViewer creates a secure viewer role
|
||||
roleSecureViewer = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSecureViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSecureViewerID),
|
||||
Description: proto.String(_secureViewerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(20),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -255,7 +276,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(30),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -272,7 +293,24 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(40),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleEditorLite creates an editor-lite role
|
||||
roleEditorLite = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorLiteRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorLiteID),
|
||||
Description: proto.String(_editorLiteUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(50),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -293,7 +331,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(60),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -314,24 +352,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSpaceEditor creates an editor role
|
||||
roleSpaceEditor = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceEditorID),
|
||||
Description: proto.String(_spaceEditorUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(70),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -348,7 +369,24 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(80),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSpaceEditor creates an editor role
|
||||
roleSpaceEditor = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceEditorID),
|
||||
Description: proto.String(_spaceEditorUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(90),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -369,7 +407,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(100),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -390,24 +428,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleEditorLite creates an editor-lite role
|
||||
roleEditorLite = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorLiteRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorLiteID),
|
||||
Description: proto.String(_editorLiteUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(110),
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -424,30 +445,10 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(120),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSecureViewer creates a secure viewer role
|
||||
roleSecureViewer = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSecureViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSecureViewerID),
|
||||
Description: proto.String(_secureViewerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
// roleDenied creates a secure viewer role
|
||||
roleDenied = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewDeniedRole()
|
||||
@@ -461,7 +462,7 @@ var (
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
LibreGraphWeight: proto.Int32(200),
|
||||
}
|
||||
}()
|
||||
)
|
||||
@@ -531,39 +532,17 @@ func GetLegacyRoleName(role libregraph.UnifiedRoleDefinition) string {
|
||||
return legacyNames[role.GetId()]
|
||||
}
|
||||
|
||||
// weightRoles sorts the provided role definitions by the number of permissions[n].actions they grant,
|
||||
// the implementation is optimistic and assumes that the weight relies on the number of available actions.
|
||||
// weightRoles sorts the provided role definitions by the number of LibreGraphWeight,
|
||||
// descending - false - sorts the roles from least to most permissions
|
||||
// descending - true - sorts the roles from most to least permissions
|
||||
func weightRoles(roleSet []*libregraph.UnifiedRoleDefinition, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
slices.SortFunc(roleSet, func(i, j *libregraph.UnifiedRoleDefinition) int {
|
||||
var ia []string
|
||||
for _, rp := range i.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ia = append(ia, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
var ja []string
|
||||
for _, rp := range j.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ja = append(ja, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
switch descending {
|
||||
case true:
|
||||
return cmp.Compare(len(ja), len(ia))
|
||||
default:
|
||||
return cmp.Compare(len(ia), len(ja))
|
||||
slices.SortFunc(roleSet, func(a, b *libregraph.UnifiedRoleDefinition) int {
|
||||
if descending {
|
||||
return cmp.Compare(b.GetLibreGraphWeight(), a.GetLibreGraphWeight())
|
||||
}
|
||||
return cmp.Compare(a.GetLibreGraphWeight(), b.GetLibreGraphWeight())
|
||||
})
|
||||
|
||||
for i, role := range roleSet {
|
||||
role.LibreGraphWeight = libregraph.PtrInt32(int32(i) + 1)
|
||||
}
|
||||
|
||||
// return for the sake of consistency, optional because the slice is modified in place
|
||||
return roleSet
|
||||
}
|
||||
|
||||
|
||||
@@ -100,16 +100,16 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
givenActions: getRoleActions(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
},
|
||||
},
|
||||
"RoleViewer | file": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
},
|
||||
},
|
||||
"RoleViewer | file | federated": {
|
||||
@@ -124,8 +124,8 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
givenActions: getRoleActions(unifiedrole.RoleFileEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
@@ -133,8 +133,8 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
givenActions: getRoleActions(unifiedrole.RoleEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
},
|
||||
@@ -161,8 +161,8 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
givenActions: getRoleActions(unifiedrole.BuildInRoles...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewerListGrants,
|
||||
unifiedrole.RoleFileEditor,
|
||||
unifiedrole.RoleFileEditorListGrants,
|
||||
@@ -172,13 +172,13 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
givenActions: getRoleActions(unifiedrole.BuildInRoles...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleDenied,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewerListGrants,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
unifiedrole.RoleEditorListGrants,
|
||||
unifiedrole.RoleDenied,
|
||||
},
|
||||
},
|
||||
"BuildInRoles | drive": {
|
||||
@@ -215,7 +215,7 @@ func TestGetRolesByPermissions(t *testing.T) {
|
||||
|
||||
for i, generatedDefinition := range generatedDefinitions {
|
||||
g.Expect(generatedDefinition.Id).To(Equal(tc.unifiedRoleDefinition[i].Id))
|
||||
g.Expect(*generatedDefinition.LibreGraphWeight).To(Equal(int32(i + 1)))
|
||||
g.Expect(generatedDefinition.LibreGraphWeight).To(Equal(tc.unifiedRoleDefinition[i].LibreGraphWeight))
|
||||
}
|
||||
|
||||
generatedActions := getRoleActions(generatedDefinitions...)
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
"@types/redux-logger": "^3.0.13",
|
||||
"axios": "^1.7.7",
|
||||
"classnames": "^2.5.1",
|
||||
"i18next": "^23.16.8",
|
||||
"i18next": "^25.1.2",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"i18next-http-backend": "^2.5.2",
|
||||
"i18next-http-backend": "^3.0.2",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"kpop": "https://download.kopano.io/community/kapp:/kpop-2.7.2.tgz",
|
||||
"query-string": "^9.1.1",
|
||||
@@ -117,13 +117,13 @@
|
||||
"css-loader": "7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||
"dotenv": "16.4.7",
|
||||
"dotenv-expand": "10.0.0",
|
||||
"dotenv-expand": "12.0.2",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-react-app": "^6.0.0",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-flowtype": "^5.10.0",
|
||||
"eslint-plugin-i18next": "^6.1.1",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jest": "^24.7.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
|
||||
@@ -58,7 +58,7 @@ func DefaultConfig() *config.Config {
|
||||
IdentifierScopesConf: "",
|
||||
IdentifierDefaultBannerLogo: "",
|
||||
IdentifierDefaultSignInPageText: "",
|
||||
IdentifierDefaultLogoTargetURI: "",
|
||||
IdentifierDefaultLogoTargetURI: "https://opencloud.eu",
|
||||
IdentifierDefaultUsernameHintText: "",
|
||||
SigningKid: "private-key",
|
||||
SigningMethod: "PS256",
|
||||
|
||||
274
services/idp/pnpm-lock.yaml
generated
274
services/idp/pnpm-lock.yaml
generated
@@ -54,14 +54,14 @@ importers:
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
i18next:
|
||||
specifier: ^23.16.8
|
||||
version: 23.16.8
|
||||
specifier: ^25.1.2
|
||||
version: 25.1.2(typescript@5.8.3)
|
||||
i18next-browser-languagedetector:
|
||||
specifier: ^7.2.1
|
||||
version: 7.2.1
|
||||
i18next-http-backend:
|
||||
specifier: ^2.5.2
|
||||
version: 2.5.2(encoding@0.1.13)
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2(encoding@0.1.13)
|
||||
i18next-resources-to-backend:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
@@ -82,7 +82,7 @@ importers:
|
||||
version: 17.0.2(react@17.0.2)
|
||||
react-i18next:
|
||||
specifier: ^15.5.1
|
||||
version: 15.5.1(i18next@23.16.8)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.8.3)
|
||||
version: 15.5.1(i18next@25.1.2(typescript@5.8.3))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.8.3)
|
||||
react-redux:
|
||||
specifier: ^8.1.3
|
||||
version: 8.1.3(@types/react-dom@17.0.25)(@types/react@17.0.80)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(redux@4.2.1)
|
||||
@@ -145,14 +145,14 @@ importers:
|
||||
specifier: 16.4.7
|
||||
version: 16.4.7
|
||||
dotenv-expand:
|
||||
specifier: 10.0.0
|
||||
version: 10.0.0
|
||||
specifier: 12.0.2
|
||||
version: 12.0.2
|
||||
eslint:
|
||||
specifier: ^7.32.0
|
||||
version: 7.32.0
|
||||
eslint-config-react-app:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(babel-eslint@10.1.0(eslint@7.32.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.30.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0))(eslint-plugin-jest@24.7.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.2(eslint@7.32.0))(eslint-plugin-react@7.37.2(eslint@7.32.0))(eslint-plugin-testing-library@3.10.2(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3)
|
||||
version: 6.0.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(babel-eslint@10.1.0(eslint@7.32.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0))(eslint-plugin-jest@24.7.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.2(eslint@7.32.0))(eslint-plugin-react@7.37.2(eslint@7.32.0))(eslint-plugin-testing-library@3.10.2(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3)
|
||||
eslint-loader:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(eslint@7.32.0)(webpack@5.99.6)
|
||||
@@ -163,8 +163,8 @@ importers:
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.1
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.30.0
|
||||
version: 2.30.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)
|
||||
specifier: ^2.31.0
|
||||
version: 2.31.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)
|
||||
eslint-plugin-jest:
|
||||
specifier: ^24.7.0
|
||||
version: 24.7.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3)
|
||||
@@ -279,6 +279,10 @@ packages:
|
||||
resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/compat-data@7.26.8':
|
||||
resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -386,6 +390,10 @@ packages:
|
||||
resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-validator-identifier@7.27.1':
|
||||
resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-validator-option@7.25.9':
|
||||
resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -984,10 +992,6 @@ packages:
|
||||
resolution: {integrity: sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.26.7':
|
||||
resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.26.9':
|
||||
resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -996,6 +1000,10 @@ packages:
|
||||
resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.27.1':
|
||||
resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/template@7.26.9':
|
||||
resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -2094,12 +2102,8 @@ packages:
|
||||
resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
array.prototype.findlastindex@1.2.5:
|
||||
resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
array.prototype.flat@1.3.2:
|
||||
resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
|
||||
array.prototype.findlastindex@1.2.6:
|
||||
resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
array.prototype.flat@1.3.3:
|
||||
@@ -2526,8 +2530,8 @@ packages:
|
||||
core-js@3.40.0:
|
||||
resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==}
|
||||
|
||||
core-js@3.41.0:
|
||||
resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==}
|
||||
core-js@3.42.0:
|
||||
resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==}
|
||||
|
||||
core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
@@ -2854,8 +2858,8 @@ packages:
|
||||
dot-case@3.0.4:
|
||||
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
|
||||
|
||||
dotenv-expand@10.0.0:
|
||||
resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==}
|
||||
dotenv-expand@12.0.2:
|
||||
resolution: {integrity: sha512-lXpXz2ZE1cea1gL4sz2Ipj8y4PiVjytYr3Ij0SWoms1PGxIv7m2CRKuRuCRtHdVuvM/hNJPMxt5PbhboNC4dPQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
dotenv@16.4.7:
|
||||
@@ -3053,8 +3057,8 @@ packages:
|
||||
eslint: ^6.0.0 || ^7.0.0
|
||||
webpack: ^4.0.0 || ^5.0.0
|
||||
|
||||
eslint-module-utils@2.11.0:
|
||||
resolution: {integrity: sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==}
|
||||
eslint-module-utils@2.12.0:
|
||||
resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
@@ -3084,12 +3088,12 @@ packages:
|
||||
resolution: {integrity: sha512-/Vy6BfX44njxpRnbJm7bbph0KaNJF2eillqN5W+u03hHuxmh9BjtjdPSrI9HPtyoEbG4j5nBn9gXm/dg99mz3Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
eslint-plugin-import@2.30.0:
|
||||
resolution: {integrity: sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==}
|
||||
eslint-plugin-import@2.31.0:
|
||||
resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
@@ -3605,8 +3609,8 @@ packages:
|
||||
engines: {node: '>= 16.0'}
|
||||
hasBin: true
|
||||
|
||||
i18next-http-backend@2.5.2:
|
||||
resolution: {integrity: sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==}
|
||||
i18next-http-backend@3.0.2:
|
||||
resolution: {integrity: sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==}
|
||||
|
||||
i18next-parser@9.0.2:
|
||||
resolution: {integrity: sha512-Q1yTZljBp1DcVAQD7LxduEqFRpjIeZc+5VnQ+gU8qG9WvY3U5rqK0IVONRWNtngh3orb197bfy1Sz4wlwcplxg==}
|
||||
@@ -3619,6 +3623,14 @@ packages:
|
||||
i18next@23.16.8:
|
||||
resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==}
|
||||
|
||||
i18next@25.1.2:
|
||||
resolution: {integrity: sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==}
|
||||
peerDependencies:
|
||||
typescript: ^5
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3744,8 +3756,8 @@ packages:
|
||||
resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-core-module@2.15.1:
|
||||
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
|
||||
is-core-module@2.16.1:
|
||||
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-data-view@1.0.1:
|
||||
@@ -5762,9 +5774,6 @@ packages:
|
||||
resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
string.prototype.trimend@1.0.8:
|
||||
resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==}
|
||||
|
||||
string.prototype.trimend@1.0.9:
|
||||
resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -6406,6 +6415,12 @@ snapshots:
|
||||
js-tokens: 4.0.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
js-tokens: 4.0.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
'@babel/compat-data@7.26.8': {}
|
||||
|
||||
'@babel/core@7.26.10':
|
||||
@@ -6558,6 +6573,8 @@ snapshots:
|
||||
|
||||
'@babel/helper-validator-identifier@7.25.9': {}
|
||||
|
||||
'@babel/helper-validator-identifier@7.27.1': {}
|
||||
|
||||
'@babel/helper-validator-option@7.25.9': {}
|
||||
|
||||
'@babel/helper-wrap-function@7.25.9':
|
||||
@@ -7280,10 +7297,6 @@ snapshots:
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@babel/runtime@7.26.7':
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@babel/runtime@7.26.9':
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
@@ -7292,6 +7305,8 @@ snapshots:
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@babel/runtime@7.27.1': {}
|
||||
|
||||
'@babel/template@7.26.9':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
@@ -7669,7 +7684,7 @@ snapshots:
|
||||
'@eslint/eslintrc@0.4.3':
|
||||
dependencies:
|
||||
ajv: 6.12.6
|
||||
debug: 4.4.0
|
||||
debug: 4.3.5
|
||||
espree: 7.3.1
|
||||
globals: 13.24.0
|
||||
ignore: 4.0.6
|
||||
@@ -7691,7 +7706,7 @@ snapshots:
|
||||
'@humanwhocodes/config-array@0.5.0':
|
||||
dependencies:
|
||||
'@humanwhocodes/object-schema': 1.2.1
|
||||
debug: 4.4.0
|
||||
debug: 4.3.5
|
||||
minimatch: 3.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -8073,8 +8088,8 @@ snapshots:
|
||||
|
||||
'@testing-library/dom@10.3.2':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/runtime': 7.27.1
|
||||
'@types/aria-query': 5.0.4
|
||||
aria-query: 5.3.0
|
||||
chalk: 4.1.2
|
||||
@@ -8329,7 +8344,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 4.33.0
|
||||
'@typescript-eslint/visitor-keys': 4.33.0
|
||||
debug: 4.4.0
|
||||
debug: 4.3.5
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
semver: 7.7.1
|
||||
@@ -8513,7 +8528,7 @@ snapshots:
|
||||
|
||||
aria-query@4.2.2:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
'@babel/runtime-corejs3': 7.24.8
|
||||
|
||||
aria-query@5.3.0:
|
||||
@@ -8525,7 +8540,7 @@ snapshots:
|
||||
array-buffer-byte-length@1.0.1:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
is-array-buffer: 3.0.4
|
||||
is-array-buffer: 3.0.5
|
||||
|
||||
array-buffer-byte-length@1.0.2:
|
||||
dependencies:
|
||||
@@ -8554,21 +8569,15 @@ snapshots:
|
||||
es-object-atoms: 1.0.0
|
||||
es-shim-unscopables: 1.0.2
|
||||
|
||||
array.prototype.findlastindex@1.2.5:
|
||||
array.prototype.findlastindex@1.2.6:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
call-bind: 1.0.8
|
||||
call-bound: 1.0.4
|
||||
define-properties: 1.2.1
|
||||
es-abstract: 1.23.3
|
||||
es-abstract: 1.23.9
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.0.0
|
||||
es-shim-unscopables: 1.0.2
|
||||
|
||||
array.prototype.flat@1.3.2:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
define-properties: 1.2.1
|
||||
es-abstract: 1.23.3
|
||||
es-shim-unscopables: 1.0.2
|
||||
es-object-atoms: 1.1.1
|
||||
es-shim-unscopables: 1.1.0
|
||||
|
||||
array.prototype.flat@1.3.3:
|
||||
dependencies:
|
||||
@@ -8601,14 +8610,14 @@ snapshots:
|
||||
|
||||
arraybuffer.prototype.slice@1.0.3:
|
||||
dependencies:
|
||||
array-buffer-byte-length: 1.0.1
|
||||
array-buffer-byte-length: 1.0.2
|
||||
call-bind: 1.0.8
|
||||
define-properties: 1.2.1
|
||||
es-abstract: 1.23.9
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
is-array-buffer: 3.0.4
|
||||
is-shared-array-buffer: 1.0.3
|
||||
is-array-buffer: 3.0.5
|
||||
is-shared-array-buffer: 1.0.4
|
||||
|
||||
arraybuffer.prototype.slice@1.0.4:
|
||||
dependencies:
|
||||
@@ -9103,7 +9112,7 @@ snapshots:
|
||||
|
||||
core-js@3.40.0: {}
|
||||
|
||||
core-js@3.41.0: {}
|
||||
core-js@3.42.0: {}
|
||||
|
||||
core-util-is@1.0.3: {}
|
||||
|
||||
@@ -9227,7 +9236,7 @@ snapshots:
|
||||
|
||||
css-vendor@2.0.8:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
is-in-browser: 1.1.3
|
||||
|
||||
css-what@6.1.0: {}
|
||||
@@ -9296,7 +9305,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
es-errors: 1.3.0
|
||||
is-data-view: 1.0.1
|
||||
is-data-view: 1.0.2
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
dependencies:
|
||||
@@ -9308,7 +9317,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
es-errors: 1.3.0
|
||||
is-data-view: 1.0.1
|
||||
is-data-view: 1.0.2
|
||||
|
||||
data-view-byte-length@1.0.2:
|
||||
dependencies:
|
||||
@@ -9320,7 +9329,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
es-errors: 1.3.0
|
||||
is-data-view: 1.0.1
|
||||
is-data-view: 1.0.2
|
||||
|
||||
data-view-byte-offset@1.0.1:
|
||||
dependencies:
|
||||
@@ -9410,7 +9419,7 @@ snapshots:
|
||||
|
||||
dom-helpers@5.2.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
csstype: 3.1.3
|
||||
|
||||
dom-serializer@1.4.1:
|
||||
@@ -9452,7 +9461,9 @@ snapshots:
|
||||
no-case: 3.0.4
|
||||
tslib: 2.6.3
|
||||
|
||||
dotenv-expand@10.0.0: {}
|
||||
dotenv-expand@12.0.2:
|
||||
dependencies:
|
||||
dotenv: 16.4.7
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
@@ -9518,7 +9529,7 @@ snapshots:
|
||||
array-buffer-byte-length: 1.0.1
|
||||
arraybuffer.prototype.slice: 1.0.3
|
||||
available-typed-arrays: 1.0.7
|
||||
call-bind: 1.0.7
|
||||
call-bind: 1.0.8
|
||||
data-view-buffer: 1.0.1
|
||||
data-view-byte-length: 1.0.1
|
||||
data-view-byte-offset: 1.0.0
|
||||
@@ -9553,7 +9564,7 @@ snapshots:
|
||||
safe-array-concat: 1.1.2
|
||||
safe-regex-test: 1.1.0
|
||||
string.prototype.trim: 1.2.9
|
||||
string.prototype.trimend: 1.0.8
|
||||
string.prototype.trimend: 1.0.9
|
||||
string.prototype.trimstart: 1.0.8
|
||||
typed-array-buffer: 1.0.2
|
||||
typed-array-byte-length: 1.0.1
|
||||
@@ -9654,7 +9665,7 @@ snapshots:
|
||||
|
||||
es-set-tostringtag@2.0.3:
|
||||
dependencies:
|
||||
get-intrinsic: 1.2.4
|
||||
get-intrinsic: 1.3.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
@@ -9732,7 +9743,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
source-map: 0.6.1
|
||||
|
||||
eslint-config-react-app@6.0.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(babel-eslint@10.1.0(eslint@7.32.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.30.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0))(eslint-plugin-jest@24.7.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.2(eslint@7.32.0))(eslint-plugin-react@7.37.2(eslint@7.32.0))(eslint-plugin-testing-library@3.10.2(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3):
|
||||
eslint-config-react-app@6.0.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(babel-eslint@10.1.0(eslint@7.32.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0))(eslint-plugin-jest@24.7.0(@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.2(eslint@7.32.0))(eslint-plugin-react@7.37.2(eslint@7.32.0))(eslint-plugin-testing-library@3.10.2(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 4.33.0(eslint@7.32.0)(typescript@5.8.3)
|
||||
@@ -9740,7 +9751,7 @@ snapshots:
|
||||
confusing-browser-globals: 1.0.11
|
||||
eslint: 7.32.0
|
||||
eslint-plugin-flowtype: 5.10.0(eslint@7.32.0)
|
||||
eslint-plugin-import: 2.30.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@7.32.0)
|
||||
eslint-plugin-react: 7.37.2(eslint@7.32.0)
|
||||
eslint-plugin-react-hooks: 4.6.2(eslint@7.32.0)
|
||||
@@ -9752,7 +9763,7 @@ snapshots:
|
||||
eslint-import-resolver-node@0.3.9:
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
is-core-module: 2.15.1
|
||||
is-core-module: 2.16.1
|
||||
resolve: 1.22.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -9767,7 +9778,7 @@ snapshots:
|
||||
schema-utils: 2.7.1
|
||||
webpack: 5.99.6
|
||||
|
||||
eslint-module-utils@2.11.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@7.32.0):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@7.32.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@@ -9788,26 +9799,27 @@ snapshots:
|
||||
lodash: 4.17.21
|
||||
requireindex: 1.1.0
|
||||
|
||||
eslint-plugin-import@2.30.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0):
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint@7.32.0):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.8
|
||||
array.prototype.findlastindex: 1.2.5
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
array.prototype.findlastindex: 1.2.6
|
||||
array.prototype.flat: 1.3.3
|
||||
array.prototype.flatmap: 1.3.3
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 7.32.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.11.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@7.32.0)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@7.32.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.15.1
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.fromentries: 2.0.8
|
||||
object.groupby: 1.0.3
|
||||
object.values: 1.2.0
|
||||
object.values: 1.2.1
|
||||
semver: 6.3.1
|
||||
string.prototype.trimend: 1.0.9
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 4.33.0(eslint@7.32.0)(typescript@5.8.3)
|
||||
@@ -10329,7 +10341,7 @@ snapshots:
|
||||
|
||||
gopd@1.0.1:
|
||||
dependencies:
|
||||
get-intrinsic: 1.2.4
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
@@ -10392,7 +10404,7 @@ snapshots:
|
||||
|
||||
history@4.10.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
loose-envify: 1.4.0
|
||||
resolve-pathname: 3.0.0
|
||||
tiny-invariant: 1.3.3
|
||||
@@ -10467,7 +10479,7 @@ snapshots:
|
||||
node-gettext: 3.0.0
|
||||
p-from-callback: 1.0.1
|
||||
|
||||
i18next-http-backend@2.5.2(encoding@0.1.13):
|
||||
i18next-http-backend@3.0.2(encoding@0.1.13):
|
||||
dependencies:
|
||||
cross-fetch: 4.0.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
@@ -10501,7 +10513,13 @@ snapshots:
|
||||
|
||||
i18next@23.16.8:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.7
|
||||
'@babel/runtime': 7.24.8
|
||||
|
||||
i18next@25.1.2(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.1
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
@@ -10599,7 +10617,7 @@ snapshots:
|
||||
|
||||
is-bigint@1.0.4:
|
||||
dependencies:
|
||||
has-bigints: 1.0.2
|
||||
has-bigints: 1.1.0
|
||||
|
||||
is-bigint@1.1.0:
|
||||
dependencies:
|
||||
@@ -10625,13 +10643,13 @@ snapshots:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
|
||||
is-core-module@2.15.1:
|
||||
is-core-module@2.16.1:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
|
||||
is-data-view@1.0.1:
|
||||
dependencies:
|
||||
is-typed-array: 1.1.13
|
||||
is-typed-array: 1.1.15
|
||||
|
||||
is-data-view@1.0.2:
|
||||
dependencies:
|
||||
@@ -10744,7 +10762,7 @@ snapshots:
|
||||
|
||||
is-typed-array@1.1.13:
|
||||
dependencies:
|
||||
which-typed-array: 1.1.15
|
||||
which-typed-array: 1.1.19
|
||||
|
||||
is-typed-array@1.1.15:
|
||||
dependencies:
|
||||
@@ -10825,7 +10843,7 @@ snapshots:
|
||||
iterator.prototype@1.1.3:
|
||||
dependencies:
|
||||
define-properties: 1.2.1
|
||||
get-intrinsic: 1.2.4
|
||||
get-intrinsic: 1.3.0
|
||||
has-symbols: 1.0.3
|
||||
reflect.getprototypeof: 1.0.6
|
||||
set-function-name: 2.0.2
|
||||
@@ -11212,46 +11230,46 @@ snapshots:
|
||||
|
||||
jss-plugin-camel-case@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
hyphenate-style-name: 1.1.0
|
||||
jss: 10.10.0
|
||||
|
||||
jss-plugin-default-unit@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
jss: 10.10.0
|
||||
|
||||
jss-plugin-global@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
jss: 10.10.0
|
||||
|
||||
jss-plugin-nested@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
jss-plugin-props-sort@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
jss: 10.10.0
|
||||
|
||||
jss-plugin-rule-value-function@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
jss-plugin-vendor-prefixer@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
css-vendor: 2.0.8
|
||||
jss: 10.10.0
|
||||
|
||||
jss@10.10.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
csstype: 3.1.3
|
||||
is-in-browser: 1.1.3
|
||||
tiny-warning: 1.0.3
|
||||
@@ -11440,7 +11458,7 @@ snapshots:
|
||||
|
||||
mini-create-react-context@0.4.1(prop-types@15.8.1)(react@17.0.2):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
prop-types: 15.8.1
|
||||
react: 17.0.2
|
||||
tiny-warning: 1.0.3
|
||||
@@ -11517,7 +11535,7 @@ snapshots:
|
||||
normalize-package-data@5.0.0:
|
||||
dependencies:
|
||||
hosted-git-info: 6.1.1
|
||||
is-core-module: 2.15.1
|
||||
is-core-module: 2.16.1
|
||||
semver: 7.7.1
|
||||
validate-npm-package-license: 3.0.4
|
||||
|
||||
@@ -11583,9 +11601,9 @@ snapshots:
|
||||
|
||||
object.groupby@1.0.3:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
call-bind: 1.0.8
|
||||
define-properties: 1.2.1
|
||||
es-abstract: 1.23.3
|
||||
es-abstract: 1.23.9
|
||||
|
||||
object.values@1.2.0:
|
||||
dependencies:
|
||||
@@ -11604,7 +11622,7 @@ snapshots:
|
||||
dependencies:
|
||||
acorn: 7.4.1
|
||||
base64-js: 1.5.1
|
||||
core-js: 3.41.0
|
||||
core-js: 3.42.0
|
||||
crypto-js: 4.2.0
|
||||
serialize-javascript: 4.0.0
|
||||
|
||||
@@ -12329,11 +12347,11 @@ snapshots:
|
||||
|
||||
react-error-overlay@6.0.11: {}
|
||||
|
||||
react-i18next@15.5.1(i18next@23.16.8)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.8.3):
|
||||
react-i18next@15.5.1(i18next@25.1.2(typescript@5.8.3))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
html-parse-stringify: 3.0.1
|
||||
i18next: 23.16.8
|
||||
i18next: 25.1.2(typescript@5.8.3)
|
||||
react: 17.0.2
|
||||
optionalDependencies:
|
||||
react-dom: 17.0.2(react@17.0.2)
|
||||
@@ -12383,7 +12401,7 @@ snapshots:
|
||||
|
||||
react-router@5.2.1(react@17.0.2):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
history: 4.10.1
|
||||
hoist-non-react-statics: 3.3.2
|
||||
loose-envify: 1.4.0
|
||||
@@ -12525,7 +12543,7 @@ snapshots:
|
||||
|
||||
regenerator-transform@0.15.2:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
|
||||
regex-parser@2.3.0: {}
|
||||
|
||||
@@ -12616,7 +12634,7 @@ snapshots:
|
||||
|
||||
resolve@2.0.0-next.5:
|
||||
dependencies:
|
||||
is-core-module: 2.15.1
|
||||
is-core-module: 2.16.1
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
|
||||
@@ -12649,7 +12667,7 @@ snapshots:
|
||||
safe-array-concat@1.1.2:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
get-intrinsic: 1.2.4
|
||||
get-intrinsic: 1.3.0
|
||||
has-symbols: 1.0.3
|
||||
isarray: 2.0.5
|
||||
|
||||
@@ -12796,7 +12814,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.4
|
||||
get-intrinsic: 1.3.0
|
||||
object-inspect: 1.13.2
|
||||
|
||||
side-channel@1.1.0:
|
||||
@@ -12982,12 +13000,6 @@ snapshots:
|
||||
es-abstract: 1.23.9
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
string.prototype.trimend@1.0.8:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
define-properties: 1.2.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
string.prototype.trimend@1.0.9:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@@ -13207,7 +13219,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
es-errors: 1.3.0
|
||||
is-typed-array: 1.1.13
|
||||
is-typed-array: 1.1.15
|
||||
|
||||
typed-array-buffer@1.0.3:
|
||||
dependencies:
|
||||
@@ -13219,9 +13231,9 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
for-each: 0.3.3
|
||||
gopd: 1.0.1
|
||||
has-proto: 1.0.3
|
||||
is-typed-array: 1.1.13
|
||||
gopd: 1.2.0
|
||||
has-proto: 1.2.0
|
||||
is-typed-array: 1.1.15
|
||||
|
||||
typed-array-byte-length@1.0.3:
|
||||
dependencies:
|
||||
@@ -13236,9 +13248,9 @@ snapshots:
|
||||
available-typed-arrays: 1.0.7
|
||||
call-bind: 1.0.8
|
||||
for-each: 0.3.3
|
||||
gopd: 1.0.1
|
||||
has-proto: 1.0.3
|
||||
is-typed-array: 1.1.13
|
||||
gopd: 1.2.0
|
||||
has-proto: 1.2.0
|
||||
is-typed-array: 1.1.15
|
||||
|
||||
typed-array-byte-offset@1.0.4:
|
||||
dependencies:
|
||||
@@ -13254,9 +13266,9 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
for-each: 0.3.3
|
||||
gopd: 1.0.1
|
||||
has-proto: 1.0.3
|
||||
is-typed-array: 1.1.13
|
||||
gopd: 1.2.0
|
||||
has-proto: 1.2.0
|
||||
is-typed-array: 1.1.15
|
||||
possible-typed-array-names: 1.0.0
|
||||
|
||||
typed-array-length@1.0.7:
|
||||
@@ -13283,7 +13295,7 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
has-bigints: 1.0.2
|
||||
has-symbols: 1.0.3
|
||||
has-symbols: 1.1.0
|
||||
which-boxed-primitive: 1.0.2
|
||||
|
||||
unbox-primitive@1.1.0:
|
||||
@@ -13570,7 +13582,7 @@ snapshots:
|
||||
available-typed-arrays: 1.0.7
|
||||
call-bind: 1.0.8
|
||||
for-each: 0.3.3
|
||||
gopd: 1.0.1
|
||||
gopd: 1.2.0
|
||||
has-tostringtag: 1.0.2
|
||||
|
||||
which-typed-array@1.1.19:
|
||||
@@ -13607,7 +13619,7 @@ snapshots:
|
||||
'@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1)
|
||||
'@babel/core': 7.26.10
|
||||
'@babel/preset-env': 7.26.9(@babel/core@7.26.10)
|
||||
'@babel/runtime': 7.27.0
|
||||
'@babel/runtime': 7.27.1
|
||||
'@rollup/plugin-babel': 5.3.1(@babel/core@7.26.10)(@types/babel__core@7.20.5)(rollup@2.79.2)
|
||||
'@rollup/plugin-node-resolve': 15.3.0(rollup@2.79.2)
|
||||
'@rollup/plugin-replace': 2.4.2(rollup@2.79.2)
|
||||
|
||||
@@ -78,7 +78,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
}
|
||||
natsServer, err := nats.NewNATSServer(
|
||||
ctx,
|
||||
logging.NewLogWrapper(logger),
|
||||
logger,
|
||||
nats.Host(cfg.Nats.Host),
|
||||
nats.Port(cfg.Nats.Port),
|
||||
nats.ClusterID(cfg.Nats.ClusterID),
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"time"
|
||||
|
||||
nserver "github.com/nats-io/nats-server/v2/server"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/nats/pkg/logging"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var NATSListenAndServeLoopTimer = 1 * time.Second
|
||||
@@ -15,7 +18,7 @@ type NATSServer struct {
|
||||
}
|
||||
|
||||
// NatsOption configures the new NATSServer instance
|
||||
func NewNATSServer(ctx context.Context, logger nserver.Logger, opts ...NatsOption) (*NATSServer, error) {
|
||||
func NewNATSServer(ctx context.Context, logger log.Logger, opts ...NatsOption) (*NATSServer, error) {
|
||||
natsOpts := &nserver.Options{}
|
||||
|
||||
for _, o := range opts {
|
||||
@@ -32,7 +35,8 @@ func NewNATSServer(ctx context.Context, logger nserver.Logger, opts ...NatsOptio
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server.SetLoggerV2(logger, true, true, false)
|
||||
nLogger := logging.NewLogWrapper(logger)
|
||||
server.SetLoggerV2(nLogger, logger.GetLevel() <= zerolog.DebugLevel, logger.GetLevel() <= zerolog.TraceLevel, false)
|
||||
|
||||
return &NATSServer{
|
||||
ctx: ctx,
|
||||
|
||||
@@ -294,6 +294,7 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
|
||||
authenticators = append(authenticators, middleware.AppAuthAuthenticator{
|
||||
Logger: logger,
|
||||
RevaGatewaySelector: gatewaySelector,
|
||||
UserRoleAssigner: roleAssigner,
|
||||
})
|
||||
}
|
||||
authenticators = append(authenticators, middleware.NewOIDCAuthenticator(
|
||||
|
||||
@@ -64,9 +64,12 @@ type Route struct {
|
||||
// Backend is a static URL to forward the request to
|
||||
Backend string `yaml:"backend,omitempty"`
|
||||
// Service name to look up in the registry
|
||||
Service string `yaml:"service,omitempty"`
|
||||
ApacheVHost bool `yaml:"apache_vhost,omitempty"`
|
||||
Unprotected bool `yaml:"unprotected,omitempty"`
|
||||
Service string `yaml:"service,omitempty"`
|
||||
ApacheVHost bool `yaml:"apache_vhost,omitempty"`
|
||||
Unprotected bool `yaml:"unprotected,omitempty"`
|
||||
AdditionalHeaders map[string]string `yaml:"additional_headers,omitempty"`
|
||||
RemoteUserHeader string `yaml:"remote_user_header,omitempty"`
|
||||
SkipXAccessToken bool `yaml:"skip_x_access_token"`
|
||||
}
|
||||
|
||||
// RouteType defines the type of route
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles"
|
||||
|
||||
@@ -99,8 +100,7 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
claims := oidc.FromContext(ctx)
|
||||
user, ok := revactx.ContextGetUser(ctx)
|
||||
token := ""
|
||||
// TODO what if an X-Access-Token is set? happens eg for download requests to the /data endpoint in the reva frontend
|
||||
token, hasToken := revactx.ContextGetToken(ctx)
|
||||
|
||||
if claims == nil && !ok {
|
||||
m.next.ServeHTTP(w, req)
|
||||
@@ -192,10 +192,11 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
m.logger.Debug().Interface("claims", claims).Interface("user", user).Msg("associated claims with user")
|
||||
} else if user != nil {
|
||||
} else if user != nil && !hasToken {
|
||||
// If we already have a token (e.g. the app auth middleware adds the token to the context) there is no need
|
||||
// to get yet another one here.
|
||||
var err error
|
||||
_, token, err = m.userProvider.GetUserByClaims(req.Context(), "username", user.Username)
|
||||
|
||||
if errors.Is(err, backend.ErrAccountDisabled) {
|
||||
m.logger.Debug().Interface("user", user).Msg("Disabled")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
@@ -209,7 +210,13 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
req.Header.Set(revactx.TokenHeader, token)
|
||||
ri := router.ContextRoutingInfo(ctx)
|
||||
if ri.RemoteUserHeader() != "" {
|
||||
req.Header.Set(ri.RemoteUserHeader(), user.GetId().GetOpaqueId())
|
||||
}
|
||||
if !ri.SkipXAccessToken() {
|
||||
req.Header.Set(revactx.TokenHeader, token)
|
||||
}
|
||||
|
||||
m.next.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/oidc"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend/mocks"
|
||||
userRoleMocks "github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles/mocks"
|
||||
@@ -206,6 +207,7 @@ func mockRequest(claims map[string]interface{}) (*http.Request, *httptest.Respon
|
||||
}
|
||||
|
||||
ctx := oidc.NewContext(context.Background(), claims)
|
||||
ctx = router.SetRoutingInfo(ctx, router.RoutingInfo{})
|
||||
req := httptest.NewRequest("GET", "http://example.com/foo", nil).WithContext(ctx)
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
)
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
type AppAuthAuthenticator struct {
|
||||
Logger log.Logger
|
||||
RevaGatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
UserRoleAssigner userroles.UserRoleAssigner
|
||||
}
|
||||
|
||||
// Authenticate implements the authenticator interface to authenticate requests via app auth.
|
||||
@@ -43,11 +45,20 @@ func (m AppAuthAuthenticator) Authenticate(r *http.Request) (*http.Request, bool
|
||||
return nil, false
|
||||
}
|
||||
if authenticateResponse.GetStatus().GetCode() != cs3rpc.Code_CODE_OK {
|
||||
// TODO: log???
|
||||
m.Logger.Debug().Str("msg", authenticateResponse.GetStatus().GetMessage()).Str("clientid", username).Msg("app auth failed")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
r.Header.Set(revactx.TokenHeader, authenticateResponse.GetToken())
|
||||
user := authenticateResponse.GetUser()
|
||||
if user, err = m.UserRoleAssigner.ApplyUserRole(r.Context(), user); err != nil {
|
||||
m.Logger.Error().Err(err).Str("clientid", username).Msg("app auth: failed to load user roles")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
ctx := revactx.ContextSetUser(r.Context(), user)
|
||||
ctx = revactx.ContextSetToken(ctx, authenticateResponse.GetToken())
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
return r, true
|
||||
}
|
||||
|
||||
@@ -5,19 +5,24 @@ import (
|
||||
"net/http/httptest"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
userRoleMocks "github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles/mocks"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func() {
|
||||
var authenticator Authenticator
|
||||
BeforeEach(func() {
|
||||
pool.RemoveSelector("GatewaySelector" + "eu.opencloud.api.gateway")
|
||||
ra := &userRoleMocks.UserRoleAssigner{}
|
||||
ra.On("ApplyUserRole", mock.Anything, mock.Anything, mock.Anything).Return(&userv1beta1.User{}, nil)
|
||||
authenticator = AppAuthAuthenticator{
|
||||
Logger: log.NewLogger(),
|
||||
RevaGatewaySelector: pool.GetSelector[gateway.GatewayAPIClient](
|
||||
@@ -39,6 +44,7 @@ var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func(
|
||||
}
|
||||
},
|
||||
),
|
||||
UserRoleAssigner: ra,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -51,7 +57,12 @@ var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func(
|
||||
|
||||
Expect(valid).To(Equal(true))
|
||||
Expect(req2).ToNot(BeNil())
|
||||
Expect(req2.Header.Get("x-access-token")).To(Equal("reva-token"))
|
||||
user, ok := revactx.ContextGetUser(req2.Context())
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(user).ToNot(BeNil())
|
||||
token, ok := revactx.ContextGetToken(req2.Context())
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(token).To(Equal("reva-token"))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ var _ = Describe("Authenticating requests", Label("Authentication"), func() {
|
||||
EnableBasicAuth(true),
|
||||
)
|
||||
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
Expect(r.Header.Get(headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
}))
|
||||
rr := httptest.NewRecorder()
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
@@ -178,7 +178,7 @@ var _ = Describe("Authenticating requests", Label("Authentication"), func() {
|
||||
EnableBasicAuth(true),
|
||||
)
|
||||
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
Expect(r.Header.Get(headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
}))
|
||||
rr := httptest.NewRecorder()
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
@@ -193,7 +193,7 @@ var _ = Describe("Authenticating requests", Label("Authentication"), func() {
|
||||
EnableBasicAuth(true),
|
||||
)
|
||||
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
Expect(r.Header.Get(headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
}))
|
||||
rr := httptest.NewRecorder()
|
||||
testHandler.ServeHTTP(rr, req)
|
||||
|
||||
@@ -45,7 +45,7 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
token := req.Header.Get("x-access-token")
|
||||
token := req.Header.Get(revactx.TokenHeader)
|
||||
|
||||
// we need to pass the token to authenticate the CreateHome request.
|
||||
//ctx := tokenpkg.ContextSetToken(r.Context(), token)
|
||||
@@ -84,7 +84,7 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
func (m createHome) shouldServe(req *http.Request) bool {
|
||||
return req.Header.Get("x-access-token") != ""
|
||||
return req.Header.Get(revactx.TokenHeader) != ""
|
||||
}
|
||||
|
||||
func (m createHome) getUserRoles(user *userv1beta1.User) ([]string, error) {
|
||||
|
||||
@@ -6,11 +6,12 @@ import (
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
)
|
||||
|
||||
const (
|
||||
_headerRevaAccessToken = "x-access-token"
|
||||
headerRevaAccessToken = revactx.TokenHeader
|
||||
headerShareToken = "public-token"
|
||||
basicAuthPasswordPrefix = "password|"
|
||||
authenticationType = "publicshares"
|
||||
@@ -118,7 +119,7 @@ func (a PublicShareAuthenticator) Authenticate(r *http.Request) (*http.Request,
|
||||
return nil, false
|
||||
}
|
||||
|
||||
r.Header.Add(_headerRevaAccessToken, authResp.Token)
|
||||
r.Header.Add(headerRevaAccessToken, authResp.Token)
|
||||
|
||||
a.Logger.Debug().
|
||||
Str("authenticator", "public_share").
|
||||
|
||||
@@ -58,7 +58,7 @@ var _ = Describe("Authenticating requests", Label("PublicShareAuthenticator"), f
|
||||
Expect(req2).ToNot(BeNil())
|
||||
|
||||
h := req2.Header
|
||||
Expect(h.Get(_headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
Expect(h.Get(headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
})
|
||||
})
|
||||
Context("using signature authentication", func() {
|
||||
@@ -71,7 +71,7 @@ var _ = Describe("Authenticating requests", Label("PublicShareAuthenticator"), f
|
||||
Expect(req2).ToNot(BeNil())
|
||||
|
||||
h := req2.Header
|
||||
Expect(h.Get(_headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
Expect(h.Get(headerRevaAccessToken)).To(Equal("exampletoken"))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -85,7 +85,7 @@ var _ = Describe("Authenticating requests", Label("PublicShareAuthenticator"), f
|
||||
Expect(req2).ToNot(BeNil())
|
||||
|
||||
h := req2.Header
|
||||
Expect(h.Get(_headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
Expect(h.Get(headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
||||
})
|
||||
})
|
||||
Context("not using a public-token", func() {
|
||||
|
||||
@@ -86,9 +86,11 @@ func New(serviceSelector selector.Selector, policySelectorCfg *config.PolicySele
|
||||
|
||||
// RoutingInfo contains the proxy rewrite hook and some information about the route.
|
||||
type RoutingInfo struct {
|
||||
rewrite func(*httputil.ProxyRequest)
|
||||
endpoint string
|
||||
unprotected bool
|
||||
rewrite func(*httputil.ProxyRequest)
|
||||
endpoint string
|
||||
unprotected bool
|
||||
remoteUserHeader string
|
||||
skipXAccessToken bool
|
||||
}
|
||||
|
||||
// Rewrite returns the proxy rewrite hook.
|
||||
@@ -101,6 +103,17 @@ func (r RoutingInfo) IsRouteUnprotected() bool {
|
||||
return r.unprotected
|
||||
}
|
||||
|
||||
// RemoteUserHeader returns the name of Header for setting the remote user value
|
||||
func (r RoutingInfo) RemoteUserHeader() string {
|
||||
return r.remoteUserHeader
|
||||
}
|
||||
|
||||
// SkipXAccessToken return true if the reva access token should not be added to the
|
||||
// outgoing request
|
||||
func (r RoutingInfo) SkipXAccessToken() bool {
|
||||
return r.skipXAccessToken
|
||||
}
|
||||
|
||||
// Router handles the routing of HTTP requests according to the given policies.
|
||||
type Router struct {
|
||||
logger log.Logger
|
||||
@@ -126,8 +139,10 @@ func (rt Router) addHost(policy string, target *url.URL, route config.Route) {
|
||||
}
|
||||
|
||||
rt.rewriters[policy][routeType][route.Method] = append(rt.rewriters[policy][routeType][route.Method], RoutingInfo{
|
||||
endpoint: route.Endpoint,
|
||||
unprotected: route.Unprotected,
|
||||
endpoint: route.Endpoint,
|
||||
unprotected: route.Unprotected,
|
||||
remoteUserHeader: route.RemoteUserHeader,
|
||||
skipXAccessToken: route.SkipXAccessToken,
|
||||
rewrite: func(req *httputil.ProxyRequest) {
|
||||
if route.Service != "" {
|
||||
// select next node
|
||||
@@ -161,6 +176,10 @@ func (rt Router) addHost(policy string, target *url.URL, route config.Route) {
|
||||
req.Out.Host = target.Host
|
||||
}
|
||||
|
||||
for k, v := range route.AdditionalHeaders {
|
||||
req.Out.Header.Set(k, v)
|
||||
}
|
||||
|
||||
req.Out.URL.Path = singleJoiningSlash(target.Path, req.Out.URL.Path)
|
||||
if targetQuery == "" || req.Out.URL.RawQuery == "" {
|
||||
req.Out.URL.RawQuery = targetQuery + req.Out.URL.RawQuery
|
||||
@@ -209,6 +228,8 @@ func (rt Router) Route(r *http.Request) (RoutingInfo, bool) {
|
||||
if rt.rewriters[pol][rtype][r.Method] != nil {
|
||||
// use specific method
|
||||
method = r.Method
|
||||
} else {
|
||||
method = ""
|
||||
}
|
||||
|
||||
for _, ri := range rt.rewriters[pol][rtype][method] {
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
|
||||
namespace TestHelpers;
|
||||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\OcConfigHelper;
|
||||
|
||||
|
||||
@@ -34,6 +34,26 @@ class CliContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private SpacesContext $spacesContext;
|
||||
|
||||
/**
|
||||
* opencloud users storage path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getUsersStoragePath(): string {
|
||||
$path = getenv('OC_STORAGE_PATH') ?: '/var/lib/opencloud/storage/users';
|
||||
return $path . '/users';
|
||||
}
|
||||
|
||||
/**
|
||||
* opencloud project spaces storage path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getProjectsStoragePath(): string {
|
||||
$path = getenv('OC_STORAGE_PATH') ?: '/var/lib/opencloud/storage/users';
|
||||
return $path . '/projects';
|
||||
}
|
||||
|
||||
/**
|
||||
* @BeforeScenario
|
||||
*
|
||||
@@ -85,8 +105,8 @@ class CliContext implements Context {
|
||||
): void {
|
||||
$command = "idm resetpassword -u $user";
|
||||
$body = [
|
||||
"command" => $command,
|
||||
"inputs" => [$password, $password]
|
||||
"command" => $command,
|
||||
"inputs" => [$password, $password]
|
||||
];
|
||||
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
@@ -105,7 +125,7 @@ class CliContext implements Context {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "trash purge-empty-dirs -p $path --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -119,7 +139,7 @@ class CliContext implements Context {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "backup consistency -p $path";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -139,7 +159,7 @@ class CliContext implements Context {
|
||||
$user = $this->featureContext->getActualUserName($user);
|
||||
$command = "auth-app create --user-name=$user --expiration=$expirationTime";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -159,7 +179,7 @@ class CliContext implements Context {
|
||||
$user = $this->featureContext->getActualUserName($user);
|
||||
$command = "auth-app create --user-name=$user --expiration=$expirationTime";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
|
||||
$response = CliHelper::runCommand($body);
|
||||
@@ -182,7 +202,7 @@ class CliContext implements Context {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "revisions purge -p $path --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -201,7 +221,7 @@ class CliContext implements Context {
|
||||
$fileId = $this->spacesContext->getFileId($user, $space, $file);
|
||||
$command = "revisions purge -p $path -r $fileId --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -214,7 +234,7 @@ class CliContext implements Context {
|
||||
public function theAdministratorReindexesAllSpacesUsingTheCli(): void {
|
||||
$command = "search index --all-spaces";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -230,7 +250,7 @@ class CliContext implements Context {
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $spaceName);
|
||||
$command = "search index --space $spaceId";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -248,7 +268,7 @@ class CliContext implements Context {
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
||||
$command = "revisions purge -p $path -r $spaceId --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -306,7 +326,7 @@ class CliContext implements Context {
|
||||
}
|
||||
$command = "storage-users uploads sessions --json $flag";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -326,7 +346,7 @@ class CliContext implements Context {
|
||||
$flagString = trim($flag);
|
||||
$command = "storage-users uploads sessions $flagString --clean --json";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -339,7 +359,7 @@ class CliContext implements Context {
|
||||
public function theAdministratorRestartsTheUploadSessionsThatAreInPostprocessing(): void {
|
||||
$command = "storage-users uploads sessions --processing --restart --json";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -365,7 +385,7 @@ class CliContext implements Context {
|
||||
|
||||
$command = "storage-users uploads sessions --id=$uploadId --restart --json";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
@@ -431,9 +451,241 @@ class CliContext implements Context {
|
||||
public function cleanUploadsSessions(): void {
|
||||
$command = "storage-users uploads sessions --clean";
|
||||
$body = [
|
||||
"command" => $command
|
||||
"command" => $command
|
||||
];
|
||||
$response = CliHelper::runCommand($body);
|
||||
Assert::assertEquals("200", $response->getStatusCode(), "Failed to clean upload sessions");
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator creates the folder :folder for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $folder
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorCreatesFolder(string $folder, string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
$body = [
|
||||
"command" => "mkdir -p $storagePath/$userUuid/$folder",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator lists the content of the POSIX storage folder of user :user
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorCheckUsersFolder(string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
$body = [
|
||||
"command" => "ls -la $storagePath/$userUuid",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator creates the file :file with content :content for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $content
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorCreatesFile(string $file, string $content, string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
$safeContent = escapeshellarg($content);
|
||||
$body = [
|
||||
"command" => "echo -n $safeContent > $storagePath/$userUuid/$file",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator puts the content :content into the file :file in the POSIX storage folder of user :user
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $file
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorChangesFileContent(string $content, string $file, string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
$safeContent = escapeshellarg($content);
|
||||
$body = [
|
||||
"command" => "echo -n $safeContent >> $storagePath/$userUuid/$file",
|
||||
"raw" => true
|
||||
];
|
||||
sleep(1);
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator reads the content of the file :file in the POSIX storage folder of user :user
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorReadsTheFileContent(string $user, string $file): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
$body = [
|
||||
"command" => "cat $storagePath/$userUuid/$file",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator copies the file :file to the folder :folder for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $folder
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorCopiesFileToFolder(string $user, string $file, string $folder): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
|
||||
$source = "$storagePath/$userUuid/$file";
|
||||
$destination = "$storagePath/$userUuid/$folder";
|
||||
|
||||
$body = [
|
||||
"command" => "cp $source $destination",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator moves the file :file to the folder :folder for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $folder
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorMovesFileToFolder(string $user, string $file, string $folder): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
|
||||
$source = "$storagePath/$userUuid/$file";
|
||||
$destination = "$storagePath/$userUuid/$folder";
|
||||
|
||||
$body = [
|
||||
"command" => "mv $source $destination",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator deletes the file :file for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorDeletesFile(string $file, string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
|
||||
$body = [
|
||||
"command" => "rm $storagePath/$userUuid/$file",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator deletes the folder :folder for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $folder
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorDeletesFolder(string $folder, string $user): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$storagePath = $this->getUsersStoragePath();
|
||||
|
||||
$body = [
|
||||
"command" => "rm -r $storagePath/$userUuid/$folder",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator copies the file :file to the space :space for user :user on the POSIX filesystem
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $space
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorCopiesFileToSpace(string $user, string $file, string $space): void {
|
||||
$userUuid = $this->featureContext->getUserIdByUserName($user);
|
||||
$usersStoragePath = $this->getUsersStoragePath();
|
||||
$projectsStoragePath = $this->getProjectsStoragePath();
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $space);
|
||||
$spaceId = explode('$', $spaceId)[1];
|
||||
|
||||
$source = "$usersStoragePath/$userUuid/$file";
|
||||
$destination = "$projectsStoragePath/$spaceId";
|
||||
|
||||
$body = [
|
||||
"command" => "cp $source $destination",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator deletes the project space :space on the POSIX filesystem
|
||||
*
|
||||
* @param string $space
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorDeletesSpace(string $space): void {
|
||||
$projectsStoragePath = $this->getProjectsStoragePath();
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $space);
|
||||
$spaceId = explode('$', $spaceId)[1];
|
||||
|
||||
$body = [
|
||||
"command" => "rm -r $projectsStoragePath/$spaceId",
|
||||
"raw" => true
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,6 +458,15 @@ default:
|
||||
- TrashbinContext:
|
||||
- SpacesTUSContext:
|
||||
|
||||
collaborativePosix:
|
||||
paths:
|
||||
- "%paths.base%/../features/collaborativePosix"
|
||||
context: *common_ldap_suite_context
|
||||
contexts:
|
||||
- FeatureContext: *common_feature_context_params
|
||||
- CliContext:
|
||||
- OcConfigContext:
|
||||
|
||||
coreApiMain:
|
||||
paths:
|
||||
- "%paths.base%/../features/coreApiMain"
|
||||
|
||||
@@ -48,8 +48,8 @@ else
|
||||
SEARCH_EXTRACTOR_TYPE := basic
|
||||
endif
|
||||
|
||||
# default to decomposedfs
|
||||
STORAGE_DRIVER ?= decomposed
|
||||
# default to posix
|
||||
STORAGE_DRIVER ?= posix
|
||||
ifeq ($(STORAGE_DRIVER),posix)
|
||||
# posix requires a additional driver config
|
||||
COMPOSE_FILE := $(COMPOSE_FILE):src/posix.yml
|
||||
|
||||
@@ -10,6 +10,7 @@ services:
|
||||
WITH_WRAPPER: $WITH_WRAPPER
|
||||
OC_URL: "https://opencloud-server:9200"
|
||||
STORAGE_USERS_DRIVER: $STORAGE_DRIVER
|
||||
STORAGE_USERS_POSIX_WATCH_FS: "true"
|
||||
STORAGE_USERS_DRIVER_LOCAL_ROOT: /srv/app/tmp/opencloud/local/root
|
||||
STORAGE_USERS_DRIVER_OC_ROOT: /srv/app/tmp/opencloud/storage/users
|
||||
STORAGE_SYSTEM_DRIVER_OC_ROOT: /srv/app/tmp/opencloud/storage/metadata
|
||||
|
||||
@@ -6,6 +6,7 @@ FROM opencloudeu/opencloud:${OC_IMAGE_TAG} AS opencloud
|
||||
|
||||
FROM ubuntu:22.04
|
||||
COPY --from=opencloud /usr/bin/opencloud /usr/bin/opencloud
|
||||
RUN apt-get update && apt-get install -y inotify-tools
|
||||
|
||||
COPY ["./serve-opencloud.sh", "/usr/bin/serve-opencloud"]
|
||||
RUN chmod +x /usr/bin/serve-opencloud
|
||||
|
||||
@@ -6,3 +6,4 @@ services:
|
||||
STORAGE_USERS_DRIVER: posix
|
||||
# posix requires a shared cache store
|
||||
STORAGE_USERS_ID_CACHE_STORE: "nats-js-kv"
|
||||
STORAGE_USERS_POSIX_WATCH_FS: "true"
|
||||
|
||||
231
tests/acceptance/expected-failures-localAPI-on-posix-storage.md
Normal file
231
tests/acceptance/expected-failures-localAPI-on-posix-storage.md
Normal file
@@ -0,0 +1,231 @@
|
||||
## Scenarios from OpenCloud API tests that are expected to fail with decomposed storage
|
||||
|
||||
#### [Downloading the archive of the resource (files | folder) using resource path is not possible](https://github.com/owncloud/ocis/issues/4637)
|
||||
|
||||
- [apiArchiver/downloadByPath.feature:25](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L25)
|
||||
- [apiArchiver/downloadByPath.feature:26](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L26)
|
||||
- [apiArchiver/downloadByPath.feature:43](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L43)
|
||||
- [apiArchiver/downloadByPath.feature:44](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L44)
|
||||
- [apiArchiver/downloadByPath.feature:47](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L47)
|
||||
- [apiArchiver/downloadByPath.feature:73](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L73)
|
||||
- [apiArchiver/downloadByPath.feature:171](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L171)
|
||||
- [apiArchiver/downloadByPath.feature:172](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiArchiver/downloadByPath.feature#L172)
|
||||
|
||||
#### [PATCH request for TUS upload with wrong checksum gives incorrect response](https://github.com/owncloud/ocis/issues/1755)
|
||||
|
||||
- [apiSpacesShares/shareUploadTUS.feature:283](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature#L283)
|
||||
- [apiSpacesShares/shareUploadTUS.feature:303](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature#L303)
|
||||
- [apiSpacesShares/shareUploadTUS.feature:384](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature#L384)
|
||||
|
||||
#### [Settings service user can list other peoples assignments](https://github.com/owncloud/ocis/issues/5032)
|
||||
|
||||
- [apiAccountsHashDifficulty/assignRole.feature:27](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAccountsHashDifficulty/assignRole.feature#L27)
|
||||
- [apiAccountsHashDifficulty/assignRole.feature:28](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAccountsHashDifficulty/assignRole.feature#L28)
|
||||
- [apiGraph/getAssignedRole.feature:31](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/getAssignedRole.feature#L31)
|
||||
- [apiGraph/getAssignedRole.feature:32](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/getAssignedRole.feature#L32)
|
||||
- [apiGraph/getAssignedRole.feature:33](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraph/getAssignedRole.feature#L33)
|
||||
|
||||
#### [A User can get information of another user with Graph API](https://github.com/owncloud/ocis/issues/5125)
|
||||
|
||||
- [apiGraphUserGroup/getUser.feature:84](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L84)
|
||||
- [apiGraphUserGroup/getUser.feature:85](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L85)
|
||||
- [apiGraphUserGroup/getUser.feature:86](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L86)
|
||||
- [apiGraphUserGroup/getUser.feature:628](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L628)
|
||||
- [apiGraphUserGroup/getUser.feature:629](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L629)
|
||||
- [apiGraphUserGroup/getUser.feature:630](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L630)
|
||||
- [apiGraphUserGroup/getUser.feature:645](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L645)
|
||||
- [apiGraphUserGroup/getUser.feature:646](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L646)
|
||||
- [apiGraphUserGroup/getUser.feature:647](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L647)
|
||||
|
||||
#### [Normal user can get expanded members information of a group](https://github.com/owncloud/ocis/issues/5604)
|
||||
|
||||
- [apiGraphUserGroup/getGroup.feature:399](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L399)
|
||||
- [apiGraphUserGroup/getGroup.feature:400](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L400)
|
||||
- [apiGraphUserGroup/getGroup.feature:401](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L401)
|
||||
- [apiGraphUserGroup/getGroup.feature:460](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L460)
|
||||
- [apiGraphUserGroup/getGroup.feature:461](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L461)
|
||||
- [apiGraphUserGroup/getGroup.feature:462](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L462)
|
||||
- [apiGraphUserGroup/getGroup.feature:508](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L508)
|
||||
- [apiGraphUserGroup/getGroup.feature:509](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L509)
|
||||
- [apiGraphUserGroup/getGroup.feature:510](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L510)
|
||||
|
||||
#### [Same users can be added in a group multiple time](https://github.com/owncloud/ocis/issues/5702)
|
||||
|
||||
- [apiGraphUserGroup/addUserToGroup.feature:295](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L295)
|
||||
|
||||
#### [Users are added in a group with wrong host in host-part of user](https://github.com/owncloud/ocis/issues/5871)
|
||||
|
||||
- [apiGraphUserGroup/addUserToGroup.feature:379](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L379)
|
||||
- [apiGraphUserGroup/addUserToGroup.feature:393](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L393)
|
||||
|
||||
#### [Adding the same user as multiple members in a single request results in listing the same user twice in the group](https://github.com/owncloud/ocis/issues/5855)
|
||||
|
||||
- [apiGraphUserGroup/addUserToGroup.feature:430](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L430)
|
||||
|
||||
#### [Shared file locking is not possible using different path](https://github.com/owncloud/ocis/issues/7599)
|
||||
|
||||
- [apiLocks/lockFiles.feature:185](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L185)
|
||||
- [apiLocks/lockFiles.feature:186](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L186)
|
||||
- [apiLocks/lockFiles.feature:187](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L187)
|
||||
- [apiLocks/lockFiles.feature:309](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L309)
|
||||
- [apiLocks/lockFiles.feature:310](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L310)
|
||||
- [apiLocks/lockFiles.feature:311](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L311)
|
||||
- [apiLocks/lockFiles.feature:364](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L364)
|
||||
- [apiLocks/lockFiles.feature:365](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L365)
|
||||
- [apiLocks/lockFiles.feature:366](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L366)
|
||||
- [apiLocks/lockFiles.feature:367](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L367)
|
||||
- [apiLocks/lockFiles.feature:368](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L368)
|
||||
- [apiLocks/lockFiles.feature:369](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L369)
|
||||
- [apiLocks/lockFiles.feature:399](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L399)
|
||||
- [apiLocks/lockFiles.feature:400](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L400)
|
||||
- [apiLocks/lockFiles.feature:401](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L401)
|
||||
- [apiLocks/lockFiles.feature:402](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L402)
|
||||
- [apiLocks/lockFiles.feature:403](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L403)
|
||||
- [apiLocks/lockFiles.feature:404](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L404)
|
||||
- [apiLocks/unlockFiles.feature:62](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L62)
|
||||
- [apiLocks/unlockFiles.feature:63](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L63)
|
||||
- [apiLocks/unlockFiles.feature:64](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L64)
|
||||
- [apiLocks/unlockFiles.feature:171](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L171)
|
||||
- [apiLocks/unlockFiles.feature:172](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L172)
|
||||
- [apiLocks/unlockFiles.feature:173](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L173)
|
||||
- [apiLocks/unlockFiles.feature:174](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L174)
|
||||
- [apiLocks/unlockFiles.feature:175](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L175)
|
||||
- [apiLocks/unlockFiles.feature:176](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L176)
|
||||
- [apiLocks/unlockFiles.feature:199](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L199)
|
||||
- [apiLocks/unlockFiles.feature:200](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L200)
|
||||
- [apiLocks/unlockFiles.feature:201](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L201)
|
||||
- [apiLocks/unlockFiles.feature:202](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L202)
|
||||
- [apiLocks/unlockFiles.feature:203](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L203)
|
||||
- [apiLocks/unlockFiles.feature:204](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L204)
|
||||
- [apiLocks/unlockFiles.feature:227](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L227)
|
||||
- [apiLocks/unlockFiles.feature:228](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L228)
|
||||
- [apiLocks/unlockFiles.feature:229](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L229)
|
||||
- [apiLocks/unlockFiles.feature:230](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L230)
|
||||
- [apiLocks/unlockFiles.feature:231](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L231)
|
||||
- [apiLocks/unlockFiles.feature:232](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L232)
|
||||
|
||||
#### [Folders can be locked and locking works partially](https://github.com/owncloud/ocis/issues/7641)
|
||||
|
||||
- [apiLocks/lockFiles.feature:443](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L443)
|
||||
- [apiLocks/lockFiles.feature:444](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L444)
|
||||
- [apiLocks/lockFiles.feature:445](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L445)
|
||||
- [apiLocks/lockFiles.feature:446](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L446)
|
||||
- [apiLocks/lockFiles.feature:447](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L447)
|
||||
- [apiLocks/lockFiles.feature:448](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L448)
|
||||
- [apiLocks/lockFiles.feature:417](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L417)
|
||||
- [apiLocks/lockFiles.feature:418](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L418)
|
||||
- [apiLocks/lockFiles.feature:419](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L419)
|
||||
- [apiLocks/lockFiles.feature:420](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L420)
|
||||
- [apiLocks/lockFiles.feature:421](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L421)
|
||||
- [apiLocks/lockFiles.feature:422](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L422)
|
||||
|
||||
#### [Anonymous users can unlock a file shared to them through a public link if they get the lock token](https://github.com/owncloud/ocis/issues/7761)
|
||||
|
||||
- [apiLocks/unlockFiles.feature:42](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L42)
|
||||
- [apiLocks/unlockFiles.feature:43](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L43)
|
||||
- [apiLocks/unlockFiles.feature:44](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L44)
|
||||
- [apiLocks/unlockFiles.feature:45](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L45)
|
||||
- [apiLocks/unlockFiles.feature:46](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L46)
|
||||
- [apiLocks/unlockFiles.feature:47](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L47)
|
||||
|
||||
#### [Trying to unlock a shared file with sharer's lock token gives 500](https://github.com/owncloud/ocis/issues/7767)
|
||||
|
||||
- [apiLocks/unlockFiles.feature:115](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L115)
|
||||
- [apiLocks/unlockFiles.feature:116](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L116)
|
||||
- [apiLocks/unlockFiles.feature:117](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L117)
|
||||
- [apiLocks/unlockFiles.feature:118](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L118)
|
||||
- [apiLocks/unlockFiles.feature:119](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L119)
|
||||
- [apiLocks/unlockFiles.feature:120](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L120)
|
||||
- [apiLocks/unlockFiles.feature:143](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L143)
|
||||
- [apiLocks/unlockFiles.feature:144](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L144)
|
||||
- [apiLocks/unlockFiles.feature:145](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L145)
|
||||
- [apiLocks/unlockFiles.feature:146](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L146)
|
||||
- [apiLocks/unlockFiles.feature:147](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L147)
|
||||
- [apiLocks/unlockFiles.feature:148](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/unlockFiles.feature#L148)
|
||||
|
||||
#### [Anonymous user trying lock a file shared to them through a public link gives 405](https://github.com/owncloud/ocis/issues/7790)
|
||||
|
||||
- [apiLocks/lockFiles.feature:532](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L532)
|
||||
- [apiLocks/lockFiles.feature:533](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L533)
|
||||
- [apiLocks/lockFiles.feature:534](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L534)
|
||||
- [apiLocks/lockFiles.feature:535](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L535)
|
||||
- [apiLocks/lockFiles.feature:554](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L554)
|
||||
- [apiLocks/lockFiles.feature:555](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L555)
|
||||
- [apiLocks/lockFiles.feature:556](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L556)
|
||||
- [apiLocks/lockFiles.feature:557](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiLocks/lockFiles.feature#L557)
|
||||
|
||||
#### [sharee (editor role) MOVE a file by file-id into shared sub-folder returns 502](https://github.com/owncloud/ocis/issues/7617)
|
||||
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:368](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L368)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:591](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L591)
|
||||
|
||||
#### [MOVE a file into same folder with same name returns 404 instead of 403](https://github.com/owncloud/ocis/issues/1976)
|
||||
|
||||
- [apiSpacesShares/moveSpaces.feature:69](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/moveSpaces.feature#L69)
|
||||
- [apiSpacesShares/moveSpaces.feature:70](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/moveSpaces.feature#L70)
|
||||
- [apiSpacesShares/moveSpaces.feature:416](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesShares/moveSpaces.feature#L416)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:61](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L61)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:174](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L174)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:175](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L175)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:176](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L176)
|
||||
- [apiSpacesDavOperation/moveByFileId.feature:393](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L393)
|
||||
|
||||
#### [OCM. admin cannot get federated users if he hasn't connection with them ](https://github.com/owncloud/ocis/issues/9829)
|
||||
|
||||
- [apiOcm/searchFederationUsers.feature:429](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiOcm/searchFederationUsers.feature#L429)
|
||||
- [apiOcm/searchFederationUsers.feature:601](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiOcm/searchFederationUsers.feature#L601)
|
||||
|
||||
#### [OCM. federated connection is not dropped when one of the users deletes the connection](https://github.com/owncloud/ocis/issues/10216)
|
||||
|
||||
- [apiOcm/deleteFederatedConnections.feature:21](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiOcm/deleteFederatedConnections.feature#L21)
|
||||
- [apiOcm/deleteFederatedConnections.feature:67](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiOcm/deleteFederatedConnections.feature#L67)
|
||||
|
||||
#### [OCM. server crash after deleting share for ocm user](https://github.com/owncloud/ocis/issues/10213)
|
||||
|
||||
- [apiOcm/deleteFederatedConnections.feature:102](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiOcm/deleteFederatedConnections.feature#L102)
|
||||
|
||||
#### [Shares Jail PROPFIND returns different File IDs for the same item](https://github.com/owncloud/ocis/issues/9933)
|
||||
|
||||
- [apiSharingNg1/propfindShares.feature:149](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSharingNg1/propfindShares.feature#L149)
|
||||
|
||||
#### [Readiness check for some services returns 500 status code](https://github.com/owncloud/ocis/issues/10661)
|
||||
- [apiServiceAvailability/serviceAvailabilityCheck.feature:116](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiServiceAvailability/serviceAvailabilityCheck.feature#L116)
|
||||
- [apiServiceAvailability/serviceAvailabilityCheck.feature:125](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiServiceAvailability/serviceAvailabilityCheck.feature#L125)
|
||||
|
||||
#### [Skip tests for different languages](https://github.com/opencloud-eu/opencloud/issues/183)
|
||||
- [apiActivities/activities.feature:2598](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiActivities/activities.feature#L2598)
|
||||
|
||||
|
||||
#### [Missing properties in REPORT response](https://github.com/owncloud/ocis/issues/9780), [d:getetag property has empty value in REPORT response](https://github.com/owncloud/ocis/issues/9783)
|
||||
|
||||
- [apiSearch1/search.feature:437](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L437)
|
||||
- [apiSearch1/search.feature:438](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L438)
|
||||
- [apiSearch1/search.feature:439](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L439)
|
||||
- [apiSearch1/search.feature:465](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L465)
|
||||
- [apiSearch1/search.feature:466](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L466)
|
||||
- [apiSearch1/search.feature:467](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSearch1/search.feature#L467)
|
||||
|
||||
#### [No notification triggered for .zip virus file](https://github.com/opencloud-eu/opencloud/issues/382)
|
||||
- [apiAntivirus/antivirus.feature:41](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L41)
|
||||
- [apiAntivirus/antivirus.feature:43](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L43)
|
||||
- [apiAntivirus/antivirus.feature:45](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L45)
|
||||
- [apiAntivirus/antivirus.feature:69](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L69)
|
||||
- [apiAntivirus/antivirus.feature:71](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L71)
|
||||
- [apiAntivirus/antivirus.feature:73](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L73)
|
||||
- [apiAntivirus/antivirus.feature:115](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L115)
|
||||
- [apiAntivirus/antivirus.feature:117](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L117)
|
||||
- [apiAntivirus/antivirus.feature:119](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L119)
|
||||
- [apiAntivirus/antivirus.feature:141](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L141)
|
||||
- [apiAntivirus/antivirus.feature:143](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L143)
|
||||
- [apiAntivirus/antivirus.feature:145](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L145)
|
||||
- [apiAntivirus/antivirus.feature:169](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L169)
|
||||
- [apiAntivirus/antivirus.feature:171](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L171)
|
||||
- [apiAntivirus/antivirus.feature:173](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L173)
|
||||
- [apiAntivirus/antivirus.feature:199](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L199)
|
||||
- [apiAntivirus/antivirus.feature:201](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L201)
|
||||
- [apiAntivirus/antivirus.feature:203](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L203)
|
||||
- [apiAntivirus/antivirus.feature:228](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L228)
|
||||
- [apiAntivirus/antivirus.feature:253](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiAntivirus/antivirus.feature#L253)
|
||||
|
||||
Note: always have an empty line at the end of this file.
|
||||
The bash script that processes this file requires that the last line has a newline on the end.
|
||||
@@ -30,7 +30,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -152,7 +152,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -205,7 +205,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 60
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add and delete."
|
||||
@@ -293,7 +293,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -353,7 +353,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 100
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and edit."
|
||||
@@ -435,7 +435,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 50
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and upload."
|
||||
@@ -488,7 +488,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -564,7 +564,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight":{
|
||||
"const": 0
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -695,7 +695,7 @@ Feature: permissions role definitions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 0
|
||||
"const": 20
|
||||
},
|
||||
"description": {
|
||||
"const": "View only documents, images and PDFs. Watermarks will be applied."
|
||||
@@ -756,4 +756,4 @@ Feature: permissions role definitions
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -153,7 +153,7 @@ Feature: List a federated sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -176,7 +176,7 @@ Feature: List a federated sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 100
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and edit."
|
||||
@@ -228,7 +228,7 @@ Feature: List a federated sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -251,7 +251,7 @@ Feature: List a federated sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 60
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add and delete."
|
||||
|
||||
@@ -60,7 +60,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -83,7 +83,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 50
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and upload."
|
||||
@@ -106,7 +106,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 60
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add and delete."
|
||||
@@ -183,7 +183,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -206,7 +206,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -229,7 +229,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -316,7 +316,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -339,7 +339,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -362,7 +362,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -580,7 +580,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -603,7 +603,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 100
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and edit."
|
||||
@@ -680,7 +680,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -703,7 +703,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 50
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and upload."
|
||||
@@ -726,7 +726,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 60
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add and delete."
|
||||
@@ -803,7 +803,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 10
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -826,7 +826,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 100
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download and edit."
|
||||
@@ -926,7 +926,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -949,7 +949,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -972,7 +972,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -1048,7 +1048,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -1071,7 +1071,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -1094,7 +1094,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -1330,7 +1330,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -1353,7 +1353,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -1376,7 +1376,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -1668,7 +1668,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 40
|
||||
},
|
||||
"description": {
|
||||
"const": "View and download."
|
||||
@@ -1691,7 +1691,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 90
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete including the history."
|
||||
@@ -1714,7 +1714,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 3
|
||||
"const": 120
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add, delete and manage members."
|
||||
@@ -2188,7 +2188,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 20
|
||||
},
|
||||
"description": {
|
||||
"const": "View only documents, images and PDFs. Watermarks will be applied."
|
||||
@@ -2297,7 +2297,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 2
|
||||
"const": 80
|
||||
},
|
||||
"description": {
|
||||
"const": "View, download, upload, edit, add and delete."
|
||||
@@ -2377,7 +2377,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 200
|
||||
},
|
||||
"description": {
|
||||
"const": "Deny all access."
|
||||
@@ -2474,7 +2474,7 @@ Feature: List a sharing permissions
|
||||
],
|
||||
"properties": {
|
||||
"@libre.graph.weight": {
|
||||
"const": 1
|
||||
"const": 200
|
||||
},
|
||||
"description": {
|
||||
"const": "Deny all access."
|
||||
|
||||
@@ -434,7 +434,7 @@ Feature: Change data of space
|
||||
When user "<user>" uploads a file inside space "Project Jupiter" with content "" to ".space/newSpaceImage.png" using the WebDAV API
|
||||
And user "<user>" sets the file ".space/newSpaceImage.png" as a space image in a special section of the "Project Jupiter" space
|
||||
Then the HTTP status code should be "200"
|
||||
And the JSON response should contain space called "Project Jupiter" owned by "Alice" with description file ".space/newSpaceImage.png" and match
|
||||
And the JSON response should contain space called "Project Jupiter" owned by "Alice" with space image ".space/newSpaceImage.png" and match
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
@@ -597,4 +597,78 @@ Feature: Change data of space
|
||||
Examples:
|
||||
| role |
|
||||
| Space Editor Without Versions |
|
||||
| Space Editor |
|
||||
| Space Editor |
|
||||
|
||||
@issue-462
|
||||
Scenario: user doesn't lose the space image when admin fetches the space
|
||||
Given the administrator has assigned the role "Space Admin" to user "Brian" using the Graph API
|
||||
And user "Alice" has created a folder ".space" in space "Project Jupiter"
|
||||
And user "Alice" has uploaded a file inside space "Project Jupiter" with content "" to ".space/spaceImage.jpeg"
|
||||
And user "Alice" has set the file ".space/spaceImage.jpeg" as a space image in a special section of the "Project Jupiter" space
|
||||
When user "Brian" lists all spaces via the Graph API
|
||||
And user "Alice" lists all available spaces via the Graph API with query "$filter=driveType eq 'project'"
|
||||
Then the HTTP status code should be "200"
|
||||
And the JSON response should contain space called "Project Jupiter" owned by "Alice" with space image ".space/spaceImage.png" and match
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"special"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"enum": ["Project Jupiter"]
|
||||
},
|
||||
"special": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"size",
|
||||
"name",
|
||||
"specialFolder",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "number",
|
||||
"enum": [0]
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"enum": ["spaceImage.jpeg"]
|
||||
},
|
||||
"specialFolder": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"enum": ["image"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"file": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mimeType"
|
||||
],
|
||||
"properties": {
|
||||
"mimeType": {
|
||||
"type": "string",
|
||||
"enum": ["image/jpeg"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
@env-config @skipOnOpencloud-decomposed-Storage @skipOnOpencloud-decomposeds3-Storage
|
||||
Feature: create a resources using collaborative posixfs
|
||||
|
||||
Background:
|
||||
Given the config "STORAGE_USERS_POSIX_WATCH_FS" has been set to "true"
|
||||
And user "Alice" has been created with default attributes
|
||||
|
||||
|
||||
Scenario: create folder
|
||||
Given user "Alice" has uploaded file with content "content" to "textfile.txt"
|
||||
When the administrator creates the folder "myFolder" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
When the administrator lists the content of the POSIX storage folder of user "Alice"
|
||||
Then the command output should contain "myFolder"
|
||||
And as "Alice" folder "/myFolder" should exist
|
||||
|
||||
|
||||
Scenario: create file
|
||||
Given user "Alice" has created folder "/folder"
|
||||
When the administrator creates the file "test.txt" with content "content" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
When the administrator lists the content of the POSIX storage folder of user "Alice"
|
||||
Then the command output should contain "test.txt"
|
||||
And the content of file "/test.txt" for user "Alice" should be "content"
|
||||
|
||||
|
||||
Scenario: edit file
|
||||
Given user "Alice" has uploaded file with content "content" to "test.txt"
|
||||
When the administrator puts the content "new" into the file "test.txt" in the POSIX storage folder of user "Alice"
|
||||
Then the content of file "/test.txt" for user "Alice" should be "contentnew"
|
||||
|
||||
|
||||
Scenario: read file content
|
||||
Given user "Alice" has uploaded file with content "content" to "textfile.txt"
|
||||
When the administrator reads the content of the file "textfile.txt" in the POSIX storage folder of user "Alice"
|
||||
Then the command output should contain "content"
|
||||
|
||||
|
||||
Scenario: copy file to folder
|
||||
Given user "Alice" has created folder "/folder"
|
||||
And user "Alice" has uploaded file with content "content" to "test.txt"
|
||||
When the administrator copies the file "test.txt" to the folder "folder" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And the content of file "/folder/test.txt" for user "Alice" should be "content"
|
||||
|
||||
|
||||
Scenario: move file to folder
|
||||
Given user "Alice" has created folder "/folder"
|
||||
And user "Alice" has uploaded file with content "content" to "test.txt"
|
||||
When the administrator moves the file "test.txt" to the folder "folder" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And the content of file "/folder/test.txt" for user "Alice" should be "content"
|
||||
And as "Alice" file "/test.txt" should not exist
|
||||
|
||||
|
||||
Scenario: delete file
|
||||
Given user "Alice" has uploaded file with content "content" to "test.txt"
|
||||
When the administrator deletes the file "test.txt" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And as "Alice" file "/test.txt" should not exist
|
||||
|
||||
|
||||
Scenario: delete folder
|
||||
Given user "Alice" has created folder "/folder"
|
||||
And user "Alice" has uploaded file with content "content" to "/folder/test.txt"
|
||||
When the administrator deletes the folder "folder" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And as "Alice" folder "folder" should not exist
|
||||
|
||||
|
||||
Scenario: copy file from personal to project space
|
||||
Given user "Alice" has uploaded file with content "content" to "test.txt"
|
||||
And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
|
||||
And user "Alice" has created a space "Project space" with the default quota using the Graph API
|
||||
When the administrator copies the file "test.txt" to the space "Project space" for user "Alice" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And using spaces DAV path
|
||||
And for user "Alice" the space "Project space" should contain these entries:
|
||||
| test.txt |
|
||||
|
||||
|
||||
Scenario: delete project space
|
||||
Given the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
|
||||
And user "Alice" has created a space "Project space" with the default quota using the Graph API
|
||||
When the administrator deletes the project space "Project space" on the POSIX filesystem
|
||||
Then the command should be successful
|
||||
And the user "Alice" should not have a space called "Project space"
|
||||
@@ -271,3 +271,36 @@ func RunCommand(command string, inputs []string) (int, string) {
|
||||
|
||||
return c.ProcessState.ExitCode(), cmdOutput
|
||||
}
|
||||
|
||||
func RunRawCommand(command string, inputs []string) (int, string) {
|
||||
logs := new(strings.Builder)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
fmt.Print("Running command: ", command)
|
||||
|
||||
c := exec.CommandContext(ctx, "bash", "-c", command)
|
||||
|
||||
ptyF, err := pty.Start(c)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
defer ptyF.Close()
|
||||
|
||||
for _, input := range inputs {
|
||||
fmt.Fprintf(ptyF, "%s\n", input)
|
||||
}
|
||||
|
||||
var cmdOutput string
|
||||
if err := c.Wait(); err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
cmdOutput = "Command timed out:\n"
|
||||
}
|
||||
}
|
||||
|
||||
io.Copy(logs, ptyF)
|
||||
cmdOutput += logs.String()
|
||||
cmdOutput = strings.TrimLeft(cmdOutput, strings.Join(inputs, "\r\n"))
|
||||
|
||||
return c.ProcessState.ExitCode(), cmdOutput
|
||||
}
|
||||
|
||||
@@ -198,7 +198,19 @@ func CommandHandler(res http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
raw := false
|
||||
if r, ok := body["raw"].(bool); ok {
|
||||
raw = r
|
||||
}
|
||||
|
||||
exitCode, output := opencloud.RunCommand(command, stdIn)
|
||||
var exitCode int
|
||||
var output string
|
||||
|
||||
|
||||
if raw {
|
||||
exitCode, output = opencloud.RunRawCommand(command, stdIn)
|
||||
} else {
|
||||
exitCode, output = opencloud.RunCommand(command, stdIn)
|
||||
}
|
||||
sendCmdResponse(res, exitCode, output)
|
||||
}
|
||||
|
||||
7
vendor/dario.cat/mergo/FUNDING.json
vendored
Normal file
7
vendor/dario.cat/mergo/FUNDING.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x6160020e7102237aC41bdb156e94401692D76930"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
vendor/dario.cat/mergo/README.md
vendored
5
vendor/dario.cat/mergo/README.md
vendored
@@ -85,7 +85,6 @@ Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/depend
|
||||
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
|
||||
* [grafana/loki](https://github.com/grafana/loki)
|
||||
* [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
||||
* [masterminds/sprig](github.com/Masterminds/sprig)
|
||||
* [moby/moby](https://github.com/moby/moby)
|
||||
* [slackhq/nebula](https://github.com/slackhq/nebula)
|
||||
@@ -191,10 +190,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Note: if test are failing due missing package, please execute:
|
||||
|
||||
go get gopkg.in/yaml.v3
|
||||
|
||||
### Transformers
|
||||
|
||||
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
|
||||
|
||||
4
vendor/dario.cat/mergo/SECURITY.md
vendored
4
vendor/dario.cat/mergo/SECURITY.md
vendored
@@ -4,8 +4,8 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.3.x | :white_check_mark: |
|
||||
| < 0.3 | :x: |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
| < 1.0 | :x: |
|
||||
|
||||
## Security contact information
|
||||
|
||||
|
||||
24
vendor/github.com/CiscoM31/godata/expression_parser.go
generated
vendored
24
vendor/github.com/CiscoM31/godata/expression_parser.go
generated
vendored
@@ -58,8 +58,9 @@ const (
|
||||
ExpressionTokenDuration // duration = [ "duration" ] SQUOTE durationValue SQUOTE
|
||||
ExpressionTokenGuid // [25] A 128-bit GUID
|
||||
ExpressionTokenAssignement // The '=' assignement for function arguments.
|
||||
ExpressionTokenGeographyPolygon //
|
||||
ExpressionTokenGeometryPolygon //
|
||||
ExpressionTokenGeographyPolygon // A polygon with geodetic (ie spherical) coordinates. Parsed Token.Value is '<long> <lat>,<long> <lat>...'
|
||||
ExpressionTokenGeometryPolygon // A polygon with planar (ie cartesian) coordinates. Parsed Token.Value is '<long> <lat>,<long> <lat>...'
|
||||
ExpressionTokenGeographyPoint // A geodetic coordinate point. Parsed Token.Value is '<long> <lat>'
|
||||
expressionTokenLast
|
||||
)
|
||||
|
||||
@@ -94,6 +95,7 @@ func (e ExpressionTokenType) String() string {
|
||||
"ExpressionTokenAssignement",
|
||||
"ExpressionTokenGeographyPolygon",
|
||||
"ExpressionTokenGeometryPolygon",
|
||||
"ExpressionTokenGeographyPoint",
|
||||
"expressionTokenLast",
|
||||
}[e]
|
||||
}
|
||||
@@ -178,15 +180,11 @@ func NewExpressionTokenizer() *Tokenizer {
|
||||
// E.g. ABNF for 'geo.distance':
|
||||
// distanceMethodCallExpr = "geo.distance" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
|
||||
t.Add("(?i)^(?P<token>(geo.distance|geo.intersects|geo.length))[\\s(]", ExpressionTokenFunc)
|
||||
// geographyPolygon = geographyPrefix SQUOTE fullPolygonLiteral SQUOTE
|
||||
// fullPolygonLiteral = sridLiteral polygonLiteral
|
||||
// sridLiteral = "SRID" EQ 1*5DIGIT SEMI
|
||||
// polygonLiteral = "Polygon" polygonData
|
||||
// polygonData = OPEN ringLiteral *( COMMA ringLiteral ) CLOSE
|
||||
// Example: geography'SRID=0;Polygon((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581))'
|
||||
t.Add(`^geography'SRID=[0-9]{1,5};Polygon\(\((-?[0-9]+\.[0-9]+\s+-?[0-9]+\.[0-9]+)(,\s-?[0-9]+\.[0-9]+\s+-?[0-9]+\.[0-9]+)*\)\)'`, ExpressionTokenGeographyPolygon)
|
||||
// geometryPolygon = geometryPrefix SQUOTE fullPolygonLiteral SQUOTE
|
||||
t.Add(`^geometry'SRID=[0-9]{1,5};Polygon\(\((-?[0-9]+\.[0-9]+\s+-?[0-9]+\.[0-9]+)(,\s-?[0-9]+\.[0-9]+\s+-?[0-9]+\.[0-9]+)*\)\)'`, ExpressionTokenGeometryPolygon)
|
||||
// Example: geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581))'
|
||||
t.Add(`(?i)^geography'(?:SRID=(\d{1,5});)?POLYGON\s*\(\(\s*(?P<subtoken>-?\d+(\.\d+)?\s+-?\d+(\.\d+)?(?:\s*,\s*-?\d+(\.\d+)?\s+-?\d+(\.\d+)?)*?)\s*\)\)'`, ExpressionTokenGeographyPolygon)
|
||||
t.Add(`(?i)^geometry'(?:SRID=(\d{1,5});)?POLYGON\s*\(\(\s*(?P<subtoken>-?\d+(\.\d+)?\s+-?\d+(\.\d+)?(?:\s*,\s*-?\d+(\.\d+)?\s+-?\d+(\.\d+)?)*?)\s*\)\)'`, ExpressionTokenGeometryPolygon)
|
||||
// Example: geography'POINT(-122.131577 47.678581)'
|
||||
t.Add(`(?i)^geography'POINT\s*\(\s*(?P<subtoken>-?\d+(\.\d+)?\s+-?\d+(\.\d+)?)\s*\)'`, ExpressionTokenGeographyPoint)
|
||||
// According to ODATA ABNF notation, functions must be followed by a open parenthesis with no space
|
||||
// between the function name and the open parenthesis.
|
||||
// However, we are leniently allowing space characters between the function and the open parenthesis.
|
||||
@@ -315,7 +313,7 @@ func NewExpressionParser() *ExpressionParser {
|
||||
// Edm.Boolean geo.intersects(Edm.GeometryPoint,Edm.GeometryPolygon)
|
||||
// The geo.intersects function returns true if the specified point lies within the interior
|
||||
// or on the boundary of the specified polygon, otherwise it returns false.
|
||||
parser.DefineFunction("geo.intersects", []int{2}, false)
|
||||
parser.DefineFunction("geo.intersects", []int{2}, true)
|
||||
// The geo.length function has the following signatures:
|
||||
// Edm.Double geo.length(Edm.GeographyLineString)
|
||||
// Edm.Double geo.length(Edm.GeometryLineString)
|
||||
@@ -329,7 +327,7 @@ func NewExpressionParser() *ExpressionParser {
|
||||
parser.DefineFunction("all", []int{2}, true)
|
||||
// Define 'case' as a function accepting 1-10 arguments. Each argument is a pair of expressions separated by a colon.
|
||||
// See https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_case
|
||||
parser.DefineFunction("case", []int{1,2,3,4,5,6,7,8,9,10}, true)
|
||||
parser.DefineFunction("case", []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, true)
|
||||
|
||||
return parser
|
||||
}
|
||||
|
||||
3
vendor/github.com/CiscoM31/godata/filter_parser.go
generated
vendored
3
vendor/github.com/CiscoM31/godata/filter_parser.go
generated
vendored
@@ -21,8 +21,7 @@ func ParseFilterString(ctx context.Context, filter string) (*GoDataFilterQuery,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tree == nil || tree.Token == nil ||
|
||||
(len(tree.Children) == 0 && tree.Token.Type != ExpressionTokenBoolean) {
|
||||
if tree == nil || tree.Token == nil || !GlobalFilterParser.isBooleanExpression(tree.Token) {
|
||||
return nil, BadRequestError("Value must be a boolean expression")
|
||||
}
|
||||
return &GoDataFilterQuery{tree, filter}, nil
|
||||
|
||||
4
vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go
generated
vendored
4
vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go
generated
vendored
@@ -276,11 +276,9 @@ func parseMountInfoLine(line string) (mountInfo, error) {
|
||||
fields1 = append(fields1, "")
|
||||
}
|
||||
|
||||
fields2 := strings.Split(fieldss[1], " ")
|
||||
fields2 := strings.SplitN(fieldss[1], " ", 3)
|
||||
if len(fields2) < 3 {
|
||||
return mountInfo{}, fmt.Errorf("not enough fields after separator: %v", fields2)
|
||||
} else if len(fields2) > 3 {
|
||||
return mountInfo{}, fmt.Errorf("too many fields after separator: %v", fields2)
|
||||
}
|
||||
|
||||
return mountInfo{
|
||||
|
||||
1
vendor/github.com/beevik/etree/CONTRIBUTORS
generated
vendored
1
vendor/github.com/beevik/etree/CONTRIBUTORS
generated
vendored
@@ -12,3 +12,4 @@ Martin Dosch (mdosch)
|
||||
Hugo Wetterberg (hugowetterberg)
|
||||
Tobias Theel (nerzal)
|
||||
Daniel Potapov (dpotapov)
|
||||
Mikhail Ferapontow (MikhailFerapontow)
|
||||
|
||||
7
vendor/github.com/beevik/etree/RELEASE_NOTES.md
generated
vendored
7
vendor/github.com/beevik/etree/RELEASE_NOTES.md
generated
vendored
@@ -1,3 +1,10 @@
|
||||
Release 1.5.1
|
||||
=============
|
||||
|
||||
**Fixes**
|
||||
|
||||
* Fixed a bug in `InsertChildAt`.
|
||||
|
||||
Release 1.5.0
|
||||
=============
|
||||
|
||||
|
||||
2
vendor/github.com/beevik/etree/etree.go
generated
vendored
2
vendor/github.com/beevik/etree/etree.go
generated
vendored
@@ -831,7 +831,7 @@ func (e *Element) InsertChildAt(index int, t Token) {
|
||||
}
|
||||
|
||||
if t.Parent() != nil {
|
||||
if t.Parent() == e && t.Index() > index {
|
||||
if t.Parent() == e && t.Index() < index {
|
||||
index--
|
||||
}
|
||||
t.Parent().RemoveChild(t)
|
||||
|
||||
55
vendor/github.com/goccy/go-yaml/decode.go
generated
vendored
55
vendor/github.com/goccy/go-yaml/decode.go
generated
vendored
@@ -7,7 +7,6 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -16,11 +15,12 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/internal/errors"
|
||||
"github.com/goccy/go-yaml/parser"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Decoder reads and decodes YAML values from an input stream.
|
||||
@@ -488,6 +488,21 @@ func (d *Decoder) fileToNode(f *ast.File) ast.Node {
|
||||
func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) {
|
||||
if typ.Kind() != reflect.String {
|
||||
if !v.Type().ConvertibleTo(typ) {
|
||||
|
||||
// Special case for "strings -> floats" aka scientific notation
|
||||
// If the destination type is a float and the source type is a string, check if we can
|
||||
// use strconv.ParseFloat to convert the string to a float.
|
||||
if (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) &&
|
||||
v.Type().Kind() == reflect.String {
|
||||
if f, err := strconv.ParseFloat(v.String(), 64); err == nil {
|
||||
if typ.Kind() == reflect.Float32 {
|
||||
return reflect.ValueOf(float32(f)), nil
|
||||
} else if typ.Kind() == reflect.Float64 {
|
||||
return reflect.ValueOf(f), nil
|
||||
}
|
||||
// else, fall through to the error below
|
||||
}
|
||||
}
|
||||
return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken())
|
||||
}
|
||||
return v.Convert(typ), nil
|
||||
@@ -877,6 +892,15 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
|
||||
dst.SetInt(int64(vv))
|
||||
return nil
|
||||
}
|
||||
case string: // handle scientific notation
|
||||
if i, err := strconv.ParseFloat(vv, 64); err == nil {
|
||||
if 0 <= i && i <= math.MaxUint64 && !dst.OverflowInt(int64(i)) {
|
||||
dst.SetInt(int64(i))
|
||||
return nil
|
||||
}
|
||||
} else { // couldn't be parsed as float
|
||||
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
|
||||
}
|
||||
default:
|
||||
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
|
||||
}
|
||||
@@ -899,6 +923,16 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
|
||||
dst.SetUint(uint64(vv))
|
||||
return nil
|
||||
}
|
||||
case string: // handle scientific notation
|
||||
if i, err := strconv.ParseFloat(vv, 64); err == nil {
|
||||
if 0 <= i && i <= math.MaxUint64 && !dst.OverflowUint(uint64(i)) {
|
||||
dst.SetUint(uint64(i))
|
||||
return nil
|
||||
}
|
||||
} else { // couldn't be parsed as float
|
||||
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
|
||||
}
|
||||
|
||||
default:
|
||||
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
|
||||
}
|
||||
@@ -1501,10 +1535,19 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node
|
||||
}
|
||||
continue
|
||||
}
|
||||
k := reflect.ValueOf(d.nodeToValue(key))
|
||||
if k.IsValid() && k.Type().ConvertibleTo(keyType) {
|
||||
k = k.Convert(keyType)
|
||||
|
||||
k := d.createDecodableValue(keyType)
|
||||
if d.canDecodeByUnmarshaler(k) {
|
||||
if err := d.decodeByUnmarshaler(ctx, k, key); err != nil {
|
||||
return errors.Wrapf(err, "failed to decode by unmarshaler")
|
||||
}
|
||||
} else {
|
||||
k = reflect.ValueOf(d.nodeToValue(key))
|
||||
if k.IsValid() && k.Type().ConvertibleTo(keyType) {
|
||||
k = k.Convert(keyType)
|
||||
}
|
||||
}
|
||||
|
||||
if k.IsValid() {
|
||||
if err := d.validateDuplicateKey(keyMap, k.Interface(), key); err != nil {
|
||||
return errors.Wrapf(err, "invalid map key")
|
||||
@@ -1621,7 +1664,7 @@ func (d *Decoder) resolveReference() error {
|
||||
}
|
||||
}
|
||||
for _, reader := range d.referenceReaders {
|
||||
bytes, err := ioutil.ReadAll(reader)
|
||||
bytes, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read buffer")
|
||||
}
|
||||
|
||||
4
vendor/github.com/goccy/go-yaml/parser/parser.go
generated
vendored
4
vendor/github.com/goccy/go-yaml/parser/parser.go
generated
vendored
@@ -2,7 +2,7 @@ package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
@@ -730,7 +730,7 @@ func Parse(tokens token.Tokens, mode Mode) (*ast.File, error) {
|
||||
|
||||
// Parse parse from filename, and returns ast.File
|
||||
func ParseFile(filename string, mode Mode) (*ast.File, error) {
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
file, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read file: %s", filename)
|
||||
}
|
||||
|
||||
2
vendor/github.com/goccy/go-yaml/path.go
generated
vendored
2
vendor/github.com/goccy/go-yaml/path.go
generated
vendored
@@ -468,7 +468,7 @@ func (n *rootNode) String() string {
|
||||
|
||||
func (n *rootNode) filter(node ast.Node) (ast.Node, error) {
|
||||
if n.child == nil {
|
||||
return nil, nil
|
||||
return node, nil
|
||||
}
|
||||
filtered, err := n.child.filter(node)
|
||||
if err != nil {
|
||||
|
||||
13
vendor/github.com/goccy/go-yaml/scanner/context.go
generated
vendored
13
vendor/github.com/goccy/go-yaml/scanner/context.go
generated
vendored
@@ -196,9 +196,16 @@ func (c *Context) existsBuffer() bool {
|
||||
|
||||
func (c *Context) bufferedSrc() []rune {
|
||||
src := c.buf[:c.notSpaceCharPos]
|
||||
if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" {
|
||||
// remove end '\n' character
|
||||
src = src[:len(src)-1]
|
||||
if c.isDocument() && c.literalOpt == "-" {
|
||||
// remove end '\n' character and trailing empty lines
|
||||
// https://yaml.org/spec/1.2.2/#8112-block-chomping-indicator
|
||||
for {
|
||||
if len(src) > 0 && src[len(src)-1] == '\n' {
|
||||
src = src[:len(src)-1]
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
201
vendor/github.com/goccy/go-yaml/scanner/scanner.go
generated
vendored
201
vendor/github.com/goccy/go-yaml/scanner/scanner.go
generated
vendored
@@ -4,8 +4,9 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
// IndentState state for indent
|
||||
@@ -316,100 +317,93 @@ func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) {
|
||||
continue
|
||||
} else if c == '\\' {
|
||||
isFirstLineChar = false
|
||||
if idx+1 < size {
|
||||
nextChar := src[idx+1]
|
||||
switch nextChar {
|
||||
case 'b':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\b')
|
||||
idx++
|
||||
continue
|
||||
case 'e':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\x1B')
|
||||
idx++
|
||||
continue
|
||||
case 'f':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\f')
|
||||
idx++
|
||||
continue
|
||||
case 'n':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\n')
|
||||
idx++
|
||||
continue
|
||||
case 'r':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\r')
|
||||
idx++
|
||||
continue
|
||||
case 'v':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\v')
|
||||
idx++
|
||||
continue
|
||||
case 'L': // LS (#x2028)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA8'}...)
|
||||
idx++
|
||||
continue
|
||||
case 'N': // NEL (#x85)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\x85'}...)
|
||||
idx++
|
||||
continue
|
||||
case 'P': // PS (#x2029)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA9'}...)
|
||||
idx++
|
||||
continue
|
||||
case '_': // #xA0
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\xA0'}...)
|
||||
idx++
|
||||
continue
|
||||
case '"':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, nextChar)
|
||||
idx++
|
||||
continue
|
||||
case 'x':
|
||||
if idx+3 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\x")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+4])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 3
|
||||
continue
|
||||
case 'u':
|
||||
if idx+5 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\u")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+6])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 5
|
||||
continue
|
||||
case 'U':
|
||||
if idx+9 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\U")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+10])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 9
|
||||
continue
|
||||
case '\\':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
idx++
|
||||
}
|
||||
if idx+1 >= size {
|
||||
value = append(value, c)
|
||||
continue
|
||||
}
|
||||
value = append(value, c)
|
||||
nextChar := src[idx+1]
|
||||
progress := 0
|
||||
switch nextChar {
|
||||
case 'b':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\b')
|
||||
case 'e':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\x1B')
|
||||
case 'f':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\f')
|
||||
case 'n':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\n')
|
||||
case 'r':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\r')
|
||||
case 'v':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\v')
|
||||
case 'L': // LS (#x2028)
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA8'}...)
|
||||
case 'N': // NEL (#x85)
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\x85'}...)
|
||||
case 'P': // PS (#x2029)
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA9'}...)
|
||||
case '_': // #xA0
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\xA0'}...)
|
||||
case '"':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, nextChar)
|
||||
case 'x':
|
||||
progress = 3
|
||||
if idx+progress >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\x")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+progress+1])
|
||||
value = append(value, rune(codeNum))
|
||||
case 'u':
|
||||
progress = 5
|
||||
if idx+progress >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\u")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+progress+1])
|
||||
value = append(value, rune(codeNum))
|
||||
case 'U':
|
||||
progress = 9
|
||||
if idx+progress >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\U")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+progress+1])
|
||||
value = append(value, rune(codeNum))
|
||||
case '\\':
|
||||
progress = 1
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, c)
|
||||
default:
|
||||
value = append(value, c)
|
||||
}
|
||||
idx += progress
|
||||
s.progressColumn(ctx, progress)
|
||||
continue
|
||||
} else if c != '"' {
|
||||
value = append(value, c)
|
||||
@@ -621,6 +615,16 @@ func (s *Scanner) scanNewLine(ctx *Context, c rune) {
|
||||
}
|
||||
}
|
||||
|
||||
// There is no problem that we ignore CR which followed by LF and normalize it to LF, because of following YAML1.2 spec.
|
||||
// > Line breaks inside scalar content must be normalized by the YAML processor. Each such line break must be parsed into a single line feed character.
|
||||
// > Outside scalar content, YAML allows any line break to be used to terminate lines.
|
||||
// > -- https://yaml.org/spec/1.2/spec.html
|
||||
if c == '\r' && ctx.nextChar() == '\n' {
|
||||
ctx.addOriginBuf('\r')
|
||||
ctx.progress(1)
|
||||
c = '\n'
|
||||
}
|
||||
|
||||
if ctx.isEOS() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
} else if s.isAnchor {
|
||||
@@ -840,15 +844,6 @@ func (s *Scanner) scan(ctx *Context) (pos int) {
|
||||
return
|
||||
}
|
||||
case '\r', '\n':
|
||||
// There is no problem that we ignore CR which followed by LF and normalize it to LF, because of following YAML1.2 spec.
|
||||
// > Line breaks inside scalar content must be normalized by the YAML processor. Each such line break must be parsed into a single line feed character.
|
||||
// > Outside scalar content, YAML allows any line break to be used to terminate lines.
|
||||
// > -- https://yaml.org/spec/1.2/spec.html
|
||||
if c == '\r' && ctx.nextChar() == '\n' {
|
||||
ctx.addOriginBuf('\r')
|
||||
ctx.progress(1)
|
||||
c = '\n'
|
||||
}
|
||||
s.scanNewLine(ctx, c)
|
||||
continue
|
||||
case ' ':
|
||||
|
||||
2
vendor/github.com/goccy/go-yaml/token/token.go
generated
vendored
2
vendor/github.com/goccy/go-yaml/token/token.go
generated
vendored
@@ -623,7 +623,7 @@ func IsNeedQuoted(value string) bool {
|
||||
}
|
||||
first := value[0]
|
||||
switch first {
|
||||
case '*', '&', '[', '{', '}', ']', ',', '!', '|', '>', '%', '\'', '"', '@', ' ':
|
||||
case '*', '&', '[', '{', '}', ']', ',', '!', '|', '>', '%', '\'', '"', '@', ' ', '`':
|
||||
return true
|
||||
}
|
||||
last := value[len(value)-1]
|
||||
|
||||
65
vendor/github.com/gookit/config/v2/README.md
generated
vendored
65
vendor/github.com/gookit/config/v2/README.md
generated
vendored
@@ -231,15 +231,57 @@ name = config.String("name")
|
||||
fmt.Print(name) // "new name"
|
||||
```
|
||||
|
||||
## Load from flags
|
||||
## Load from ENV
|
||||
|
||||
> Support simple flags parameter parsing, loading
|
||||
Support load ENV vars to config data.
|
||||
|
||||
- Support set value to sub key in map.
|
||||
- eg: `{"DB_USERNAME": "db.username"}` value will set to `username` in `db`
|
||||
|
||||
```go
|
||||
// flags like: --name inhere --env dev --age 99 --debug
|
||||
// os env: APP_NAME=config APP_DEBUG=true DB_USERNAME=someone
|
||||
|
||||
// load ENV info
|
||||
config.LoadOSEnvs(map[string]string{"APP_NAME": "app_name", "APP_DEBUG": "app_debug", "DB_USERNAME": "db.username"})
|
||||
|
||||
// read
|
||||
config.Bool("app_debug") // true
|
||||
config.String("app_name") // "config"
|
||||
```
|
||||
|
||||
## Load from flags
|
||||
|
||||
Support simple CLI flags parameter parsing, load to config data.
|
||||
|
||||
- define format: `name:type:desc` OR `name:type` OR `name:desc` (type, desc is optional)
|
||||
- `type` can set `flag` type. allow: `bool`, `int`, `string`(default)
|
||||
- `desc` can set `flag` description
|
||||
- `name` can be in key path format.
|
||||
- eg: `db.username`, input: `--db.username=someone` values will be mapped to `username` of the `db` configuration
|
||||
|
||||
```go
|
||||
// 'debug' flag is bool type
|
||||
config.LoadFlags([]string{"env", "debug:bool"})
|
||||
// can with flag desc message
|
||||
config.LoadFlags([]string{"env:set the run env"})
|
||||
config.LoadFlags([]string{"debug:bool:set debug mode"})
|
||||
// can set value to map key. eg: myapp --map1.sub-key=val
|
||||
config.LoadFlags([]string{"map1.sub-key"})
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```go
|
||||
// flags like: --name inhere --env dev --age 99 --debug --map1.sub-key=val
|
||||
|
||||
// load flag info
|
||||
keys := []string{"name", "env", "age:int" "debug:bool"}
|
||||
keys := []string{
|
||||
"name",
|
||||
"env:set the run env",
|
||||
"age:int",
|
||||
"debug:bool:set debug mode",
|
||||
"map1.sub-key",
|
||||
}
|
||||
err := config.LoadFlags(keys)
|
||||
|
||||
// read
|
||||
@@ -247,18 +289,7 @@ config.String("name") // "inhere"
|
||||
config.String("env") // "dev"
|
||||
config.Int("age") // 99
|
||||
config.Bool("debug") // true
|
||||
```
|
||||
|
||||
## Load from ENV
|
||||
|
||||
```go
|
||||
// os env: APP_NAME=config APP_DEBUG=true
|
||||
// load ENV info
|
||||
config.LoadOSEnvs(map[string]string{"APP_NAME": "app_name", "APP_DEBUG": "app_debug"})
|
||||
|
||||
// read
|
||||
config.Bool("app_debug") // true
|
||||
config.String("app_name") // "config"
|
||||
config.Get("map1") // map[string]any{"sub-key":"val"}
|
||||
```
|
||||
|
||||
## New config instance
|
||||
@@ -377,6 +408,8 @@ type Options struct {
|
||||
}
|
||||
```
|
||||
|
||||
> **TIP**: please visit https://pkg.go.dev/github.com/gookit/config/v2#Options to see the latest options information
|
||||
|
||||
Examples for set options:
|
||||
|
||||
```go
|
||||
|
||||
45
vendor/github.com/gookit/config/v2/README.zh-CN.md
generated
vendored
45
vendor/github.com/gookit/config/v2/README.zh-CN.md
generated
vendored
@@ -220,8 +220,19 @@ name = config.String("name")
|
||||
fmt.Print(name) // new name
|
||||
```
|
||||
|
||||
## 加载配置文件
|
||||
|
||||
- `LoadExists(sourceFiles ...string) (err error)` 从存在的配置文件里加载数据,会忽略不存在的文件
|
||||
- `LoadFiles(sourceFiles ...string) (err error)` 从给定的配置文件里加载数据,有文件不存在则会panic
|
||||
|
||||
> **TIP**: 更多加载方式请查看 `config.Load*` 相关方法
|
||||
|
||||
## 从ENV载入数据
|
||||
|
||||
`LoadOSEnvs` 支持从环境变量中读取数据,并解析为配置数据。格式为 `ENV_NAME: config_key`
|
||||
|
||||
- `config_key` 可以是 key path 格式。 eg: `{"DB_USERNAME": "db.username"}` 值将会映射到 `db` 配置的 `username`
|
||||
|
||||
```go
|
||||
// os env: APP_NAME=config APP_DEBUG=true
|
||||
// load ENV info
|
||||
@@ -234,13 +245,36 @@ config.String("app_name") // "config"
|
||||
|
||||
## 从命令行参数载入数据
|
||||
|
||||
支持简单的从命令行 `flag` 参数解析,加载数据
|
||||
支持简单的从命令行 `flag` 参数解析,加载数据。
|
||||
|
||||
- 配置参数格式为 `name:type:desc` OR `name:type` OR `name:desc` (type, desc 是可选的)
|
||||
- `type` 可以设置 `flag` 的类型,支持 `bool`, `int`, `string`(默认)
|
||||
- `desc` 可以设置 `flag` 的描述信息
|
||||
- `name` 可以是 key path 格式。 eg: `db.username`, input: `--db.username=someone` 值将会映射到 `db` 配置的 `username`
|
||||
|
||||
```go
|
||||
// flags like: --name inhere --env dev --age 99 --debug
|
||||
// 'debug' flag is bool type
|
||||
config.LoadFlags([]string{"env", "debug:bool"})
|
||||
// can with flag desc message
|
||||
config.LoadFlags([]string{"env:set the run env"})
|
||||
config.LoadFlags([]string{"debug:bool:set debug mode"})
|
||||
// can set value to map key. eg: myapp --map1.sub-key=val
|
||||
config.LoadFlags([]string{"map1.sub-key"})
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```go
|
||||
// flags like: --name inhere --env dev --age 99 --debug --map1.sub-key=val
|
||||
|
||||
// load flag info
|
||||
keys := []string{"name", "env", "age:int" "debug:bool"}
|
||||
keys := []string{
|
||||
"name",
|
||||
"env:set the run env",
|
||||
"age:int",
|
||||
"debug:bool:set debug mode",
|
||||
"map1.sub-key",
|
||||
}
|
||||
err := config.LoadFlags(keys)
|
||||
|
||||
// read
|
||||
@@ -248,6 +282,7 @@ config.String("name") // "inhere"
|
||||
config.String("env") // "dev"
|
||||
config.Int("age") // 99
|
||||
config.Bool("debug") // true
|
||||
config.Get("map1") // map[string]any{"sub-key":"val"}
|
||||
```
|
||||
|
||||
## 创建自定义实例
|
||||
@@ -366,6 +401,8 @@ type Options struct {
|
||||
}
|
||||
```
|
||||
|
||||
> **提示**: 访问 https://pkg.go.dev/github.com/gookit/config/v2#Options 查看最新的选项信息
|
||||
|
||||
Examples for set options:
|
||||
|
||||
```go
|
||||
@@ -417,7 +454,7 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
|
||||
- `LoadData(dataSource ...any) (err error)` 从struct或map加载数据
|
||||
- `LoadFlags(keys []string) (err error)` 从命令行参数载入数据
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` 从ENV载入数据
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` 从ENV载入配置数据
|
||||
- `LoadExists(sourceFiles ...string) (err error)` 从存在的配置文件里加载数据,会忽略不存在的文件
|
||||
- `LoadFiles(sourceFiles ...string) (err error)` 从给定的配置文件里加载数据,有文件不存在则会panic
|
||||
- `LoadFromDir(dirPath, format string) (err error)` 从给定目录里加载自定格式的文件,文件名会作为 key
|
||||
|
||||
7
vendor/github.com/gookit/config/v2/config.go
generated
vendored
7
vendor/github.com/gookit/config/v2/config.go
generated
vendored
@@ -116,6 +116,13 @@ func New(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name, opts...).WithDriver(JSONDriver)
|
||||
}
|
||||
|
||||
// NewGeneric create generic config instance with custom options.
|
||||
//
|
||||
// - default add options: ParseEnv, ParseDefault, ParseTime
|
||||
func NewGeneric(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name, ParseEnv, ParseDefault, ParseTime).WithOptions(opts...).WithDriver(JSONDriver)
|
||||
}
|
||||
|
||||
// NewEmpty create config instance with custom options
|
||||
func NewEmpty(name string, opts ...OptionFn) *Config {
|
||||
c := &Config{
|
||||
|
||||
41
vendor/github.com/gookit/config/v2/load.go
generated
vendored
41
vendor/github.com/gookit/config/v2/load.go
generated
vendored
@@ -108,18 +108,19 @@ func (c *Config) LoadOSEnv(keys []string, keyToLower bool) {
|
||||
c.fireHook(OnLoadData)
|
||||
}
|
||||
|
||||
// LoadOSEnvs load data from OS ENVs. format: {ENV_NAME: config_key}
|
||||
// LoadOSEnvs load data from OS ENVs. see Config.LoadOSEnvs
|
||||
func LoadOSEnvs(nameToKeyMap map[string]string) { dc.LoadOSEnvs(nameToKeyMap) }
|
||||
|
||||
// LoadOSEnvs load data from os ENVs. format: {ENV_NAME: config_key}
|
||||
// LoadOSEnvs load data from os ENVs. format: `{ENV_NAME: config_key}`
|
||||
//
|
||||
// - `config_key` allow use key path. eg: `{"DB_USERNAME": "db.username"}`
|
||||
func (c *Config) LoadOSEnvs(nameToKeyMap map[string]string) {
|
||||
for name, key := range nameToKeyMap {
|
||||
for name, cfgKey := range nameToKeyMap {
|
||||
if val := os.Getenv(name); val != "" {
|
||||
if key == "" {
|
||||
key = strings.ToLower(name)
|
||||
if cfgKey == "" {
|
||||
cfgKey = strings.ToLower(name)
|
||||
}
|
||||
|
||||
_ = c.Set(key, val)
|
||||
_ = c.Set(cfgKey, val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,8 +136,8 @@ var validTypes = map[string]int{
|
||||
"string": 1,
|
||||
}
|
||||
|
||||
// LoadFlags load data from cli flags
|
||||
func LoadFlags(keys []string) error { return dc.LoadFlags(keys) }
|
||||
// LoadFlags load data from cli flags. see Config.LoadFlags
|
||||
func LoadFlags(defines []string) error { return dc.LoadFlags(defines) }
|
||||
|
||||
// LoadFlags parse command line arguments, based on provide keys.
|
||||
//
|
||||
@@ -144,13 +145,20 @@ func LoadFlags(keys []string) error { return dc.LoadFlags(keys) }
|
||||
//
|
||||
// // 'debug' flag is bool type
|
||||
// c.LoadFlags([]string{"env", "debug:bool"})
|
||||
func (c *Config) LoadFlags(keys []string) (err error) {
|
||||
// // can with flag desc message
|
||||
// c.LoadFlags([]string{"env:set the run env"})
|
||||
// c.LoadFlags([]string{"debug:bool:set debug mode"})
|
||||
// // can set value to map key. eg: myapp --map1.sub-key=val
|
||||
// c.LoadFlags([]string{"--map1.sub-key"})
|
||||
func (c *Config) LoadFlags(defines []string) (err error) {
|
||||
hash := map[string]int8{}
|
||||
|
||||
// bind vars
|
||||
for _, key := range keys {
|
||||
key, typ := parseVarNameAndType(key)
|
||||
desc := "config flag " + key
|
||||
for _, str := range defines {
|
||||
key, typ, desc := parseVarNameAndType(str)
|
||||
if desc == "" {
|
||||
desc = "config flag " + key
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case "int":
|
||||
@@ -181,7 +189,12 @@ func (c *Config) LoadFlags(keys []string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
_ = c.Set(name, f.Value.String()) // ignore error
|
||||
// if f.Value implement the flag.Getter, read typed value
|
||||
if gtr, ok := f.Value.(flag.Getter); ok {
|
||||
_ = c.Set(name, gtr.Get())
|
||||
// } else { // TIP: basic type flag always implements Getter interface
|
||||
// _ = c.Set(name, f.Value.String()) // ignore error
|
||||
}
|
||||
})
|
||||
|
||||
c.fireHook(OnLoadData)
|
||||
|
||||
33
vendor/github.com/gookit/config/v2/options.go
generated
vendored
33
vendor/github.com/gookit/config/v2/options.go
generated
vendored
@@ -22,35 +22,44 @@ type HookFunc func(event string, c *Config)
|
||||
|
||||
// Options config options
|
||||
type Options struct {
|
||||
// ParseEnv parse env in string value and default value. like: "${EnvName}" "${EnvName|default}"
|
||||
// ParseEnv parse env in string value and default value. default: false
|
||||
//
|
||||
// - like: "${EnvName}" "${EnvName|default}"
|
||||
ParseEnv bool
|
||||
// ParseTime parses a duration string to time.Duration
|
||||
// ParseTime parses a duration string to `time.Duration`. default: false
|
||||
//
|
||||
// eg: 10s, 2m
|
||||
ParseTime bool
|
||||
// Readonly config is readonly
|
||||
Readonly bool
|
||||
// ParseDefault tag on binding data to struct. tag: default
|
||||
// ParseDefault tag on binding data to struct. default: false
|
||||
//
|
||||
// - tag: default
|
||||
ParseDefault bool
|
||||
// EnableCache enable config data cache
|
||||
// Readonly config is readonly. default: false
|
||||
Readonly bool
|
||||
// EnableCache enable config data cache. default: false
|
||||
EnableCache bool
|
||||
// ParseKey parse key path, allow find value by key path. eg: 'key.sub' will find `map[key]sub`
|
||||
// ParseKey support key path, allow find value by key path. default: true
|
||||
//
|
||||
// - eg: 'key.sub' will find `map[key]sub`
|
||||
ParseKey bool
|
||||
// TagName tag name for binding data to struct
|
||||
//
|
||||
// Deprecated: please set tag name by DecoderConfig, or use SetTagName()
|
||||
TagName string
|
||||
// Delimiter the delimiter char for split key path, if `FindByPath=true`. default is '.'
|
||||
// Delimiter the delimiter char for split key path, on `ParseKey=true`.
|
||||
//
|
||||
// - default is '.'
|
||||
Delimiter byte
|
||||
// DumpFormat default write format
|
||||
// DumpFormat default write format. default is 'json'
|
||||
DumpFormat string
|
||||
// ReadFormat default input format
|
||||
// ReadFormat default input format. default is 'json'
|
||||
ReadFormat string
|
||||
// DecoderConfig setting for binding data to struct. such as: TagName
|
||||
DecoderConfig *mapstructure.DecoderConfig
|
||||
// HookFunc on data changed. you can do something...
|
||||
HookFunc HookFunc
|
||||
// MergeOptions settings for merge two data
|
||||
MergeOptions []func(*mergo.Config)
|
||||
// HookFunc on data changed. you can do something...
|
||||
HookFunc HookFunc
|
||||
// WatchChange bool
|
||||
}
|
||||
|
||||
|
||||
17
vendor/github.com/gookit/config/v2/read.go
generated
vendored
17
vendor/github.com/gookit/config/v2/read.go
generated
vendored
@@ -99,10 +99,10 @@ func (c *Config) Data() map[string]any {
|
||||
return c.data
|
||||
}
|
||||
|
||||
// Sub return sub config data by key
|
||||
// Sub return a map config data by key
|
||||
func Sub(key string) map[string]any { return dc.Sub(key) }
|
||||
|
||||
// Sub get sub config data by key
|
||||
// Sub get a map config data by key
|
||||
//
|
||||
// Note: will don't apply any options, like ParseEnv
|
||||
func (c *Config) Sub(key string) map[string]any {
|
||||
@@ -127,23 +127,24 @@ func (c *Config) Keys() []string {
|
||||
}
|
||||
|
||||
// Get config value by key string, support get sub-value by key path(eg. 'map.key'),
|
||||
//
|
||||
// - ok is true, find value from config
|
||||
// - ok is false, not found or error
|
||||
func Get(key string, findByPath ...bool) any { return dc.Get(key, findByPath...) }
|
||||
|
||||
// Get config value by key
|
||||
// Get config value by key, findByPath default is true.
|
||||
func (c *Config) Get(key string, findByPath ...bool) any {
|
||||
val, _ := c.GetValue(key, findByPath...)
|
||||
return val
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
// GetValue get value by given key string. findByPath default is true.
|
||||
func GetValue(key string, findByPath ...bool) (any, bool) {
|
||||
return dc.GetValue(key, findByPath...)
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
// GetValue get value by given key string. findByPath default is true.
|
||||
//
|
||||
// Return:
|
||||
// - ok is true, find value from config
|
||||
// - ok is false, not found or error
|
||||
func (c *Config) GetValue(key string, findByPath ...bool) (value any, ok bool) {
|
||||
sep := c.opts.Delimiter
|
||||
if key = formatKey(key, string(sep)); key == "" {
|
||||
|
||||
14
vendor/github.com/gookit/config/v2/util.go
generated
vendored
14
vendor/github.com/gookit/config/v2/util.go
generated
vendored
@@ -134,20 +134,28 @@ func Getenv(name string, defVal ...string) (val string) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseVarNameAndType(key string) (string, string) {
|
||||
func parseVarNameAndType(key string) (string, string, string) {
|
||||
var desc string
|
||||
typ := "string"
|
||||
key = strings.Trim(key, "-")
|
||||
|
||||
// can set var type: int, uint, bool
|
||||
if strings.IndexByte(key, ':') > 0 {
|
||||
list := strings.SplitN(key, ":", 2)
|
||||
list := strings.SplitN(key, ":", 3)
|
||||
key, typ = list[0], list[1]
|
||||
if len(list) == 3 {
|
||||
desc = list[2]
|
||||
}
|
||||
|
||||
// if type is not valid and has multi words, as desc message.
|
||||
if _, ok := validTypes[typ]; !ok {
|
||||
if desc == "" && strings.ContainsRune(typ, ' ') {
|
||||
desc = typ
|
||||
}
|
||||
typ = "string"
|
||||
}
|
||||
}
|
||||
return key, typ
|
||||
return key, typ, desc
|
||||
}
|
||||
|
||||
// format key
|
||||
|
||||
4
vendor/github.com/gookit/config/v2/write.go
generated
vendored
4
vendor/github.com/gookit/config/v2/write.go
generated
vendored
@@ -28,12 +28,12 @@ func (c *Config) SetData(data map[string]any) {
|
||||
c.fireHook(OnSetData)
|
||||
}
|
||||
|
||||
// Set val by key
|
||||
// Set value by key. setByPath default is true
|
||||
func Set(key string, val any, setByPath ...bool) error {
|
||||
return dc.Set(key, val, setByPath...)
|
||||
}
|
||||
|
||||
// Set a value by key string.
|
||||
// Set a value by key string. setByPath default is true
|
||||
func (c *Config) Set(key string, val any, setByPath ...bool) (err error) {
|
||||
if c.opts.Readonly {
|
||||
return ErrReadonly
|
||||
|
||||
1
vendor/github.com/gookit/goutil/.gitignore
generated
vendored
1
vendor/github.com/gookit/goutil/.gitignore
generated
vendored
@@ -19,5 +19,6 @@
|
||||
*.cov
|
||||
.DS_Store
|
||||
|
||||
*~
|
||||
testdata/
|
||||
vendor/
|
||||
1
vendor/github.com/gookit/goutil/README.md
generated
vendored
1
vendor/github.com/gookit/goutil/README.md
generated
vendored
@@ -1417,6 +1417,7 @@ func BlankOr(val, defVal string) string
|
||||
func ZeroOr[T ~string](val, defVal T) T
|
||||
func ErrorOr(s string, err error, defVal string) string
|
||||
func OrElse(s, orVal string) string
|
||||
func OrElseNilSafe(s *string, orVal string) string
|
||||
func OrHandle(s string, fn comdef.StringHandleFunc) string
|
||||
func Valid(ss ...string) string
|
||||
func Replaces(str string, pairs map[string]string) string
|
||||
|
||||
1
vendor/github.com/gookit/goutil/README.zh-CN.md
generated
vendored
1
vendor/github.com/gookit/goutil/README.zh-CN.md
generated
vendored
@@ -1418,6 +1418,7 @@ func BlankOr(val, defVal string) string
|
||||
func ZeroOr[T ~string](val, defVal T) T
|
||||
func ErrorOr(s string, err error, defVal string) string
|
||||
func OrElse(s, orVal string) string
|
||||
func OrElseNilSafe(s *string, orVal string) string
|
||||
func OrHandle(s string, fn comdef.StringHandleFunc) string
|
||||
func Valid(ss ...string) string
|
||||
func Replaces(str string, pairs map[string]string) string
|
||||
|
||||
6
vendor/github.com/gookit/goutil/arrutil/collection.go
generated
vendored
6
vendor/github.com/gookit/goutil/arrutil/collection.go
generated
vendored
@@ -135,13 +135,13 @@ func Differences[T any](first, second []T, fn Comparer[T]) []T {
|
||||
return CloneSlice(first)
|
||||
}
|
||||
|
||||
max := firstLen
|
||||
maxLn := firstLen
|
||||
if secondLen > firstLen {
|
||||
max = secondLen
|
||||
maxLn = secondLen
|
||||
}
|
||||
|
||||
result := make([]T, 0)
|
||||
for i := 0; i < max; i++ {
|
||||
for i := 0; i < maxLn; i++ {
|
||||
if i < firstLen {
|
||||
s := first[i]
|
||||
if i, _ := TwowaySearch(second, s, fn); i < 0 {
|
||||
|
||||
29
vendor/github.com/gookit/goutil/basefn/basefn.go
generated
vendored
29
vendor/github.com/gookit/goutil/basefn/basefn.go
generated
vendored
@@ -54,7 +54,18 @@ func MustOK(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Must if error is not empty, will panic
|
||||
// Must return like (v, error). will panic on error, otherwise return v.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// // old
|
||||
// v, err := fn()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// // new
|
||||
// v := goutil.Must(fn())
|
||||
func Must[T any](v T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -62,6 +73,22 @@ func Must[T any](v T, err error) T {
|
||||
return v
|
||||
}
|
||||
|
||||
// MustIgnore for return like (v, error). Ignore return v and will panic on error.
|
||||
//
|
||||
// Useful for io, file operation func: (n int, err error)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// // old
|
||||
// _, err := fn()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// // new
|
||||
// basefn.MustIgnore(fn())
|
||||
func MustIgnore(_ any, err error) { PanicErr(err) }
|
||||
|
||||
// ErrOnFail return input error on cond is false, otherwise return nil
|
||||
func ErrOnFail(cond bool, err error) error {
|
||||
return OrError(cond, err)
|
||||
|
||||
9
vendor/github.com/gookit/goutil/byteutil/buffer.go
generated
vendored
9
vendor/github.com/gookit/goutil/byteutil/buffer.go
generated
vendored
@@ -93,10 +93,11 @@ func (b *Buffer) writeAnysWithNl(vs []any, nl bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// Printf quiet write message to buffer, ignore error.
|
||||
func (b *Buffer) Printf(tpl string, vs ...any) {
|
||||
_, _ = b.WriteString(fmt.Sprintf(tpl, vs...))
|
||||
}
|
||||
// Printf quick write message to buffer, ignore error.
|
||||
func (b *Buffer) Printf(tpl string, vs ...any) { _, _ = fmt.Fprintf(b, tpl, vs...) }
|
||||
|
||||
// Println quick write message with newline to buffer, will ignore error.
|
||||
func (b *Buffer) Println(vs ...any) { _, _ = fmt.Fprintln(b, vs...) }
|
||||
|
||||
// ResetGet buffer string. alias of ResetAndGet()
|
||||
func (b *Buffer) ResetGet() string {
|
||||
|
||||
11
vendor/github.com/gookit/goutil/check.go
generated
vendored
11
vendor/github.com/gookit/goutil/check.go
generated
vendored
@@ -26,6 +26,17 @@ func IsEmpty(v any) bool {
|
||||
return reflects.IsEmpty(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
// Alias of the IsEmptyReal()
|
||||
var IsZeroReal = IsEmptyReal
|
||||
|
||||
// IsEmptyReal checks for empty given value and also real empty value if the passed value is a pointer
|
||||
func IsEmptyReal(v any) bool {
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
return reflects.IsEmptyReal(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
// IsFunc value
|
||||
func IsFunc(val any) bool {
|
||||
if val == nil {
|
||||
|
||||
6
vendor/github.com/gookit/goutil/comdef/consts_nonwin.go
generated
vendored
Normal file
6
vendor/github.com/gookit/goutil/comdef/consts_nonwin.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
//go:build !windows
|
||||
|
||||
package comdef
|
||||
|
||||
// Newline string for non-windows
|
||||
const Newline = "\n"
|
||||
4
vendor/github.com/gookit/goutil/comdef/consts_windows.go
generated
vendored
Normal file
4
vendor/github.com/gookit/goutil/comdef/consts_windows.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
package comdef
|
||||
|
||||
// Newline string for windows
|
||||
const Newline = "\r\n"
|
||||
2
vendor/github.com/gookit/goutil/comdef/types.go
generated
vendored
2
vendor/github.com/gookit/goutil/comdef/types.go
generated
vendored
@@ -59,7 +59,7 @@ type SimpleType interface {
|
||||
Int | Uint | Float | ~string | ~bool
|
||||
}
|
||||
|
||||
// ScalarType interface type.
|
||||
// ScalarType basic interface type.
|
||||
//
|
||||
// TIP: has bool type, it cannot be ordered
|
||||
//
|
||||
|
||||
4
vendor/github.com/gookit/goutil/errorx/stack.go
generated
vendored
4
vendor/github.com/gookit/goutil/errorx/stack.go
generated
vendored
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
@@ -112,7 +112,7 @@ func (f *Func) FileLine() (file string, line int) {
|
||||
func (f *Func) Location() string {
|
||||
file, line := f.FileLine()
|
||||
|
||||
return f.Name() + "(), " + path.Base(file) + ":" + strconv.Itoa(line)
|
||||
return f.Name() + "(), " + filepath.Base(file) + ":" + strconv.Itoa(line)
|
||||
}
|
||||
|
||||
// String of the func
|
||||
|
||||
9
vendor/github.com/gookit/goutil/fsutil/find.go
generated
vendored
9
vendor/github.com/gookit/goutil/fsutil/find.go
generated
vendored
@@ -216,14 +216,17 @@ func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error)
|
||||
return // ignore I/O error
|
||||
}
|
||||
|
||||
// names, _ := d.Readdirnames(-1)
|
||||
// sort.Strings(names)
|
||||
|
||||
des, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// remove the last '/' char
|
||||
dirLn := len(dir)
|
||||
if dirLn > 1 && dir[dirLn-1] == '/' {
|
||||
dir = dir[:dirLn-1]
|
||||
}
|
||||
|
||||
for _, ent := range des {
|
||||
filePath := dir + "/" + ent.Name()
|
||||
|
||||
|
||||
35
vendor/github.com/gookit/goutil/fsutil/fsutil.go
generated
vendored
35
vendor/github.com/gookit/goutil/fsutil/fsutil.go
generated
vendored
@@ -6,20 +6,26 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/basefn"
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// PathSep alias of os.PathSeparator
|
||||
const PathSep = os.PathSeparator
|
||||
|
||||
// JoinPaths elements, alias of filepath.Join()
|
||||
func JoinPaths(elem ...string) string {
|
||||
return filepath.Join(elem...)
|
||||
}
|
||||
|
||||
// JoinPaths3 elements, like the filepath.Join()
|
||||
func JoinPaths3(basePath, secPath string, elems ...string) string {
|
||||
return comfunc.JoinPaths3(basePath, secPath, elems)
|
||||
}
|
||||
|
||||
// JoinSubPaths elements, like the filepath.Join()
|
||||
func JoinSubPaths(basePath string, elem ...string) string {
|
||||
paths := make([]string, len(elem)+1)
|
||||
paths[0] = basePath
|
||||
copy(paths[1:], elem)
|
||||
return filepath.Join(paths...)
|
||||
func JoinSubPaths(basePath string, elems ...string) string {
|
||||
return comfunc.JoinPaths2(basePath, elems)
|
||||
}
|
||||
|
||||
// SlashPath alias of filepath.ToSlash
|
||||
@@ -35,11 +41,21 @@ func UnixPath(path string) string {
|
||||
return strings.ReplaceAll(path, "\\", "/")
|
||||
}
|
||||
|
||||
// ToAbsPath convert process. will expand home dir
|
||||
// ToAbsPath convert path to absolute path.
|
||||
// Will expand home dir, if empty will return current work dir
|
||||
//
|
||||
// TIP: will don't check path
|
||||
// TIP: will don't check path is really exists
|
||||
func ToAbsPath(p string) string {
|
||||
if len(p) == 0 || IsAbsPath(p) {
|
||||
// return current work dir
|
||||
if len(p) == 0 {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return p
|
||||
}
|
||||
return wd
|
||||
}
|
||||
|
||||
if IsAbsPath(p) {
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -54,3 +70,6 @@ func ToAbsPath(p string) string {
|
||||
}
|
||||
return filepath.Join(wd, p)
|
||||
}
|
||||
|
||||
// Must2 ok for (any, error) result. if it has error, will panic
|
||||
func Must2(_ any, err error) { basefn.MustOK(err) }
|
||||
|
||||
15
vendor/github.com/gookit/goutil/fsutil/info.go
generated
vendored
15
vendor/github.com/gookit/goutil/fsutil/info.go
generated
vendored
@@ -2,7 +2,6 @@ package fsutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
@@ -15,7 +14,7 @@ func DirPath(fpath string) string { return filepath.Dir(fpath) }
|
||||
func Dir(fpath string) string { return filepath.Dir(fpath) }
|
||||
|
||||
// PathName get file/dir name from full path
|
||||
func PathName(fpath string) string { return path.Base(fpath) }
|
||||
func PathName(fpath string) string { return filepath.Base(fpath) }
|
||||
|
||||
// Name get file/dir name from full path.
|
||||
//
|
||||
@@ -27,25 +26,25 @@ func Name(fpath string) string {
|
||||
return filepath.Base(fpath)
|
||||
}
|
||||
|
||||
// FileExt get filename ext. alias of path.Ext()
|
||||
// FileExt get filename ext. alias of filepath.Ext()
|
||||
//
|
||||
// eg: path/to/main.go => ".go"
|
||||
func FileExt(fpath string) string { return path.Ext(fpath) }
|
||||
func FileExt(fpath string) string { return filepath.Ext(fpath) }
|
||||
|
||||
// Extname get filename ext. alias of path.Ext()
|
||||
// Extname get filename ext. alias of filepath.Ext()
|
||||
//
|
||||
// eg: path/to/main.go => "go"
|
||||
func Extname(fpath string) string {
|
||||
if ext := path.Ext(fpath); len(ext) > 0 {
|
||||
if ext := filepath.Ext(fpath); len(ext) > 0 {
|
||||
return ext[1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Suffix get filename ext. alias of path.Ext()
|
||||
// Suffix get filename ext. alias of filepath.Ext()
|
||||
//
|
||||
// eg: path/to/main.go => ".go"
|
||||
func Suffix(fpath string) string { return path.Ext(fpath) }
|
||||
func Suffix(fpath string) string { return filepath.Ext(fpath) }
|
||||
|
||||
// Expand will parse first `~` as user home dir path.
|
||||
func Expand(pathStr string) string {
|
||||
|
||||
5
vendor/github.com/gookit/goutil/fsutil/operate.go
generated
vendored
5
vendor/github.com/gookit/goutil/fsutil/operate.go
generated
vendored
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -121,7 +120,7 @@ const (
|
||||
//
|
||||
// file, err := OpenFile("path/to/file.txt", FsCWFlags, 0666)
|
||||
func OpenFile(filePath string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
fileDir := path.Dir(filePath)
|
||||
fileDir := filepath.Dir(filePath)
|
||||
if err := os.MkdirAll(fileDir, DefaultDirPerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -177,7 +176,7 @@ func OpenReadFile(filepath string) (*os.File, error) {
|
||||
//
|
||||
// CreateFile("path/to/file.txt", 0664, 0666)
|
||||
func CreateFile(fpath string, filePerm, dirPerm os.FileMode, fileFlag ...int) (*os.File, error) {
|
||||
dirPath := path.Dir(fpath)
|
||||
dirPath := filepath.Dir(fpath)
|
||||
if !IsDir(dirPath) {
|
||||
err := os.MkdirAll(dirPath, dirPerm)
|
||||
if err != nil {
|
||||
|
||||
12
vendor/github.com/gookit/goutil/fsutil/opread.go
generated
vendored
12
vendor/github.com/gookit/goutil/fsutil/opread.go
generated
vendored
@@ -27,9 +27,7 @@ func DiscardReader(src io.Reader) {
|
||||
}
|
||||
|
||||
// ReadFile read file contents, will panic on error
|
||||
func ReadFile(filePath string) []byte {
|
||||
return MustReadFile(filePath)
|
||||
}
|
||||
func ReadFile(filePath string) []byte { return MustReadFile(filePath) }
|
||||
|
||||
// MustReadFile read file contents, will panic on error
|
||||
func MustReadFile(filePath string) []byte {
|
||||
@@ -53,9 +51,7 @@ func MustReadReader(r io.Reader) []byte {
|
||||
}
|
||||
|
||||
// ReadString read contents from path or io.Reader, will panic on in type error
|
||||
func ReadString(in any) string {
|
||||
return string(GetContents(in))
|
||||
}
|
||||
func ReadString(in any) string { return string(GetContents(in)) }
|
||||
|
||||
// ReadStringOrErr read contents from path or io.Reader, will panic on in type error
|
||||
func ReadStringOrErr(in any) (string, error) {
|
||||
@@ -78,9 +74,7 @@ func ReadAll(in any) []byte { return MustRead(in) }
|
||||
func GetContents(in any) []byte { return MustRead(in) }
|
||||
|
||||
// MustRead read contents from path or io.Reader, will panic on in type error
|
||||
func MustRead(in any) []byte {
|
||||
return basefn.Must(ReadOrErr(in))
|
||||
}
|
||||
func MustRead(in any) []byte { return basefn.Must(ReadOrErr(in)) }
|
||||
|
||||
// ReadOrErr read contents from path or io.Reader, will panic on in type error
|
||||
func ReadOrErr(in any) ([]byte, error) {
|
||||
|
||||
1
vendor/github.com/gookit/goutil/fsutil/opwrite.go
generated
vendored
1
vendor/github.com/gookit/goutil/fsutil/opwrite.go
generated
vendored
@@ -83,6 +83,7 @@ func SaveFile(filePath string, data any, optFns ...OpenOptionFunc) error {
|
||||
// Usage:
|
||||
//
|
||||
// fsutil.PutContents(filePath, contents, fsutil.FsCWAFlags) // append write
|
||||
// fsutil.Must2(fsutil.PutContents(filePath, contents)) // panic on error
|
||||
func PutContents(filePath string, data any, fileFlag ...int) (int, error) {
|
||||
f, err := QuickOpenFile(filePath, basefn.FirstOr(fileFlag, FsCWTFlags))
|
||||
if err != nil {
|
||||
|
||||
4
vendor/github.com/gookit/goutil/goinfo/stack.go
generated
vendored
4
vendor/github.com/gookit/goutil/goinfo/stack.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
package goinfo
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -91,7 +91,7 @@ func GetCallersInfo(skip, max int) []string {
|
||||
|
||||
if strings.ContainsRune(file, '/') {
|
||||
name = fc.Name()
|
||||
file = path.Base(file)
|
||||
file = filepath.Base(file)
|
||||
// eg: github.com/gookit/goutil/goinfo_test.someFunc2(),stack_test.go:26
|
||||
callers = append(callers, name+"(),"+file+":"+strconv.Itoa(line))
|
||||
}
|
||||
|
||||
52
vendor/github.com/gookit/goutil/goutil.go
generated
vendored
52
vendor/github.com/gookit/goutil/goutil.go
generated
vendored
@@ -23,28 +23,50 @@ func PanicIf(cond bool, fmtAndArgs ...any) {
|
||||
basefn.PanicIf(cond, fmtAndArgs...)
|
||||
}
|
||||
|
||||
// PanicIfErr if error is not empty, will panic
|
||||
func PanicIfErr(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// PanicErr if error is not empty, will panic
|
||||
// PanicErr if error is not empty, will panic.
|
||||
// Alias of basefn.PanicErr()
|
||||
func PanicErr(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// MustOK if error is not empty, will panic
|
||||
func MustOK(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// PanicIfErr if error is not empty, will panic.
|
||||
// Alias of basefn.PanicErr()
|
||||
func PanicIfErr(err error) { PanicErr(err) }
|
||||
|
||||
// Must if error is not empty, will panic
|
||||
// MustOK if error is not empty, will panic.
|
||||
// Alias of basefn.MustOK()
|
||||
func MustOK(err error) { PanicErr(err) }
|
||||
|
||||
// MustIgnore for return like (v, error). Ignore return v and will panic on error.
|
||||
//
|
||||
// Useful for io, file operation func: (n int, err error)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// // old
|
||||
// _, err := fn()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// // new
|
||||
// goutil.MustIgnore(fn())
|
||||
func MustIgnore(_ any, err error) { PanicErr(err) }
|
||||
|
||||
// Must return like (v, error). will panic on error, otherwise return v.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// // old
|
||||
// v, err := fn()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// // new
|
||||
// v := goutil.Must(fn())
|
||||
func Must[T any](v T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
17
vendor/github.com/gookit/goutil/internal/checkfn/check.go
generated
vendored
17
vendor/github.com/gookit/goutil/internal/checkfn/check.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -106,3 +107,19 @@ func Contains(data, elem any) (valid, found bool) {
|
||||
}
|
||||
return true, false
|
||||
}
|
||||
|
||||
// StringsContains check string slice contains string
|
||||
func StringsContains(ss []string, s string) bool {
|
||||
for _, v := range ss {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// check is number: int or float
|
||||
var numReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
|
||||
|
||||
// IsNumeric returns true if the given string is a numeric, otherwise false.
|
||||
func IsNumeric(s string) bool { return numReg.MatchString(s) }
|
||||
|
||||
20
vendor/github.com/gookit/goutil/internal/comfunc/fsfunc.go
generated
vendored
Normal file
20
vendor/github.com/gookit/goutil/internal/comfunc/fsfunc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package comfunc
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// JoinPaths2 elements, like the filepath.Join()
|
||||
func JoinPaths2(basePath string, elems []string) string {
|
||||
paths := make([]string, len(elems)+1)
|
||||
paths[0] = basePath
|
||||
copy(paths[1:], elems)
|
||||
return filepath.Join(paths...)
|
||||
}
|
||||
|
||||
// JoinPaths3 elements, like the filepath.Join()
|
||||
func JoinPaths3(basePath, secPath string, elems []string) string {
|
||||
paths := make([]string, len(elems)+2)
|
||||
paths[0] = basePath
|
||||
paths[1] = secPath
|
||||
copy(paths[2:], elems)
|
||||
return filepath.Join(paths...)
|
||||
}
|
||||
24
vendor/github.com/gookit/goutil/maputil/get.go
generated
vendored
24
vendor/github.com/gookit/goutil/maputil/get.go
generated
vendored
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/reflects"
|
||||
)
|
||||
|
||||
@@ -193,6 +194,14 @@ func Keys(mp any) (keys []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// TypedKeys get all keys of the given typed map.
|
||||
func TypedKeys[K comdef.SimpleType, V any](mp map[K]V) (keys []K) {
|
||||
for key := range mp {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Values get all values from the given map.
|
||||
func Values(mp any) (values []any) {
|
||||
rv := reflect.Indirect(reflect.ValueOf(mp))
|
||||
@@ -207,6 +216,14 @@ func Values(mp any) (values []any) {
|
||||
return
|
||||
}
|
||||
|
||||
// TypedValues get all values from the given typed map.
|
||||
func TypedValues[K comdef.SimpleType, V any](mp map[K]V) (values []V) {
|
||||
for _, val := range mp {
|
||||
values = append(values, val)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EachAnyMap iterates the given map and calls the given function for each item.
|
||||
func EachAnyMap(mp any, fn func(key string, val any)) {
|
||||
rv := reflect.Indirect(reflect.ValueOf(mp))
|
||||
@@ -218,3 +235,10 @@ func EachAnyMap(mp any, fn func(key string, val any)) {
|
||||
fn(key.String(), rv.MapIndex(key).Interface())
|
||||
}
|
||||
}
|
||||
|
||||
// EachTypedMap iterates the given map and calls the given function for each item.
|
||||
func EachTypedMap[K comdef.SimpleType, V any](mp map[K]V, fn func(key K, val V)) {
|
||||
for key, val := range mp {
|
||||
fn(key, val)
|
||||
}
|
||||
}
|
||||
|
||||
11
vendor/github.com/gookit/goutil/maputil/maputil.go
generated
vendored
11
vendor/github.com/gookit/goutil/maputil/maputil.go
generated
vendored
@@ -39,6 +39,17 @@ func SimpleMerge(src, dst map[string]any) map[string]any {
|
||||
return dst
|
||||
}
|
||||
|
||||
// Merge1level merge multi any map[string]any data. only merge one level data.
|
||||
func Merge1level(mps ...map[string]any) map[string]any {
|
||||
newMp := make(map[string]any)
|
||||
for _, mp := range mps {
|
||||
for k, v := range mp {
|
||||
newMp[k] = v
|
||||
}
|
||||
}
|
||||
return newMp
|
||||
}
|
||||
|
||||
// func DeepMerge(src, dst map[string]any, deep int) map[string]any { TODO
|
||||
// }
|
||||
|
||||
|
||||
11
vendor/github.com/gookit/goutil/mathutil/calc.go
generated
vendored
Normal file
11
vendor/github.com/gookit/goutil/mathutil/calc.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package mathutil
|
||||
|
||||
import "github.com/gookit/goutil/comdef"
|
||||
|
||||
// Abs get absolute value of given value
|
||||
func Abs[T comdef.Int](val T) T {
|
||||
if val >= 0 {
|
||||
return val
|
||||
}
|
||||
return -val
|
||||
}
|
||||
22
vendor/github.com/gookit/goutil/mathutil/convert.go
generated
vendored
22
vendor/github.com/gookit/goutil/mathutil/convert.go
generated
vendored
@@ -192,7 +192,16 @@ func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error) {
|
||||
iVal = int(tVal)
|
||||
}
|
||||
case string:
|
||||
iVal, err = strconv.Atoi(strings.TrimSpace(tVal))
|
||||
sVal := strings.TrimSpace(tVal)
|
||||
iVal, err = strconv.Atoi(sVal)
|
||||
// handle the case where the string might be a float
|
||||
if err != nil && checkfn.IsNumeric(sVal) {
|
||||
var floatVal float64
|
||||
if floatVal, err = strconv.ParseFloat(sVal, 64); err == nil {
|
||||
iVal = int(math.Round(floatVal))
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
case comdef.Int64able: // eg: json.Number
|
||||
var i64 int64
|
||||
if i64, err = tVal.Int64(); err == nil {
|
||||
@@ -287,7 +296,16 @@ func ToInt64With(in any, optFns ...ConvOptionFn[int64]) (i64 int64, err error) {
|
||||
|
||||
switch tVal := in.(type) {
|
||||
case string:
|
||||
i64, err = strconv.ParseInt(strings.TrimSpace(tVal), 10, 0)
|
||||
sVal := strings.TrimSpace(tVal)
|
||||
i64, err = strconv.ParseInt(sVal, 10, 0)
|
||||
// handle the case where the string might be a float
|
||||
if err != nil && checkfn.IsNumeric(sVal) {
|
||||
var floatVal float64
|
||||
if floatVal, err = strconv.ParseFloat(sVal, 64); err == nil {
|
||||
i64 = int64(math.Round(floatVal))
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
case int:
|
||||
i64 = int64(tVal)
|
||||
case int8:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user