diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index e4c86969e0..b8cbae2f23 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -18,7 +18,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3.1.0
+ uses: actions/checkout@v4
- name: Setup Go environment
uses: actions/setup-go@v4
with:
diff --git a/.github/workflows/compose.yml b/.github/workflows/compose.yml
index aa01a4c38d..0197928757 100644
--- a/.github/workflows/compose.yml
+++ b/.github/workflows/compose.yml
@@ -21,7 +21,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: ${{ inputs.submodules }}
- name: Download image
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index ecd1ecfc96..bae63b1ec7 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -27,7 +27,7 @@ jobs:
image: ${{ steps.build.outputs.imageid }}
steps:
- name: Checkout
- uses: actions/checkout@v3.1.0
+ uses: actions/checkout@v4
- name: Set up QEMU
if: inputs.platforms != ''
uses: docker/setup-qemu-action@v2
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 272845a5d9..43f6b7ac8e 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3.1.0
+ uses: actions/checkout@v4
- name: Setup Go environment
uses: actions/setup-go@v4
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a9f447c23a..d682ab8a62 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Go environment
id: go
uses: actions/setup-go@v4
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 33abc742db..71f486522b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Go environment
uses: actions/setup-go@v4
with:
@@ -39,7 +39,7 @@ jobs:
runs-on: self-hosted
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Go environment
uses: actions/setup-go@v4
with:
diff --git a/.gitignore b/.gitignore
index 8202949ebe..789e187529 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,4 @@ toolchain/
logs_test/
tmp/
+public/
diff --git a/changelog/unreleased/eos-perms.md b/changelog/unreleased/eos-perms.md
new file mode 100644
index 0000000000..0ac6f1a184
--- /dev/null
+++ b/changelog/unreleased/eos-perms.md
@@ -0,0 +1,6 @@
+Bugfix: fixed permission mapping to EOS ACLs
+
+This is to remove "m" and "q" flags in EOS ACLs
+for regular write shares (no re-sharing).
+
+https://github.com/cs3org/reva/pull/4667
diff --git a/changelog/unreleased/eos-userquota.md b/changelog/unreleased/eos-userquota.md
new file mode 100644
index 0000000000..b9edef6418
--- /dev/null
+++ b/changelog/unreleased/eos-userquota.md
@@ -0,0 +1,6 @@
+Enhancement: differentiate quota for user types in EOS
+
+We now assign a different initial quota to users depending
+on their type, whether PRIMARY or not.
+
+https://github.com/cs3org/reva/pull/4720
diff --git a/changelog/unreleased/fix-auth-log.md b/changelog/unreleased/fix-auth-log.md
new file mode 100644
index 0000000000..0f73303bb4
--- /dev/null
+++ b/changelog/unreleased/fix-auth-log.md
@@ -0,0 +1,6 @@
+Bugfix: auth: increase verbosity of oidc parsing errors
+
+This is to help further debugging of auth issues.
+An unrelated error reporting was also fixed.
+
+https://github.com/cs3org/reva/pull/4599
diff --git a/changelog/unreleased/ocm-access.md b/changelog/unreleased/ocm-access.md
new file mode 100644
index 0000000000..c99a7e2b68
--- /dev/null
+++ b/changelog/unreleased/ocm-access.md
@@ -0,0 +1,8 @@
+Enhancement: ocm: support bearer token access
+
+This PR adds support for accessing remote OCM 1.1 shares via bearer token,
+as opposed to having the shared secret in the URL only.
+In addition, the OCM client package is now part of the OCMD server package,
+and the Discover methods have been all consolidated in one place.
+
+https://github.com/cs3org/reva/pull/4670
diff --git a/docker/Dockerfile.revad-ceph b/docker/Dockerfile.revad-ceph
index a190c20199..ff895eed59 100644
--- a/docker/Dockerfile.revad-ceph
+++ b/docker/Dockerfile.revad-ceph
@@ -20,6 +20,10 @@ FROM quay.io/ceph/ceph:v18
RUN mkdir -p /etc/selinux/config
+# this is a workaround as the Ceph docker image is still based on CentOS 8 Stream, which is EOL
+RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
+RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
+
RUN dnf update --exclude=ceph-iscsi,chrony -y && dnf install -y \
git \
gcc \
@@ -28,12 +32,12 @@ RUN dnf update --exclude=ceph-iscsi,chrony -y && dnf install -y \
librbd-devel \
librados-devel
-ADD https://go.dev/dl/go1.21.5.linux-amd64.tar.gz \
- go1.21.5.linux-amd64.tar.gz
+ADD https://go.dev/dl/go1.22.2.linux-amd64.tar.gz \
+ go1.22.2.linux-amd64.tar.gz
RUN rm -rf /usr/local/go && \
- tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz && \
- rm go1.21.5.linux-amd64.tar.gz
+ tar -C /usr/local -xzf go1.22.2.linux-amd64.tar.gz && \
+ rm go1.22.2.linux-amd64.tar.gz
ENV PATH /go/bin:/usr/local/go/bin:$PATH
ENV GOPATH /go
@@ -49,8 +53,6 @@ RUN mkdir -p /go/bin && \
make revad-ceph && \
cp /go/src/github/cs3org/reva/cmd/revad/revad /usr/bin/revad
-RUN cp -r examples/ceph /etc/
-
RUN mkdir -p /etc/revad/ && touch /etc/revad/revad.toml
EXPOSE 9999 10000
diff --git a/docs/assets/scss/styles_project b/docs/assets/scss/styles_project
new file mode 100644
index 0000000000..212cd84b73
--- /dev/null
+++ b/docs/assets/scss/styles_project
@@ -0,0 +1,15 @@
+/*
+
+Add styles or override variables from the theme here.
+
+*/
+
+$primary: #29a7df;
+$secondary: #ED6A5A;
+$dark: #131516;
+$enable-gradients: false;
+$enable-rounded: false;
+$enable-shadows: false;
+$td-enable-google-fonts: true;
+$google_font_name: "Roboto";
+$google_font_family: "Roboto:300,300i,400,400i,700,700i";
diff --git a/docs/content/en/docs/config/grpc/interceptors/_index.md b/docs/content/en/docs/config/grpc/interceptors/_index.md
index b73299cd28..7ceb7a973b 100644
--- a/docs/content/en/docs/config/grpc/interceptors/_index.md
+++ b/docs/content/en/docs/config/grpc/interceptors/_index.md
@@ -11,4 +11,5 @@ To configure an GRPC interceptor you need to follow this convention in the confi
{{< highlight toml >}}
[grpc.interceptors.interceptor_name]
... config ...
+{{ highlight >}}
diff --git a/docs/content/en/docs/config/grpc/services/_index.md b/docs/content/en/docs/config/grpc/services/_index.md
index 6c31544a64..d67d237cf1 100644
--- a/docs/content/en/docs/config/grpc/services/_index.md
+++ b/docs/content/en/docs/config/grpc/services/_index.md
@@ -11,4 +11,4 @@ To configure a GRPC service you need to follow this convention in the config fil
{{< highlight toml >}}
[grpc.services.service_name]
... config ...
-
+{{ highlight >}}
diff --git a/docs/content/en/docs/config/http/middlewares/_index.md b/docs/content/en/docs/config/http/middlewares/_index.md
index b8c73308d6..912ab36fe4 100644
--- a/docs/content/en/docs/config/http/middlewares/_index.md
+++ b/docs/content/en/docs/config/http/middlewares/_index.md
@@ -11,4 +11,5 @@ To configure an HTTP middleware you need to follow this convention in the config
{{< highlight toml >}}
[http.middlewares.middleware_name]
... config ...
+{{ highlight >}}
diff --git a/docs/content/en/docs/config/http/services/_index.md b/docs/content/en/docs/config/http/services/_index.md
index f87a641e40..840e1f6776 100644
--- a/docs/content/en/docs/config/http/services/_index.md
+++ b/docs/content/en/docs/config/http/services/_index.md
@@ -11,4 +11,6 @@ To configure an HTTP service you need to follow this convention in the config fi
{{< highlight toml >}}
[http.services.service_name]
... config ...
+{{ highlight >}}
+
diff --git a/docs/content/en/docs/config/packages/notification/notificationhelper/_index.md b/docs/content/en/docs/config/packages/notification/notificationhelper/_index.md
index 45101d615d..0e1a76b716 100644
--- a/docs/content/en/docs/config/packages/notification/notificationhelper/_index.md
+++ b/docs/content/en/docs/config/packages/notification/notificationhelper/_index.md
@@ -32,11 +32,11 @@ nats_stream = "reva-notifications"
{{< /highlight >}}
{{% /dir %}}
-{{% dir name="templates" type="map[string]interface{}" default= %}}
+{{% dir name="templates" type="map[string]interface{}" default=nil %}}
Notification templates for the service. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/notification/notificationhelper/notificationhelper.go#L50)
{{< highlight toml >}}
[notification.notificationhelper]
-templates =
+templates = nil
{{< /highlight >}}
{{% /dir %}}
diff --git a/docs/content/en/docs/config/serverless/services/notifications/_index.md b/docs/content/en/docs/config/serverless/services/notifications/_index.md
index fe98ffbd5f..9b42b2b6cb 100644
--- a/docs/content/en/docs/config/serverless/services/notifications/_index.md
+++ b/docs/content/en/docs/config/serverless/services/notifications/_index.md
@@ -16,11 +16,11 @@ nats_address = ""
{{< /highlight >}}
{{% /dir %}}
-{{% dir name="nats_token" type="string" default="The token to authenticate against the NATS server" %}}
- [[Ref]](https://github.com/cs3org/reva/tree/master/internal/serverless/services/notifications/notifications.go#L48)
+{{% dir name="nats_token" type="string" default="" %}}
+The token to authenticate against the NATS server [[Ref]](https://github.com/cs3org/reva/tree/master/internal/serverless/services/notifications/notifications.go#L48)
{{< highlight toml >}}
[serverless.services.notifications]
-nats_token = "The token to authenticate against the NATS server"
+nats_token = ""
{{< /highlight >}}
{{% /dir %}}
@@ -32,11 +32,11 @@ nats_prefix = "reva-notifications"
{{< /highlight >}}
{{% /dir %}}
-{{% dir name="handlers" type="map[string]map[string]interface{}" default= %}}
+{{% dir name="handlers" type="map[string]map[string]interface{}" default=nil %}}
Settings for the different notification handlers. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/serverless/services/notifications/notifications.go#L50)
{{< highlight toml >}}
[serverless.services.notifications]
-handlers =
+handlers = nil
{{< /highlight >}}
{{% /dir %}}
diff --git a/docs/content/en/docs/tutorials/cephfs-tutorial.md b/docs/content/en/docs/tutorials/cephfs-tutorial.md
new file mode 100644
index 0000000000..4975507777
--- /dev/null
+++ b/docs/content/en/docs/tutorials/cephfs-tutorial.md
@@ -0,0 +1,135 @@
+---
+title: "Setting up Reva with CephFS"
+linkTitle: "Setting up Reva with CephFS"
+weight: 10
+description: >
+ Setting up Reva with a CephFS cluster
+---
+
+This is a guide on how to set up Reva in your local environment and connect it to an existing CephFS cluster.
+
+For questions on this tutorial plase refer to https://github.com/cs3org/reva/discussions/4610
+
+### 1. CephFS setup
+You need to have an existing CephFS installation in the machine where you will deploy Reva.
+Even though is not needed for Reva to have CephFS mounted on the machine where Reva will run, we highly recommend it
+as it will make grasping the concepts much easier.
+
+For this tutorial, we have a Ceph mount exposed under the mountpoint `/cephfs`.
+
+```
+$ cat /etc/fstab | grep cephfs
+cernbox@.cernbox=/ /cephfs ceph rbytes
+```
+
+```
+$ df -h | grep ceph
+10.81.22.151:6789,10.81.22.161:6789,10.81.22.171:6789:/ 1.3P 650G 1.2P 1% /cephfs
+```
+
+The ceph configuration lives under `/etc/ceph`.
+
+```
+$ tree /etc/ceph/
+/etc/ceph/
+├── ceph.client.cernbox.keyring
+├── ceph.conf
+└── rbdmap
+```
+
+Your cluster details will differ, this is just an example configuration file.
+```
+$ cat /etc/ceph/ceph.conf
+[global]
+auth_client_required=cephx
+fsid=f5195e24-158c-11ee-b338-5ced8c61b074
+mon_host=[v2:10.81.22.151:3300/0,v1:10.81.22.151:6789/0],[v2:10.81.22.161:3300/0,v1:10.81.22.161:6789/0],[v2:10.81.22.171:3300/0,v1:10.81.22.171:6789/0]
+```
+
+```
+cat /etc/ceph/ceph.client.cernbox.keyring
+[client.cernbox]
+key = mycephsecretkey==
+```
+
+With this information we can start setting up Reva.
+
+
+
+## Reva setup
+
+
+Follow the steps here:
+https://reva.link/docs/getting-started/build-reva/
+
+We also need the libcephfs library, depending on your OS the command to install will change, here is how you install it for Fedora 39:
+```
+dnf install libcephfs* -y
+```
+
+At this step you shoudl have a local clone of the Reva software:
+
+```
+git clone https://github.com/cs3org/reva
+cd reva
+make revad-ceph
+make reva
+./cmd/revad/revad -v
+```
+
+You can copy the binaries (`reva` is the client cli and `revad` is the daemon) to a default location so is available in your PATH:
+```
+cp ./cmd/revad/revad /usr/local/bin/revad
+cp ./cmd/reva/reva /usr/local/bin/reva
+```
+
+
+### Creating test users
+CephFS relies on the UNIX uid and guid attributes to perform access control.
+For this example, we'll create `einstein` user with `uid=4000`:
+
+```
+$ sudo useradd -u 4000 einstein
+$ id einstein
+uid=4000(einstein) gid=4000(einstein) groups=4000(einstein)
+```
+### Create configuration files
+
+For this tutorial, we'll use two files:
+- `revad.toml` (main configuration file to run reva, preconfigured for Ceph cluster)
+- `test_users.json` (configuration used to store users, only `einstein` is configured)
+
+These files are available at https://github.com/cs3org/reva/tree/master/examples/cephfs
+
+Copy the `revad.toml` to `/etc/revad/revad.toml`, the default location where the reva binary will load its configuration.
+Copy the `test_users.json` file to `/etc/revad/test_users.json` to match the configuration from `/etc/revad/revad.toml`.
+Create directory where reva will log its outpout: `mkdir -p /var/log/revad`.
+
+### Run revad
+Ideally you would use an init system like systemd or docker to run it, for this tutorial we run it manually:
+```
+$ nohup revad &
+```
+
+Let's take a look at the logs:
+
+```
+tail /var/log/revad/revad.log
+```
+
+### Connect to revad
+
+The Reva daemon listens on port `9143` (configured in `/etc/revad/revad.toml`)
+Let's use the reva client cli to connect to it:
+
+```
+$ reva -host localhost:9143 -insecure login basic
+username: einstein
+password:
+OK
+
+$ reva whoami
+```
+
+
+
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 35305c603f..1c78071386 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -1,671 +1,1718 @@
{
"name": "tech-doc-hugo",
"version": "0.0.1",
- "lockfileVersion": 1,
+ "lockfileVersion": 3,
"requires": true,
- "dependencies": {
- "@babel/code-frame": {
+ "packages": {
+ "": {
+ "name": "tech-doc-hugo",
+ "version": "0.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "hugo-extended": "^0.124.1"
+ },
+ "devDependencies": {
+ "autoprefixer": "^10.2.6",
+ "postcss": "^8.4.31",
+ "postcss-cli": "^8.3.1"
+ }
+ },
+ "node_modules/@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
- "dev": true,
- "requires": {
+ "dependencies": {
"@babel/highlight": "^7.12.13"
}
},
- "@babel/helper-validator-identifier": {
+ "node_modules/@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
- "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
- "dev": true
+ "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A=="
},
- "@babel/highlight": {
+ "node_modules/@babel/highlight": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
- "dev": true,
- "requires": {
+ "dependencies": {
"@babel/helper-validator-identifier": "^7.14.0",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
},
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dependencies": {
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
}
},
- "@nodelib/fs.scandir": {
+ "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
- "requires": {
+ "dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
- "@nodelib/fs.stat": {
+ "node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
},
- "@nodelib/fs.walk": {
+ "node_modules/@nodelib/fs.walk": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz",
"integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==",
"dev": true,
- "requires": {
+ "dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz",
+ "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
+ "dependencies": {
+ "defer-to-connect": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=14.16"
}
},
- "@types/parse-json": {
+ "node_modules/@types/http-cache-semantics": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="
+ },
+ "node_modules/@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"dev": true
},
- "ansi-regex": {
+ "node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
},
- "ansi-styles": {
+ "node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
- "requires": {
+ "dependencies": {
"color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "anymatch": {
+ "node_modules/anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"dev": true,
- "requires": {
+ "dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
- "array-union": {
+ "node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
},
- "at-least-node": {
+ "node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
},
- "autoprefixer": {
+ "node_modules/autoprefixer": {
"version": "10.2.6",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.6.tgz",
"integrity": "sha512-8lChSmdU6dCNMCQopIf4Pe5kipkAGj/fvTMslCsih0uHpOrXOPUEVOmYMMqmw3cekQkSD7EhIeuYl5y0BLdKqg==",
"dev": true,
- "requires": {
+ "dependencies": {
"browserslist": "^4.16.6",
"caniuse-lite": "^1.0.30001230",
"colorette": "^1.2.2",
"fraction.js": "^4.1.1",
"normalize-range": "^0.1.2",
"postcss-value-parser": "^4.1.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "binary-extensions": {
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
+ "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
+ "dependencies": {
+ "readable-stream": "^2.3.5",
+ "safe-buffer": "^5.1.1"
+ }
},
- "braces": {
+ "node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
- "requires": {
+ "dependencies": {
"fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "browserslist": {
+ "node_modules/browserslist": {
"version": "4.16.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"caniuse-lite": "^1.0.30001219",
"colorette": "^1.2.2",
"electron-to-chromium": "^1.3.723",
"escalade": "^3.1.1",
"node-releases": "^1.1.71"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dependencies": {
+ "buffer-alloc-unsafe": "^1.1.0",
+ "buffer-fill": "^1.0.0"
+ }
+ },
+ "node_modules/buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="
+ },
+ "node_modules/cacheable-lookup": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
+ "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==",
+ "engines": {
+ "node": ">=14.16"
}
},
- "callsites": {
+ "node_modules/cacheable-request": {
+ "version": "10.2.14",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz",
+ "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==",
+ "dependencies": {
+ "@types/http-cache-semantics": "^4.0.2",
+ "get-stream": "^6.0.1",
+ "http-cache-semantics": "^4.1.1",
+ "keyv": "^4.5.3",
+ "mimic-response": "^4.0.0",
+ "normalize-url": "^8.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/cacheable-request/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
},
- "caniuse-lite": {
+ "node_modules/caniuse-lite": {
"version": "1.0.30001234",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001234.tgz",
"integrity": "sha512-a3gjUVKkmwLdNysa1xkUAwN2VfJUJyVW47rsi3aCbkRCtbHAfo+rOsCqVw29G6coQ8gzAPb5XBXwiGHwme3isA==",
- "dev": true
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ }
+ },
+ "node_modules/careful-downloader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/careful-downloader/-/careful-downloader-3.0.0.tgz",
+ "integrity": "sha512-5KMIPa0Yoj+2tY6OK9ewdwcPebp+4XS0dMYvvF9/8fkFEfvnEpWmHWYs9JNcZ7RZUvY/v6oPzLpmmTzSIbroSA==",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "decompress": "^4.2.1",
+ "fs-extra": "^11.1.1",
+ "got": "^12.6.0",
+ "is-path-inside": "^4.0.0",
+ "tempy": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/careful-downloader/node_modules/fs-extra": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
},
- "chalk": {
+ "node_modules/chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "chokidar": {
+ "node_modules/chokidar": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"dev": true,
- "requires": {
+ "dependencies": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
- "fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.1"
}
},
- "cliui": {
+ "node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
- "color-convert": {
+ "node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
}
},
- "color-name": {
+ "node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "colorette": {
+ "node_modules/colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
"dev": true
},
- "cosmiconfig": {
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/cosmiconfig": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
"integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==",
"dev": true,
- "requires": {
+ "dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/crypto-random-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
+ "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
+ "dependencies": {
+ "type-fest": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/crypto-random-string/node_modules/type-fest": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
+ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decompress": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz",
+ "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==",
+ "dependencies": {
+ "decompress-tar": "^4.0.0",
+ "decompress-tarbz2": "^4.0.0",
+ "decompress-targz": "^4.0.0",
+ "decompress-unzip": "^4.0.1",
+ "graceful-fs": "^4.1.10",
+ "make-dir": "^1.0.0",
+ "pify": "^2.3.0",
+ "strip-dirs": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-tar": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
+ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
+ "dependencies": {
+ "file-type": "^5.2.0",
+ "is-stream": "^1.1.0",
+ "tar-stream": "^1.5.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tarbz2": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+ "dependencies": {
+ "decompress-tar": "^4.1.0",
+ "file-type": "^6.1.0",
+ "is-stream": "^1.1.0",
+ "seek-bzip": "^1.0.5",
+ "unbzip2-stream": "^1.0.9"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tarbz2/node_modules/file-type": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
+ "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-targz": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
+ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
+ "dependencies": {
+ "decompress-tar": "^4.1.1",
+ "file-type": "^5.2.0",
+ "is-stream": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-unzip": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
+ "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==",
+ "dependencies": {
+ "file-type": "^3.8.0",
+ "get-stream": "^2.2.0",
+ "pify": "^2.3.0",
+ "yauzl": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-unzip/node_modules/file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "engines": {
+ "node": ">=10"
}
},
- "dependency-graph": {
+ "node_modules/dependency-graph": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz",
"integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
},
- "dir-glob": {
+ "node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
- "requires": {
+ "dependencies": {
"path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "electron-to-chromium": {
+ "node_modules/electron-to-chromium": {
"version": "1.3.748",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.748.tgz",
"integrity": "sha512-fmIKfYALVeEybk/L2ucdgt7jN3JsbGtg3K9pmF/MRWgkeADBI1VSAa5IzdG2gZwTxsnsrFtdMpOTSM5mrBRKVQ==",
"dev": true
},
- "emoji-regex": {
+ "node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
- "error-ex": {
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "requires": {
+ "dependencies": {
"is-arrayish": "^0.2.1"
}
},
- "escalade": {
+ "node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
},
- "escape-string-regexp": {
+ "node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
+ "engines": {
+ "node": ">=0.8.0"
+ }
},
- "fast-glob": {
+ "node_modules/fast-glob": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
"dev": true,
- "requires": {
+ "dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.0",
"merge2": "^1.3.0",
"micromatch": "^4.0.2",
"picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "fastq": {
+ "node_modules/fastq": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
"dev": true,
- "requires": {
+ "dependencies": {
"reusify": "^1.0.4"
}
},
- "fill-range": {
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/file-type": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/form-data-encoder": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz",
+ "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==",
+ "engines": {
+ "node": ">= 14.17"
}
},
- "fraction.js": {
+ "node_modules/fraction.js": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz",
"integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://www.patreon.com/infusion"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
- "fs-extra": {
+ "node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "fsevents": {
+ "node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
- "optional": true
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
- "get-caller-file": {
+ "node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
},
- "get-stdin": {
+ "node_modules/get-stdin": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
+ "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==",
+ "dependencies": {
+ "object-assign": "^4.0.1",
+ "pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "glob-parent": {
+ "node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
- "globby": {
+ "node_modules/globby": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
"integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
"dev": true,
- "requires": {
+ "dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.1.1",
"ignore": "^5.1.4",
"merge2": "^1.3.0",
"slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/got": {
+ "version": "12.6.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz",
+ "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==",
+ "dependencies": {
+ "@sindresorhus/is": "^5.2.0",
+ "@szmarczak/http-timer": "^5.0.1",
+ "cacheable-lookup": "^7.0.0",
+ "cacheable-request": "^10.2.8",
+ "decompress-response": "^6.0.0",
+ "form-data-encoder": "^2.1.2",
+ "get-stream": "^6.0.1",
+ "http2-wrapper": "^2.1.10",
+ "lowercase-keys": "^3.0.0",
+ "p-cancelable": "^3.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
+ "node_modules/got/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "graceful-fs": {
+ "node_modules/graceful-fs": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
- "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
- "dev": true
+ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
},
- "has-flag": {
+ "node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
+ },
+ "node_modules/http2-wrapper": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz",
+ "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==",
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
+ "node_modules/hugo-extended": {
+ "version": "0.124.1",
+ "resolved": "https://registry.npmjs.org/hugo-extended/-/hugo-extended-0.124.1.tgz",
+ "integrity": "sha512-GaF/wOTSrfobyVwd46/0KSwVPQ76ZEU4BnKj5rrLyYtGDwFM4UXGdtTa9z8xMI4DF9RvCV6UIvU0cvkcDEl+aA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "careful-downloader": "^3.0.0",
+ "log-symbols": "^5.1.0",
+ "read-pkg-up": "^9.1.0"
+ },
+ "bin": {
+ "hugo": "lib/cli.js",
+ "hugo-extended": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
},
- "ignore": {
+ "node_modules/ignore": {
"version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
},
- "import-cwd": {
+ "node_modules/import-cwd": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
"integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==",
"dev": true,
- "requires": {
+ "dependencies": {
"import-from": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "import-fresh": {
+ "node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dev": true,
- "requires": {
+ "dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "import-from": {
+ "node_modules/import-from": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz",
"integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"resolve-from": "^5.0.0"
},
- "dependencies": {
- "resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true
- }
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-from/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
}
},
- "is-arrayish": {
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
- "is-binary-path": {
+ "node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
- "requires": {
+ "dependencies": {
"binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "is-extglob": {
+ "node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-fullwidth-code-point": {
+ "node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
},
- "is-glob": {
+ "node_modules/is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-number": {
+ "node_modules/is-natural-number": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
+ "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ=="
+ },
+ "node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz",
+ "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
- "js-tokens": {
+ "node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
},
- "json-parse-even-better-errors": {
+ "node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
- "jsonfile": {
+ "node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.6",
+ "dependencies": {
"universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
}
},
- "lines-and-columns": {
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/lines-and-columns": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
- "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
- "dev": true
+ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA="
+ },
+ "node_modules/locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "dependencies": {
+ "p-locate": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "lodash.difference": {
+ "node_modules/lodash.difference": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
"integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=",
"dev": true
},
- "lodash.forown": {
+ "node_modules/lodash.forown": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-4.4.0.tgz",
"integrity": "sha1-hRFc8E9z75ZuztUlEdOJPMRmg68=",
"dev": true
},
- "lodash.get": {
+ "node_modules/lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
"dev": true
},
- "lodash.groupby": {
+ "node_modules/lodash.groupby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
"integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=",
"dev": true
},
- "lodash.sortby": {
+ "node_modules/lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
"dev": true
},
- "merge2": {
+ "node_modules/log-symbols": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
+ "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
+ "dependencies": {
+ "chalk": "^5.0.0",
+ "is-unicode-supported": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/lowercase-keys": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/make-dir/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
},
- "micromatch": {
+ "node_modules/micromatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
"integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
"dev": true,
- "requires": {
+ "dependencies": {
"braces": "^3.0.1",
"picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": ">=8.6"
}
},
- "nanoid": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
- "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
- "dev": true
+ "node_modules/mimic-response": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz",
+ "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
},
- "node-releases": {
+ "node_modules/node-releases": {
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
"dev": true
},
- "normalize-path": {
+ "node_modules/normalize-package-data": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dependencies": {
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "normalize-range": {
+ "node_modules/normalize-range": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz",
+ "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
+ "engines": {
+ "node": ">=12.20"
+ }
},
- "parent-module": {
+ "node_modules/p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "dependencies": {
+ "yocto-queue": "^1.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "dependencies": {
+ "p-limit": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
- "requires": {
+ "dependencies": {
"callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
}
},
- "parse-json": {
+ "node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
- "requires": {
+ "dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
"json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
- "path-type": {
+ "node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
- "picomatch": {
+ "node_modules/picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
- "pify": {
+ "node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+ "dependencies": {
+ "pinkie": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "postcss": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz",
- "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==",
+ "node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"dev": true,
- "requires": {
- "colorette": "^1.2.2",
- "nanoid": "^3.1.23",
- "source-map-js": "^0.6.2"
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
}
},
- "postcss-cli": {
+ "node_modules/postcss-cli": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-8.3.1.tgz",
"integrity": "sha512-leHXsQRq89S3JC9zw/tKyiVV2jAhnfQe0J8VI4eQQbUjwIe0XxVqLrR+7UsahF1s9wi4GlqP6SJ8ydf44cgF2Q==",
"dev": true,
- "requires": {
+ "dependencies": {
"chalk": "^4.0.0",
"chokidar": "^3.3.0",
"dependency-graph": "^0.9.0",
@@ -678,180 +1725,592 @@
"read-cache": "^1.0.0",
"slash": "^3.0.0",
"yargs": "^16.0.0"
+ },
+ "bin": {
+ "postcss": "bin/postcss"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
}
},
- "postcss-load-config": {
+ "node_modules/postcss-load-config": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.0.1.tgz",
"integrity": "sha512-/pDHe30UYZUD11IeG8GWx9lNtu1ToyTsZHnyy45B4Mrwr/Kb6NgYl7k753+05CJNKnjbwh4975amoPJ+TEjHNQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"cosmiconfig": "^7.0.0",
"import-cwd": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
}
},
- "postcss-reporter": {
+ "node_modules/postcss-reporter": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.2.tgz",
"integrity": "sha512-JyQ96NTQQsso42y6L1H1RqHfWH1C3Jr0pt91mVv5IdYddZAE9DUZxuferNgk6q0o6vBVOrfVJb10X1FgDzjmDw==",
"dev": true,
- "requires": {
+ "dependencies": {
"colorette": "^1.2.1",
"lodash.difference": "^4.5.0",
"lodash.forown": "^4.4.0",
"lodash.get": "^4.4.2",
"lodash.groupby": "^4.6.0",
"lodash.sortby": "^4.7.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "postcss-value-parser": {
+ "node_modules/postcss-value-parser": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true
},
- "pretty-hrtime": {
+ "node_modules/pretty-hrtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
- "queue-microtask": {
+ "node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "read-cache": {
+ "node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
"dev": true,
- "requires": {
+ "dependencies": {
"pify": "^2.3.0"
}
},
- "readdirp": {
+ "node_modules/read-pkg": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz",
+ "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==",
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.1",
+ "normalize-package-data": "^3.0.2",
+ "parse-json": "^5.2.0",
+ "type-fest": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz",
+ "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==",
+ "dependencies": {
+ "find-up": "^6.3.0",
+ "read-pkg": "^7.1.0",
+ "type-fest": "^2.5.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
}
},
- "require-directory": {
+ "node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
},
- "resolve-from": {
+ "node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/responselike": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
+ "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==",
+ "dependencies": {
+ "lowercase-keys": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "reusify": {
+ "node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
},
- "run-parallel": {
+ "node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
- "requires": {
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
"queue-microtask": "^1.2.2"
}
},
- "slash": {
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/seek-bzip": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz",
+ "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
+ "dependencies": {
+ "commander": "^2.8.1"
+ },
+ "bin": {
+ "seek-bunzip": "bin/seek-bunzip",
+ "seek-table": "bin/seek-bzip-table"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+ "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
},
- "source-map-js": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
- "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
- "dev": true
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
+ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg=="
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string_decoder/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
- "string-width": {
+ "node_modules/string-width": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
"dev": true,
- "requires": {
+ "dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "strip-ansi": {
+ "node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-regex": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-dirs": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
+ "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
+ "dependencies": {
+ "is-natural-number": "^4.0.1"
}
},
- "supports-color": {
+ "node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
- "requires": {
+ "dependencies": {
"has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+ "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+ "dependencies": {
+ "bl": "^1.0.0",
+ "buffer-alloc": "^1.2.0",
+ "end-of-stream": "^1.0.0",
+ "fs-constants": "^1.0.0",
+ "readable-stream": "^2.3.0",
+ "to-buffer": "^1.1.1",
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/temp-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz",
+ "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==",
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/tempy": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz",
+ "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==",
+ "dependencies": {
+ "is-stream": "^3.0.0",
+ "temp-dir": "^3.0.0",
+ "type-fest": "^2.12.2",
+ "unique-string": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/tempy/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "to-regex-range": {
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "node_modules/to-buffer": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
+ },
+ "node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/unbzip2-stream": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
+ "dependencies": {
+ "buffer": "^5.2.1",
+ "through": "^2.3.8"
+ }
+ },
+ "node_modules/unique-string": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
+ "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
+ "dependencies": {
+ "crypto-random-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "universalify": {
+ "node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
- "dev": true
+ "engines": {
+ "node": ">= 10.0.0"
+ }
},
- "wrap-ansi": {
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
}
},
- "y18n": {
+ "node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
},
- "yaml": {
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
},
- "yargs": {
+ "node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
- "requires": {
+ "dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
@@ -859,13 +2318,39 @@
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "yargs-parser": {
+ "node_modules/yargs-parser": {
"version": "20.2.7",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz",
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
+ "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/docs/package.json b/docs/package.json
index a29f9d640d..b31cc2babf 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -16,10 +16,12 @@
"url": "https://github.com/bep/tech-doc-hugo/issues"
},
"homepage": "https://github.com/bep/tech-doc-hugo#readme",
- "dependencies": {},
"devDependencies": {
"autoprefixer": "^10.2.6",
- "postcss-cli": "^8.3.1",
- "postcss": "^8.4.31"
+ "postcss": "^8.4.31",
+ "postcss-cli": "^8.3.1"
+ },
+ "dependencies": {
+ "hugo-extended": "^0.124.1"
}
}
diff --git a/docs/themes/docsy b/docs/themes/docsy
index 1a09abe6d7..b95a4948ee 160000
--- a/docs/themes/docsy
+++ b/docs/themes/docsy
@@ -1 +1 @@
-Subproject commit 1a09abe6d7eaf02e44f79de3eadf8178a3792e81
+Subproject commit b95a4948ee42e601d2685a334e0b2362e31820ef
diff --git a/examples/ceph/ceph.conf b/examples/ceph/ceph.conf
deleted file mode 100644
index f2daaa8de5..0000000000
--- a/examples/ceph/ceph.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-[global]
- fsid = '8aaa35c4-75dc-42e5-a812-cbc1cdfd3323'
- mon_host = '[v2:188.184.96.178:3300/0,v1:188.184.96.178:6789/0] [v2:188.185.88.76:3300/0,v1:188.185.88.76:6789/0] [v2:188.185.126.6:3300/0,v1:188.185.126.6:6789/0]'
diff --git a/examples/ceph/keyring b/examples/ceph/keyring
deleted file mode 100644
index 9e555cc1b2..0000000000
--- a/examples/ceph/keyring
+++ /dev/null
@@ -1,2 +0,0 @@
-[client.admin]
- key = 'AQAu88Fg5iekGhAAeVP0Td05PuybytuRJgBRqA=='
diff --git a/examples/cephfs/revad.toml b/examples/cephfs/revad.toml
new file mode 100644
index 0000000000..1e8a01ba04
--- /dev/null
+++ b/examples/cephfs/revad.toml
@@ -0,0 +1,143 @@
+[log]
+output = "/var/log/revad/revad.log"
+mode = "json"
+level = "debug"
+
+[shared]
+gatewaysvc = "localhost:9142"
+jwt_secret = "$JWTSECRET"
+skip_user_groups_in_token = true
+
+[grpc]
+address = "localhost:9142"
+
+[grpc.services.gateway]
+commit_share_to_storage_grant = true
+disable_home_creation_on_login = false
+transfer_expires = 86400 # seconds
+etag_cache_ttl = 0
+#create_home_cache_ttl = 86400 # seconds
+transfer_shared_secret = "$TRANSFERSECRET"
+authregistrysvc = "localhost:9142"
+storageregistrysvc = "localhost:9142"
+userprovidersvc = "localhost:9142"
+datagateway = "https://$HOSTNAME/datagateway"
+
+[grpc.services.storageprovider]
+driver = "cephfs"
+mount_path = "/"
+mount_id = "cephfs"
+data_server_url = "http://localhost:9143/data"
+
+[grpc.services.storageprovider.drivers.cephfs]
+root = "/"
+config = "/etc/ceph/ceph.conf"
+keyring = "/etc/ceph/ceph.client.cernbox.keyring"
+client_id = "cernbox"
+disable_home = false
+enable_recycle = false
+dir_perms = 0o777
+file_perms = 0o666
+user_layout = "/users/{{.Username}}"
+
+[grpc.services.gateway.token_managers.jwt]
+expires = 1500
+
+[grpc.services.authregistry]
+driver = "static"
+
+[grpc.services.authregistry.drivers.static.rules]
+basic = "localhost:9142"
+bearer = "localhost:9158"
+
+[grpc.services.storageregistry]
+driver = "static"
+
+[grpc.services.storageregistry.drivers.static]
+#home_provider = "/"
+
+[grpc.services.storageregistry.drivers.static.rules]
+"/" = {"address" = "localhost:9142"}
+
+[grpc.services.userprovider]
+driver = "json"
+
+[grpc.services.userprovider.drivers.json]
+users = "/etc/revad/test_users.json"
+
+[grpc.services.authprovider]
+auth_manager = "json"
+
+[grpc.services.authprovider.auth_managers.json]
+users = "/etc/revad/test_users.json"
+
+[http]
+address = "0.0.0.0:9143"
+
+[http.middlewares.auth]
+credential_chain = ["basic", "bearer"]
+token_strategy_chain = ["bearer", "header"]
+
+[http.middlewares.auth.credentials_by_user_agent]
+"mirall" = "basic"
+
+[http.middlewares.cors]
+allowed_origins = ["*"]
+allowed_methods = ["OPTIONS", "LOCK", "GET", "HEAD", "POST", "DELETE", "PROPPATCH", "COPY", "MOVE", "UNLOCK", "PROPFIND", "MKCOL", "REPORT", "SEARCH", "PUT"]
+allowed_headers = ["Accept", "Accept-Language", "Authorization", "Content-Language", "Content-Type", "Depth", "OCS-APIREQUEST", "Referer", "sec-ch-ua", "sec-ch-ua-mobile", "sec-ch-ua-platform", "User-Agent", "X-Requested-With"]
+debug = true
+exposed_headers = []
+
+[http.services.datagateway]
+transfer_shared_secret = "$TRANSFERSECRET"
+timeout = 86400
+insecure = true
+prefix = "datagateway"
+
+
+[http.services.ocdav]
+files_namespace = "/"
+webdav_namespace = "/"
+timeout = 86400
+insecure = true
+enable_http_tpc = false
+
+[http.services.ocs.config]
+version = "1.8"
+website = "reva"
+host = "https://$HOSTNAME:443"
+ssl = "false"
+
+[http.services.ocs.capabilities.capabilities.core]
+poll_interval = 60
+webdav_root = "remote.php/webdav/"
+status = { installed = true, maintenance = false, nwwsaDbUpgrade = false, version = "10.0.11.5", versionstring = "10.0.11", edition = "community", productname = "reva", hostname = "" }
+support_url_signing = false
+
+[http.services.ocs.capabilities.capabilities.checksums]
+supported_types = ["sha1", "md5", "adler32"]
+
+[http.services.ocs.capabilities.capabilities.dav]
+chunkingParallelUploadDisabled = false
+
+[http.services.ocs.capabilities.capabilities.files]
+private_links = false
+bigfilechunking = true
+blacklisted_files = [ ]
+undelete = true
+versioning = true
+
+[http.services.dataprovider]
+driver = "cephfs"
+
+[http.services.dataprovider.drivers.cephfs]
+root = "/"
+config = "/etc/ceph/ceph.conf"
+keyring = "/etc/ceph/ceph.client.cernbox.keyring"
+client_id = "cernbox"
+disable_home = false
+enable_recycle = false
+dir_perms = 0o777
+file_perms = 0o666
+user_layout = "/users/{{.Username}}"
+
diff --git a/examples/cephfs/test_users.json b/examples/cephfs/test_users.json
new file mode 100644
index 0000000000..c213e9e2ec
--- /dev/null
+++ b/examples/cephfs/test_users.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": {
+ "opaque_id": "einstein",
+ "type": 1
+ },
+ "username": "einstein",
+ "secret": "relativity",
+ "mail": "example@org",
+ "display_name": "Einstein",
+ "groups": [
+ "sailing-lovers",
+ "violin-haters",
+ "physics-lovers"
+ ],
+ "uid_number": 4000
+ }
+]
diff --git a/examples/cernbox/cernbox.toml b/examples/cernbox/cernbox.toml
new file mode 100644
index 0000000000..3f7b47b30d
--- /dev/null
+++ b/examples/cernbox/cernbox.toml
@@ -0,0 +1,406 @@
+## Example configuration to run a dockerized CERNBox for ScienceMesh tests
+#
+# The following variables are actualized by the scripts in tests/sciencemesh/scripts
+
+[vars]
+internal_gateway = "your.revad.org"
+provider_domain = "your.revad.org"
+external_reva_endpoint = "https://your.nginx.org" # append here any route if applicable
+wopi_endpoint = "http://your.wopi.org:8880"
+ocmshares_json_file = "/var/tmp/reva/shares_cernbox.json"
+machine_api_key = "machine-api-key"
+wopi_shared_secret = "shared-secret-2"
+
+[http]
+certfile = "/etc/tls/your.revad.ssl.crt"
+keyfile = "/etc/tls/your.revad.ssl.key"
+
+[log]
+level = "debug"
+
+[shared]
+gatewaysvc = "{{ vars.internal_gateway }}:19000"
+jwt_secret = "reva-secret"
+
+[grpc.services.gateway]
+address = ":19000"
+authregistrysvc = "{{ grpc.services.authregistry.address }}"
+appregistrysvc = "{{ grpc.services.appregistry.address }}"
+storageregistrysvc = "{{ grpc.services.storageregistry.address }}"
+preferencessvc = "{{ grpc.services.userprovider.address }}"
+userprovidersvc = "{{ grpc.services.userprovider.address }}"
+usershareprovidersvc = "{{ grpc.services.usershareprovider.address }}"
+publicshareprovidersvc = "{{ grpc.services.publicshareprovider.address }}"
+ocmcoresvc = "{{ grpc.services.ocmcore.address }}"
+ocmshareprovidersvc = "{{ grpc.services.ocmshareprovider.address }}"
+ocminvitemanagersvc = "{{ grpc.services.ocminvitemanager.address }}"
+ocmproviderauthorizersvc = "{{ grpc.services.ocmproviderauthorizer.address }}"
+datagateway = "https://{{ http.services.datagateway.address }}/data"
+
+transfer_expires = 6 # give it a moment
+commit_share_to_storage_grant = true
+commit_share_to_storage_ref = true
+
+
+### APPS ###
+
+[grpc.services.appregistry]
+driver = "static"
+
+[grpc.services.appregistry.drivers.static]
+mime_types = [
+ {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true},
+ {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"}
+]
+
+[[grpc.services.appprovider]]
+driver = "wopi"
+custom_mime_types_json = "/etc/revad/custom-mime-types-demo.json"
+mime_types = ["application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.presentation", "text/rtf"]
+app_provider_url = "{{ grpc.services.appprovider[0].address }}"
+language = "en-GB"
+
+[grpc.services.appprovider.drivers.wopi]
+iop_secret = "{{ vars.wopi_shared_secret }}"
+wopi_url = "{{ vars.wopi_endpoint }}"
+app_name = "Collabora"
+app_url = "http://collabora.docker:9980"
+app_int_url = "http://collabora.docker:9980"
+
+
+# [[grpc.services.appprovider]]
+# driver = "wopi"
+# custom_mime_types_json = "/etc/revad/custom-mime-types-demo.json"
+# mime_types = ["text/markdown", "application/compressed-markdown", "text/plain"]
+# app_provider_url = "{{ grpc.services.appprovider[1].address }}"
+#
+# [grpc.services.appprovider.drivers.wopi]
+# iop_secret = "{{ vars.wopi_shared_secret }}"
+# wopi_url = "{{ vars.wopi_endpoint }}"
+# app_name = "CodiMD"
+# app_url = "https://codimd.docker"
+# app_int_url = "https://codimd.docker"
+
+
+### AUTH ###
+
+[grpc.services.authregistry]
+driver = "static"
+
+[grpc.services.authregistry.drivers.static.rules]
+basic = "{{ grpc.services.authprovider[0].address }}"
+bearer = "{{ grpc.services.authprovider[0].address }}"
+machine = "{{ grpc.services.authprovider[1].address }}"
+ocmshares = "{{ grpc.services.authprovider[2].address }}"
+
+[[grpc.services.authprovider]]
+auth_manager = "oidc"
+
+[grpc.services.authprovider.auth_managers.json]
+users = "/etc/revad/users.demo.json"
+
+[grpc.services.authprovider.auth_managers.oidc]
+issuer = "https://idp.docker:8443/realms/cernbox"
+uid_claim = "cern_uid"
+gid_claim = "cern_gid"
+gatewaysvc = "{{ vars.internal_gateway }}:19000"
+
+[[grpc.services.authprovider]]
+auth_manager = "machine"
+
+[grpc.services.authprovider.auth_managers.machine]
+api_key = "{{ vars.machine_api_key }}"
+gateway_addr = "{{ vars.internal_gateway }}:19000"
+
+[[grpc.services.authprovider]]
+auth_manager = "ocmshares"
+
+
+### STORAGE ###
+
+[grpc.services.storageregistry]
+driver = "static"
+
+[grpc.services.storageregistry.drivers.static]
+home_provider = "/"
+
+[grpc.services.storageregistry.drivers.static.rules]
+"/" = {"address" = "{{ grpc.services.storageprovider[0].address }}"}
+"localhome" = {"address" = "{{ grpc.services.storageprovider[0].address }}"}
+"/ocm" = {"address" = "{{ grpc.services.storageprovider[1].address }}"}
+"ocm" = {"address" = "{{ grpc.services.storageprovider[1].address }}"}
+"/sciencemesh" = { address = "{{ grpc.services.storageprovider[2].address }}" }
+"sciencemesh" = { address = "{{ grpc.services.storageprovider[2].address }}" }
+
+[[grpc.services.storageprovider]]
+driver = "localhome"
+mount_path = "/"
+mount_id = "localhome"
+expose_data_server = true
+data_server_url = "https://localhost:{{ http.services.dataprovider[0].address.port }}/data"
+enable_home_creation = true
+
+[grpc.services.storageprovider.drivers.localhome]
+user_layout = "{{.Username}}"
+
+[[grpc.services.storageprovider]]
+driver = "ocmoutcoming"
+mount_id = "ocm"
+mount_path = "/ocm"
+expose_data_server = true
+enable_home_creation = false
+data_server_url = "{{ vars.external_reva_endpoint }}/data"
+
+[grpc.services.storageprovider.drivers.ocmoutcoming]
+machine_secret = "{{ vars.machine_api_key }}"
+
+[[grpc.services.storageprovider]]
+driver = "ocmreceived"
+mount_path = "/sciencemesh"
+mount_id = "sciencemesh"
+expose_data_server = true
+# this must be accessible from the GUI, therefore the hostname will be replaced
+data_server_url = "https://your.revad.org:{{ http.services.dataprovider[2].address.port }}/data"
+
+
+### OTHER PROVIDERS ###
+
+[grpc.services.usershareprovider]
+driver = "memory"
+
+[grpc.services.publicshareprovider]
+driver = "memory"
+
+[grpc.services.preferences]
+
+[grpc.services.ocmcore]
+driver = "json"
+
+[grpc.services.ocmcore.drivers.json]
+# Note that ocmcore and ocmshareprovider should use the same file for storing the shares.
+file = "{{ vars.ocmshares_json_file }}"
+
+[grpc.services.ocminvitemanager]
+driver = "json"
+provider_domain = "{{ vars.provider_domain }}"
+
+[grpc.services.ocmshareprovider]
+driver = "json"
+provider_domain = "{{ vars.provider_domain }}"
+webdav_endpoint = "{{ vars.external_reva_endpoint }}"
+webdav_prefix = "{{ vars.external_reva_endpoint }}/remote.php/dav/files"
+webapp_template = "{{ vars.external_reva_endpoint }}/external/sciencemesh/{{.Token}}/{relative-path-to-shared-resource}"
+
+[grpc.services.ocmshareprovider.drivers.json]
+file = "{{ vars.ocmshares_json_file }}"
+
+[grpc.services.ocmproviderauthorizer]
+driver = "open" # pure OCM, all remote shares are accepted
+#driver = "json" # to enable sciencemesh
+
+[grpc.services.ocmproviderauthorizer.drivers.json]
+# this is used by the docker-based test deployment, not in production
+providers = "/etc/revad/providers.testnet.json"
+verify_request_hostname = true
+
+[grpc.services.userprovider]
+driver = "json"
+
+[grpc.services.userprovider.drivers.json]
+users = "/etc/revad/users.demo.json"
+
+[grpc.services.datatx]
+txdriver = "rclone"
+storagedriver = "json"
+remove_transfer_on_cancel = true
+
+[grpc.services.datatx.txdrivers.rclone]
+# rclone endpoint
+endpoint = "http://rclone.docker"
+# basic auth is used
+auth_user = "rcloneuser"
+auth_pass = "eilohtho9oTahsuongeeTh7reedahPo1Ohwi3aek"
+auth_header = "x-access-token"
+job_status_check_interval = 2000
+job_timeout = 120000
+storagedriver = "json"
+remove_transfer_job_on_cancel = true
+
+[grpc.services.datatx.storagedrivers.json]
+file = ""
+
+[grpc.services.datatx.txdrivers.rclone.storagedrivers.json]
+file = ""
+
+
+### HTTP ENDPOINTS ###
+
+[http.middlewares.auth]
+credential_chain = ["publicshares", "basic", "bearer"]
+token_strategy_chain = ["bearer", "header"]
+
+[http.middlewares.auth.credentials_by_user_agent]
+"mirall" = "basic"
+
+[http.services.appprovider]
+address = ":443"
+
+[http.services.datagateway]
+address = ":443"
+
+[[http.services.dataprovider]]
+driver = "localhome"
+
+[http.services.dataprovider.drivers.localhome]
+user_layout = "{{.Username}}"
+
+[[http.services.dataprovider]]
+address = ":443"
+driver = "ocmoutcoming"
+
+[http.services.dataprovider.drivers.ocmoutcoming]
+machine_secret = "{{ vars.machine_api_key }}"
+
+[[http.services.dataprovider]]
+driver = "ocmreceived"
+
+[http.services.sciencemesh]
+address = ":443"
+provider_domain = "{{ vars.provider_domain }}"
+mesh_directory_url = "https:/meshdir.docker/meshdir"
+ocm_mount_point = "/sciencemesh"
+
+[http.services.sciencemesh.smtp_credentials]
+disable_auth = true
+sender_mail = "sciencemesh@{{ vars.provider_domain }}"
+smtp_server = "smtp.{{ vars.provider_domain }}"
+smtp_port = 25
+
+[http.services.wellknown.ocmprovider]
+address = ":443"
+ocm_prefix = "ocm"
+provider = "Reva for CERNBox"
+endpoint = "{{ vars.external_reva_endpoint }}"
+enable_webapp = true
+enable_datatx = true
+
+[http.services.ocm]
+address = ":443"
+prefix = "ocm"
+
+[http.services.ocm.config]
+host = "{{ vars.provider_domain }}"
+
+# OCS
+[http.services.ocs]
+address = ":443"
+prefix = "ocs"
+share_prefix = "/"
+home_namespace = "/"
+additional_info_attribute = "{{.Username}} ({{.Mail}})"
+cache_warmup_driver = "first-request"
+resource_info_cache_ttl = 60
+resource_info_cache_type = "memory"
+
+[http.services.ocs.config]
+version = "1.8"
+website = "reva"
+host = "https://localhost"
+contact = "cernbox@cernbox.org"
+ssl = "false"
+
+[http.services.ocs.capabilities.capabilities.core]
+poll_interval = 60
+webdav_root = "remote.php/webdav"
+status = { installed = true, maintenance = false, nwwsaDbUpgrade = false, version = "10.0.11.5", versionstring = "10.0.11", edition = "community", productname = "reva", hostname = "" }
+support_url_signing = false
+
+[http.services.ocs.capabilities.capabilities.checksums]
+supported_types = ["sha1", "md5", "adler32"]
+
+[http.services.ocs.capabilities.capabilities.files]
+private_links = false
+bigfilechunking = false
+blacklisted_files = []
+undelete = true
+versioning = true
+archivers = [
+ { enabled = true, version = "2.0.0", formats = [
+ "tar",
+ "zip",
+ ], archiver_url = "/archiver", max_num_files = "10000", max_size = "1073741824" },
+]
+favorites = true
+
+[http.services.ocs.capabilities.capabilities.dav]
+
+[http.services.ocs.capabilities.capabilities.files_sharing]
+api_enabled = true
+resharing = true
+deny_access = true
+resharing_default = false
+group_sharing = true
+auto_accept_share = true
+share_with_group_members_only = true
+share_with_membership_groups_only = true
+default_permissions = 22
+search_min_length = 3
+
+[http.services.ocs.capabilities.capabilities.files_sharing.public]
+enabled = true
+send_mail = true
+social_share = true
+upload = true
+multiple = true
+supports_upload_only = true
+password = { enforced = false, enforced_for = { read_only = false, read_write = false, upload_only = false } }
+expire_date = { enabled = true }
+can_edit = true
+can_contribute = false
+
+[http.services.ocs.capabilities.capabilities.files_sharing.user]
+send_mail = true
+profile_picture = false
+settings = [{ enabled = true, version = "1.0.0" }]
+
+[http.services.ocs.capabilities.capabilities.files_sharing.user_enumeration]
+enabled = true
+group_members_only = true
+
+[http.services.ocs.capabilities.capabilities.files_sharing.federation]
+outgoing = true
+incoming = true
+
+[http.services.ocs.capabilities.capabilities.spaces]
+enabled = false
+projects = true
+
+[http.services.ocs.capabilities.version]
+edition = "reva"
+major = 10
+minor = 0
+micro = 11
+string = "10.0.11"
+
+[http.services.ocdav]
+address = ":443"
+insecure = true
+
+[http.services.prometheus]
+address = ":443"
+
+#[http.services.ui]
+#address = ":443"
+
+[http.middlewares.cors]
+allowed_origins = ["*"]
+allowed_methods = ["OPTIONS", "LOCK", "GET", "HEAD", "POST", "DELETE", "PROPPATCH", "COPY", "MOVE", "UNLOCK", "PROPFIND", "MKCOL", "REPORT", "SEARCH", "PUT"]
+allowed_headers = ["Accept", "Accept-Language", "Authorization", "Content-Language", "Content-Type", "Depth", "OCS-APIREQUEST", "Referer", "sec-ch-ua", "sec-ch-ua-mobile", "sec-ch-ua-platform", "User-Agent", "X-Requested-With"]
+debug = true
+exposed_headers = []
+
+[http.middlewares.log]
diff --git a/examples/cernbox/keycloak/cernbox.json b/examples/cernbox/keycloak/cernbox.json
new file mode 100644
index 0000000000..c7fd64f6a8
--- /dev/null
+++ b/examples/cernbox/keycloak/cernbox.json
@@ -0,0 +1,2366 @@
+{
+ "users": [
+ {
+ "id": "einstein",
+ "username": "einstein",
+ "enabled": true,
+ "email": "einstein@cern.ch",
+ "emailVerified": true,
+ "firstName": "Albert",
+ "lastName": "Einstein",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "relativity"
+ }
+ ],
+ "realmRoles": [
+ "user"
+ ],
+ "clientRoles": {
+ "account": [
+ "view-profile",
+ "manage-account"
+ ]
+ }
+ },
+ {
+ "id": "marie",
+ "username": "marie",
+ "enabled": true,
+ "email": "marie@cern.ch",
+ "emailVerified": true,
+ "firstName": "Marie",
+ "lastName": "Curie",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "radioactivity"
+ }
+ ],
+ "realmRoles": [
+ "user"
+ ],
+ "clientRoles": {
+ "account": [
+ "view-profile",
+ "manage-account"
+ ]
+ }
+ },
+ {
+ "id": "richard",
+ "username": "richard",
+ "enabled": true,
+ "email": "richard@cern.ch",
+ "emailVerified": true,
+ "firstName": "Richard",
+ "lastName": "Feynman",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "superfluidity"
+ }
+ ],
+ "realmRoles": [
+ "user"
+ ],
+ "clientRoles": {
+ "account": [
+ "view-profile",
+ "manage-account"
+ ]
+ }
+ }
+ ],
+ "id": "d5f44848-3fec-4333-bcc5-2e69b96a7652",
+ "realm": "cernbox",
+ "displayName": "Keycloak",
+ "displayNameHtml": "
Keycloak
",
+ "notBefore": 0,
+ "defaultSignatureAlgorithm": "RS256",
+ "revokeRefreshToken": false,
+ "refreshTokenMaxReuse": 0,
+ "accessTokenLifespan": 60,
+ "accessTokenLifespanForImplicitFlow": 900,
+ "ssoSessionIdleTimeout": 1800,
+ "ssoSessionMaxLifespan": 36000,
+ "ssoSessionIdleTimeoutRememberMe": 0,
+ "ssoSessionMaxLifespanRememberMe": 0,
+ "offlineSessionIdleTimeout": 2592000,
+ "offlineSessionMaxLifespanEnabled": false,
+ "offlineSessionMaxLifespan": 5184000,
+ "clientSessionIdleTimeout": 0,
+ "clientSessionMaxLifespan": 0,
+ "clientOfflineSessionIdleTimeout": 0,
+ "clientOfflineSessionMaxLifespan": 0,
+ "accessCodeLifespan": 60,
+ "accessCodeLifespanUserAction": 300,
+ "accessCodeLifespanLogin": 1800,
+ "actionTokenGeneratedByAdminLifespan": 43200,
+ "actionTokenGeneratedByUserLifespan": 300,
+ "oauth2DeviceCodeLifespan": 600,
+ "oauth2DevicePollingInterval": 5,
+ "enabled": true,
+ "sslRequired": "external",
+ "registrationAllowed": false,
+ "registrationEmailAsUsername": false,
+ "rememberMe": false,
+ "verifyEmail": false,
+ "loginWithEmailAllowed": true,
+ "duplicateEmailsAllowed": false,
+ "resetPasswordAllowed": false,
+ "editUsernameAllowed": false,
+ "bruteForceProtected": false,
+ "permanentLockout": false,
+ "maxFailureWaitSeconds": 900,
+ "minimumQuickLoginWaitSeconds": 60,
+ "waitIncrementSeconds": 60,
+ "quickLoginCheckMilliSeconds": 1000,
+ "maxDeltaTimeSeconds": 43200,
+ "failureFactor": 30,
+ "roles": {
+ "realm": [
+ {
+ "id": "1dd251c9-5c68-413f-8035-34e0336922c6",
+ "name": "offline_access",
+ "description": "${role_offline-access}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651",
+ "attributes": {}
+ },
+ {
+ "id": "e7ace27c-cfc7-4f34-8df8-bd32e0da15ce",
+ "name": "create-realm",
+ "description": "${role_create-realm}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651",
+ "attributes": {}
+ },
+ {
+ "id": "4985b709-d1cd-4583-b733-71f51c9566d2",
+ "name": "default-roles-cernbox",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "composites": {
+ "realm": [
+ "offline_access",
+ "uma_authorization"
+ ],
+ "client": {
+ "account": [
+ "view-profile",
+ "manage-account"
+ ]
+ }
+ },
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651",
+ "attributes": {}
+ },
+ {
+ "id": "abf70cc8-2287-44d5-be0e-0307ff3c0b40",
+ "name": "admin",
+ "description": "${role_admin}",
+ "composite": true,
+ "composites": {
+ "realm": [
+ "create-realm"
+ ],
+ "client": {
+ "cernbox-realm": [
+ "view-authorization",
+ "query-groups",
+ "view-clients",
+ "view-identity-providers",
+ "view-realm",
+ "manage-authorization",
+ "manage-identity-providers",
+ "impersonation",
+ "query-users",
+ "query-realms",
+ "view-users",
+ "view-events",
+ "manage-users",
+ "manage-clients",
+ "manage-realm",
+ "create-client",
+ "query-clients",
+ "manage-events"
+ ]
+ }
+ },
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651",
+ "attributes": {}
+ },
+ {
+ "id": "b2efa3fd-321d-47ae-a1c6-5efb5f0973f7",
+ "name": "uma_authorization",
+ "description": "${role_uma_authorization}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651",
+ "attributes": {}
+ }
+ ],
+ "client": {
+ "cernbox-oidc": [],
+ "security-admin-console": [],
+ "admin-cli": [],
+ "account-console": [],
+ "broker": [
+ {
+ "id": "cac7cb03-5144-41f1-bba8-70b51b34905c",
+ "name": "read-token",
+ "description": "${role_read-token}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e1bb70a9-5439-48ca-b8d6-ef27a3b6f624",
+ "attributes": {}
+ }
+ ],
+ "cernbox-realm": [
+ {
+ "id": "efaa23b3-3208-4346-92f9-49d36b714be0",
+ "name": "query-groups",
+ "description": "${role_query-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "19fa9af2-cd74-4889-9241-ccad973264de",
+ "name": "view-authorization",
+ "description": "${role_view-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "b7514426-db73-47a8-9a99-9a93821cca24",
+ "name": "view-clients",
+ "description": "${role_view-clients}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "cernbox-realm": [
+ "query-clients"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "1d65b3fc-4845-48a8-a00b-a11b5665e87c",
+ "name": "view-identity-providers",
+ "description": "${role_view-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "2427f9b7-2d1e-4ca4-b1d8-bcd878346016",
+ "name": "manage-authorization",
+ "description": "${role_manage-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "0b2f3aff-9562-4dc7-8b34-d0ad592307c3",
+ "name": "view-realm",
+ "description": "${role_view-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "31d61639-2493-4fa5-a8e5-6222a0204cb0",
+ "name": "manage-identity-providers",
+ "description": "${role_manage-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "7a3514c1-1fdf-40a7-8b26-3bfd78d13d8f",
+ "name": "impersonation",
+ "description": "${role_impersonation}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "fd468050-a5f7-4da9-b476-d701e228c1ba",
+ "name": "query-realms",
+ "description": "${role_query-realms}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "9776694a-3e2d-481b-83f9-8b8468ef5cba",
+ "name": "query-users",
+ "description": "${role_query-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "8c752cb9-e159-473d-8bd9-3db4b578204c",
+ "name": "view-users",
+ "description": "${role_view-users}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "cernbox-realm": [
+ "query-groups",
+ "query-users"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "0226e0da-1a5f-4671-aa3f-ea628ac6840b",
+ "name": "view-events",
+ "description": "${role_view-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "720bdf01-f1eb-4f7d-a2f1-674b8fba8ae5",
+ "name": "manage-users",
+ "description": "${role_manage-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "9bc4aaf1-1db4-4125-be4d-3ea9fdfdcddc",
+ "name": "manage-clients",
+ "description": "${role_manage-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "75e4d613-14b5-413b-b5ed-7323658d7237",
+ "name": "manage-realm",
+ "description": "${role_manage-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "2a3cc632-ed73-42de-a876-ed8a9d67927e",
+ "name": "create-client",
+ "description": "${role_create-client}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "afc7679e-a9d4-4deb-9a32-8b19060385c0",
+ "name": "query-clients",
+ "description": "${role_query-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ },
+ {
+ "id": "90b2fe49-3132-42b3-99a4-be0350d68f12",
+ "name": "manage-events",
+ "description": "${role_manage-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "attributes": {}
+ }
+ ],
+ "account": [
+ {
+ "id": "381fbd9e-352d-472a-88b3-b8dc1e593ed7",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "4fe6afe5-239c-4749-ad96-d607126aa370",
+ "name": "view-groups",
+ "description": "${role_view-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "0e82842e-091b-485a-b0b8-2f6679c29bda",
+ "name": "view-applications",
+ "description": "${role_view-applications}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "467762f3-ef88-483d-8c03-3f7880b22400",
+ "name": "view-consent",
+ "description": "${role_view-consent}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "9fea9466-3e06-4970-80e5-9f7afbd1eb80",
+ "name": "manage-account-links",
+ "description": "${role_manage-account-links}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "873fd72b-e3f0-4825-a2d2-c88c362bb102",
+ "name": "delete-account",
+ "description": "${role_delete-account}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "2f726de0-782b-4678-ab2e-c40d27a74968",
+ "name": "manage-consent",
+ "description": "${role_manage-consent}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": [
+ "view-consent"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ },
+ {
+ "id": "99141aca-0e6e-4e5a-97c1-5d255bece148",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": [
+ "manage-account-links"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "attributes": {}
+ }
+ ]
+ }
+ },
+ "groups": [
+ {
+ "id": "21b3d522-c35f-42da-9b35-8396c081fe13",
+ "name": "philosophy-haters",
+ "path": "/philosophy-haters",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "a3ee97a0-52ee-4dbc-9f9b-7c0f4851ad9e",
+ "name": "physics-lovers",
+ "path": "/physics-lovers",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "9d992aa0-be4c-4abc-9076-7493eec5cd5d",
+ "name": "polonium-lovers",
+ "path": "/polonium-lovers",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "3807793f-1d9b-4e79-ac30-0787127529e3",
+ "name": "quantum-lovers",
+ "path": "/quantum-lovers",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "9753c519-3a2e-4ae2-9114-eb00b3609709",
+ "name": "radium-lovers",
+ "path": "/radium-lovers",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "dce7f132-2fce-4958-9b51-c7b493133bec",
+ "name": "sailing-lovers",
+ "path": "/sailing-lovers",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ },
+ {
+ "id": "9f434513-d831-481f-9870-5d5504a795be",
+ "name": "violin-haters",
+ "path": "/violin-haters",
+ "attributes": {},
+ "realmRoles": [],
+ "clientRoles": {},
+ "subGroups": []
+ }
+ ],
+ "defaultRole": {
+ "id": "4985b709-d1cd-4583-b733-71f51c9566d2",
+ "name": "default-roles-cernbox",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "clientRole": false,
+ "containerId": "d5f44848-3fec-4333-bcc5-2e69b96a7651"
+ },
+ "requiredCredentials": [
+ "password"
+ ],
+ "otpPolicyType": "totp",
+ "otpPolicyAlgorithm": "HmacSHA1",
+ "otpPolicyInitialCounter": 0,
+ "otpPolicyDigits": 6,
+ "otpPolicyLookAheadWindow": 1,
+ "otpPolicyPeriod": 30,
+ "otpPolicyCodeReusable": false,
+ "otpSupportedApplications": [
+ "totpAppMicrosoftAuthenticatorName",
+ "totpAppFreeOTPName",
+ "totpAppGoogleName"
+ ],
+ "webAuthnPolicyRpEntityName": "keycloak",
+ "webAuthnPolicySignatureAlgorithms": [
+ "ES256"
+ ],
+ "webAuthnPolicyRpId": "",
+ "webAuthnPolicyAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyRequireResidentKey": "not specified",
+ "webAuthnPolicyUserVerificationRequirement": "not specified",
+ "webAuthnPolicyCreateTimeout": 0,
+ "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyAcceptableAaguids": [],
+ "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
+ "webAuthnPolicyPasswordlessSignatureAlgorithms": [
+ "ES256"
+ ],
+ "webAuthnPolicyPasswordlessRpId": "",
+ "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
+ "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
+ "webAuthnPolicyPasswordlessCreateTimeout": 0,
+ "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyPasswordlessAcceptableAaguids": [],
+ "scopeMappings": [
+ {
+ "clientScope": "offline_access",
+ "roles": [
+ "offline_access"
+ ]
+ }
+ ],
+ "clientScopeMappings": {
+ "account": [
+ {
+ "client": "account-console",
+ "roles": [
+ "manage-account",
+ "view-groups"
+ ]
+ }
+ ]
+ },
+ "clients": [
+ {
+ "id": "2c60f6c5-2ffb-4d0b-be37-997d79f2eac5",
+ "clientId": "account",
+ "name": "${client_account}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/cernbox/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/realms/cernbox/account/*"
+ ],
+ "webOrigins": [
+ "*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "b2a1c6b7-014c-4c58-be28-4cd1575fd919",
+ "clientId": "account-console",
+ "name": "${client_account-console}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/cernbox/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/realms/cernbox/account/*"
+ ],
+ "webOrigins": [
+ "*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+",
+ "pkce.code.challenge.method": "S256"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "protocolMappers": [
+ {
+ "id": "d71aeba9-ff27-44de-97d8-47cdded9bf61",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {}
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "026086ee-7521-4554-ab3e-c00d6a280373",
+ "clientId": "admin-cli",
+ "name": "${client_admin-cli}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": false,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {},
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "e1bb70a9-5439-48ca-b8d6-ef27a3b6f624",
+ "clientId": "broker",
+ "name": "${client_broker}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": true,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": false,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {},
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "acd215fa-56d6-4617-a55a-8eb8b98af4cb",
+ "clientId": "cernbox-oidc",
+ "name": "cernbox-oidc",
+ "description": "",
+ "rootUrl": "",
+ "adminUrl": "",
+ "baseUrl": "",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "https://cernbox1.docker/*",
+ "https://cernbox2.docker/*"
+ ],
+ "webOrigins": [
+ "*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": true,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": true,
+ "protocol": "openid-connect",
+ "attributes": {
+ "oidc.ciba.grant.enabled": "false",
+ "oauth2.device.authorization.grant.enabled": "false",
+ "display.on.consent.screen": "false",
+ "backchannel.logout.session.required": "true",
+ "backchannel.logout.revoke.offline.tokens": "false"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": true,
+ "nodeReRegistrationTimeout": -1,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "5a911287-7ef9-43c3-9eea-401a137c83b8",
+ "clientId": "cernbox-realm",
+ "name": "cernbox Realm",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": true,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": false,
+ "frontchannelLogout": false,
+ "attributes": {},
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "2299ba69-8859-4d59-b8ba-60d384b614d8",
+ "clientId": "security-admin-console",
+ "name": "${client_security-admin-console}",
+ "rootUrl": "${authAdminUrl}",
+ "baseUrl": "/admin/cernbox/console/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/admin/cernbox/console/*"
+ ],
+ "webOrigins": [
+ "*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+",
+ "pkce.code.challenge.method": "S256"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "protocolMappers": [
+ {
+ "id": "64cf2e6f-7ae8-415e-bc2a-22e15b3b8845",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "locale",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "locale",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ }
+ ],
+ "clientScopes": [
+ {
+ "id": "f5343f9d-c533-4a6b-b7cf-b243f3387212",
+ "name": "microprofile-jwt",
+ "description": "Microprofile - JWT built-in scope",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "881c1d36-008a-4961-9986-61f99e49e4e7",
+ "name": "groups",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "multivalued": "true",
+ "user.attribute": "foo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "groups",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "ffe50a2d-8a86-4b7b-94b2-a1482894f6f1",
+ "name": "upn",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "upn",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "0ac8f26d-382c-4d35-b63a-a06b90642a6c",
+ "name": "profile",
+ "description": "OpenID Connect built-in scope: profile",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "true",
+ "consent.screen.text": "${profileScopeConsentText}"
+ },
+ "protocolMappers": [
+ {
+ "id": "d61366bf-6d3c-440b-9d15-d146ee97d278",
+ "name": "middle name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "middleName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "middle_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "953283ab-f632-4cca-b71e-c68456e37e69",
+ "name": "website",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "website",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "website",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "8ffcb8e2-d342-4434-8cfa-066629984272",
+ "name": "zoneinfo",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "zoneinfo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "zoneinfo",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "49e5f7e1-614a-4ac8-b59c-7e7ca4be8c75",
+ "name": "full name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-full-name-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "userinfo.token.claim": "true"
+ }
+ },
+ {
+ "id": "3377051b-b951-4120-a577-e9c8371dfe53",
+ "name": "birthdate",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "birthdate",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "birthdate",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "d89e8483-bdd2-4074-8f09-a30ae5297492",
+ "name": "profile",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "profile",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "profile",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "526a9d58-b944-4607-883c-cb853e7bf0d4",
+ "name": "username",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "preferred_username",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "4db59ddf-4955-4aca-854a-83fea782de39",
+ "name": "picture",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "picture",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "picture",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "2d4f9809-38ad-4e88-b6d5-6990417b17e3",
+ "name": "nickname",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "nickname",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "nickname",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "869c9612-3fba-4618-80ba-b166bfa2df31",
+ "name": "gender",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "gender",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "gender",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "3c9425f1-edf1-4daa-b78f-e925aa4a6e5f",
+ "name": "given name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "firstName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "given_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "d97c24af-3dbd-453f-aa41-d0ee4ffced63",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "locale",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "locale",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "284f7309-06e7-4a9f-8974-a0695418e3bc",
+ "name": "updated at",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "updatedAt",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "updated_at",
+ "jsonType.label": "long"
+ }
+ },
+ {
+ "id": "053b3b02-3c69-490d-9382-be565e3cc6a0",
+ "name": "family name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "lastName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "family_name",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "02b6c73f-cc0b-416f-9c7f-c99fd68f7ce4",
+ "name": "phone",
+ "description": "OpenID Connect built-in scope: phone",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "true",
+ "consent.screen.text": "${phoneScopeConsentText}"
+ },
+ "protocolMappers": [
+ {
+ "id": "57dfff04-f55d-4e47-96d1-482f61f7d439",
+ "name": "phone number verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumberVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number_verified",
+ "jsonType.label": "boolean"
+ }
+ },
+ {
+ "id": "51c7f33d-1b01-4be6-96a5-7544e55a5cd1",
+ "name": "phone number",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumber",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "f7fed9dc-6317-44e6-9b5d-56c0fa13a287",
+ "name": "web-origins",
+ "description": "OpenID Connect scope for add allowed web origins to the access token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "false",
+ "consent.screen.text": ""
+ },
+ "protocolMappers": [
+ {
+ "id": "b7eb5197-7719-4b8e-a5ab-6a362b5a2d24",
+ "name": "allowed web origins",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-allowed-origins-mapper",
+ "consentRequired": false,
+ "config": {}
+ }
+ ]
+ },
+ {
+ "id": "d498fcee-d13b-4bba-85c3-c95f2acddf02",
+ "name": "email",
+ "description": "OpenID Connect built-in scope: email",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "true",
+ "consent.screen.text": "${emailScopeConsentText}"
+ },
+ "protocolMappers": [
+ {
+ "id": "1fbd2ac9-3d32-4095-b366-e75cd7aaaf76",
+ "name": "email verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "emailVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email_verified",
+ "jsonType.label": "boolean"
+ }
+ },
+ {
+ "id": "ff61a997-a211-4978-9212-5c27b886582e",
+ "name": "email",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "userinfo.token.claim": "true",
+ "user.attribute": "email",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "c79cedd3-a3ee-4f8a-96d7-81e514e8cbe9",
+ "name": "address",
+ "description": "OpenID Connect built-in scope: address",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "true",
+ "consent.screen.text": "${addressScopeConsentText}"
+ },
+ "protocolMappers": [
+ {
+ "id": "6a2e64d1-d27e-4663-9d5e-ac0d78a3c5ea",
+ "name": "address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-address-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute.formatted": "formatted",
+ "user.attribute.country": "country",
+ "user.attribute.postal_code": "postal_code",
+ "userinfo.token.claim": "true",
+ "user.attribute.street": "street",
+ "id.token.claim": "true",
+ "user.attribute.region": "region",
+ "access.token.claim": "true",
+ "user.attribute.locality": "locality"
+ }
+ }
+ ]
+ },
+ {
+ "id": "71c4630e-b700-4874-a6d5-16c58a59853a",
+ "name": "roles",
+ "description": "OpenID Connect scope for add user roles to the access token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "true",
+ "consent.screen.text": "${rolesScopeConsentText}"
+ },
+ "protocolMappers": [
+ {
+ "id": "3e22efbe-796f-4956-87a8-7472fd49bfa3",
+ "name": "client roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-client-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "access.token.claim": "true",
+ "claim.name": "resource_access.${client_id}.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ },
+ {
+ "id": "a1884484-24d0-46b6-9040-ec38c2ec5571",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {}
+ },
+ {
+ "id": "0d05297b-71e5-4185-b81a-7c95f2c0eb3b",
+ "name": "realm roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "access.token.claim": "true",
+ "claim.name": "realm_access.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "d3f84c0a-6962-4d49-ae88-a7f2a41aaed4",
+ "name": "role_list",
+ "description": "SAML role list",
+ "protocol": "saml",
+ "attributes": {
+ "consent.screen.text": "${samlRoleListScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "679fda99-b976-4c81-adc3-2cd1c687c59e",
+ "name": "role list",
+ "protocol": "saml",
+ "protocolMapper": "saml-role-list-mapper",
+ "consentRequired": false,
+ "config": {
+ "single": "false",
+ "attribute.nameformat": "Basic",
+ "attribute.name": "Role"
+ }
+ }
+ ]
+ },
+ {
+ "id": "603e8df0-3016-410b-9816-abb32d0e3071",
+ "name": "offline_access",
+ "description": "OpenID Connect built-in scope: offline_access",
+ "protocol": "openid-connect",
+ "attributes": {
+ "consent.screen.text": "${offlineAccessScopeConsentText}",
+ "display.on.consent.screen": "true"
+ }
+ },
+ {
+ "id": "4e34e7a6-ae0e-47b0-b3c5-02a608306dd2",
+ "name": "acr",
+ "description": "OpenID Connect scope for add acr (authentication context class reference) to the token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "53e7d18c-7aae-4516-b1c8-89f91b7b86a7",
+ "name": "acr loa level",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-acr-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ }
+ ]
+ }
+ ],
+ "defaultDefaultClientScopes": [
+ "role_list",
+ "profile",
+ "email",
+ "roles",
+ "web-origins",
+ "acr"
+ ],
+ "defaultOptionalClientScopes": [
+ "offline_access",
+ "address",
+ "phone",
+ "microprofile-jwt"
+ ],
+ "browserSecurityHeaders": {
+ "contentSecurityPolicyReportOnly": "",
+ "xContentTypeOptions": "nosniff",
+ "xRobotsTag": "none",
+ "xFrameOptions": "SAMEORIGIN",
+ "xXSSProtection": "1; mode=block",
+ "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
+ "strictTransportSecurity": "max-age=31536000; includeSubDomains"
+ },
+ "smtpServer": {},
+ "eventsEnabled": false,
+ "eventsListeners": [
+ "jboss-logging"
+ ],
+ "enabledEventTypes": [],
+ "adminEventsEnabled": false,
+ "adminEventsDetailsEnabled": false,
+ "identityProviders": [],
+ "identityProviderMappers": [],
+ "components": {
+ "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
+ {
+ "id": "47d66138-4145-480c-875d-363b5bc31838",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "oidc-full-name-mapper",
+ "saml-role-list-mapper",
+ "oidc-usermodel-attribute-mapper",
+ "saml-user-attribute-mapper",
+ "saml-user-property-mapper",
+ "oidc-usermodel-property-mapper",
+ "oidc-sha256-pairwise-sub-mapper",
+ "oidc-address-mapper"
+ ]
+ }
+ },
+ {
+ "id": "96d7ddd5-fe73-4217-a753-a4e202a8adb7",
+ "name": "Full Scope Disabled",
+ "providerId": "scope",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ },
+ {
+ "id": "a74b31e3-b126-4fc5-8825-96debd1f2471",
+ "name": "Consent Required",
+ "providerId": "consent-required",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ },
+ {
+ "id": "82f1d154-61a3-4b6a-b1f3-811a2e86aa85",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "b262c386-dc0f-42cd-aefb-72d0c34a24dc",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "da1c03ae-7796-476b-b80b-76be91c5cd77",
+ "name": "Max Clients Limit",
+ "providerId": "max-clients",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "max-clients": [
+ "200"
+ ]
+ }
+ },
+ {
+ "id": "26eec102-eae6-463c-91e3-7333c627394c",
+ "name": "Trusted Hosts",
+ "providerId": "trusted-hosts",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "host-sending-registration-request-must-match": [
+ "true"
+ ],
+ "client-uris-must-match": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "648e6fc9-8363-4a1d-9f0a-d67a13c9edc9",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "saml-user-attribute-mapper",
+ "oidc-full-name-mapper",
+ "oidc-address-mapper",
+ "saml-role-list-mapper",
+ "oidc-usermodel-property-mapper",
+ "saml-user-property-mapper",
+ "oidc-sha256-pairwise-sub-mapper",
+ "oidc-usermodel-attribute-mapper"
+ ]
+ }
+ }
+ ],
+ "org.keycloak.keys.KeyProvider": [
+ {
+ "id": "cc8a50f7-176a-4776-9201-5050dc802f0e",
+ "name": "rsa-generated",
+ "providerId": "rsa-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ]
+ }
+ },
+ {
+ "id": "ce297a71-1c56-4b0f-87c0-8818c2977e2a",
+ "name": "hmac-generated",
+ "providerId": "hmac-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ],
+ "algorithm": [
+ "HS256"
+ ]
+ }
+ },
+ {
+ "id": "85ce5401-1789-4e98-a14b-06ba935be78b",
+ "name": "aes-generated",
+ "providerId": "aes-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ]
+ }
+ },
+ {
+ "id": "c99a1812-0f86-4120-8538-4c53f7be670f",
+ "name": "rsa-enc-generated",
+ "providerId": "rsa-enc-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ],
+ "algorithm": [
+ "RSA-OAEP"
+ ]
+ }
+ }
+ ]
+ },
+ "internationalizationEnabled": false,
+ "supportedLocales": [],
+ "authenticationFlows": [
+ {
+ "id": "4d4d9b4d-a081-4008-ad19-b81e3a8a9ab6",
+ "alias": "Account verification options",
+ "description": "Method with which to verity the existing account",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-email-verification",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Verify Existing Account by Re-authentication",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "03928ec0-305d-4bba-a832-156a37250460",
+ "alias": "Authentication Options",
+ "description": "Authentication options.",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "basic-auth",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "basic-auth-otp",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-spnego",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 30,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "a94107c0-ae9e-4459-9b54-bdee3e5a2b2b",
+ "alias": "Browser - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-otp-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "356c5010-27d7-4c7a-a055-3880d3dc41fd",
+ "alias": "Direct Grant - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "direct-grant-validate-otp",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "b6d4fff4-9930-4030-95ce-09f5f18f6846",
+ "alias": "First broker login - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-otp-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "2c021c56-981a-4b35-945f-20e15305ef0a",
+ "alias": "Handle Existing Account",
+ "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-confirm-link",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Account verification options",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "28d90136-9d52-41d4-b6a5-c410879516d7",
+ "alias": "Reset - Conditional OTP",
+ "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-otp",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "ed8520ee-e733-40ad-8ad0-f66b803a85a6",
+ "alias": "User creation or linking",
+ "description": "Flow for the existing/non-existing user alternatives",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticatorConfig": "create unique user config",
+ "authenticator": "idp-create-user-if-unique",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Handle Existing Account",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "beb2fdfe-e8ad-4fe7-b0a3-1cbc7cd232e5",
+ "alias": "Verify Existing Account by Re-authentication",
+ "description": "Reauthentication of existing account",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-username-password-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "First broker login - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "3583e59f-8e55-41fa-8eb2-61dffa918f69",
+ "alias": "browser",
+ "description": "browser based authentication",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "auth-cookie",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-spnego",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "identity-provider-redirector",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 25,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 30,
+ "autheticatorFlow": true,
+ "flowAlias": "forms",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "da4eaa2e-2f57-4f3b-bf87-8bdeb25e6cc8",
+ "alias": "clients",
+ "description": "Base authentication for clients",
+ "providerId": "client-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "client-secret",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-jwt",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-secret-jwt",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 30,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-x509",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 40,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "61da9559-fcc0-411b-862c-1ecff20403a0",
+ "alias": "direct grant",
+ "description": "OpenID Connect Resource Owner Grant",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "direct-grant-validate-username",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "direct-grant-validate-password",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 30,
+ "autheticatorFlow": true,
+ "flowAlias": "Direct Grant - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "75f9bd37-f7fb-44d2-a3c7-ee022e31080d",
+ "alias": "docker auth",
+ "description": "Used by Docker clients to authenticate against the IDP",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "docker-http-basic-authenticator",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "0daeca0e-d7dc-40b9-8116-83307bf06c06",
+ "alias": "first broker login",
+ "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticatorConfig": "review profile config",
+ "authenticator": "idp-review-profile",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "User creation or linking",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "fad12cb4-3a42-4cad-b589-3ff705ae41c0",
+ "alias": "forms",
+ "description": "Username, password, otp and other auth forms.",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "auth-username-password-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Browser - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "6674479a-9f99-430c-a774-6b44e36f45b1",
+ "alias": "http challenge",
+ "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "no-cookie-redirect",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Authentication Options",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "fa0fc72c-92eb-42f2-942a-0e687b9ad184",
+ "alias": "registration",
+ "description": "registration flow",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "registration-page-form",
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": true,
+ "flowAlias": "registration form",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "b07a2cd8-d159-449c-b239-5b077e075d6e",
+ "alias": "registration form",
+ "description": "registration form",
+ "providerId": "form-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "registration-user-creation",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-profile-action",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 40,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-password-action",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 50,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-recaptcha-action",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 60,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "711099a9-985d-4978-a45c-88f03ac0097a",
+ "alias": "reset credentials",
+ "description": "Reset credentials for a user if they forgot their password or something",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "reset-credentials-choose-user",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-credential-email",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-password",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 30,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 40,
+ "autheticatorFlow": true,
+ "flowAlias": "Reset - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "13954e50-cc94-48d8-a181-7e0aa8f4b105",
+ "alias": "saml ecp",
+ "description": "SAML ECP Profile Authentication Flow",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "http-basic-authenticator",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ }
+ ],
+ "authenticatorConfig": [
+ {
+ "id": "88978291-3ecf-4139-a7e7-589bcce17e8d",
+ "alias": "create unique user config",
+ "config": {
+ "require.password.update.after.registration": "false"
+ }
+ },
+ {
+ "id": "785a91df-7692-43f1-9dd6-6bfcb0375e69",
+ "alias": "review profile config",
+ "config": {
+ "update.profile.on.first.login": "missing"
+ }
+ }
+ ],
+ "requiredActions": [
+ {
+ "alias": "CONFIGURE_TOTP",
+ "name": "Configure OTP",
+ "providerId": "CONFIGURE_TOTP",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 10,
+ "config": {}
+ },
+ {
+ "alias": "TERMS_AND_CONDITIONS",
+ "name": "Terms and Conditions",
+ "providerId": "TERMS_AND_CONDITIONS",
+ "enabled": false,
+ "defaultAction": false,
+ "priority": 20,
+ "config": {}
+ },
+ {
+ "alias": "UPDATE_PASSWORD",
+ "name": "Update Password",
+ "providerId": "UPDATE_PASSWORD",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 30,
+ "config": {}
+ },
+ {
+ "alias": "UPDATE_PROFILE",
+ "name": "Update Profile",
+ "providerId": "UPDATE_PROFILE",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 40,
+ "config": {}
+ },
+ {
+ "alias": "VERIFY_EMAIL",
+ "name": "Verify Email",
+ "providerId": "VERIFY_EMAIL",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 50,
+ "config": {}
+ },
+ {
+ "alias": "delete_account",
+ "name": "Delete Account",
+ "providerId": "delete_account",
+ "enabled": false,
+ "defaultAction": false,
+ "priority": 60,
+ "config": {}
+ },
+ {
+ "alias": "webauthn-register",
+ "name": "Webauthn Register",
+ "providerId": "webauthn-register",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 70,
+ "config": {}
+ },
+ {
+ "alias": "webauthn-register-passwordless",
+ "name": "Webauthn Register Passwordless",
+ "providerId": "webauthn-register-passwordless",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 80,
+ "config": {}
+ },
+ {
+ "alias": "update_user_locale",
+ "name": "Update User Locale",
+ "providerId": "update_user_locale",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 1000,
+ "config": {}
+ }
+ ],
+ "browserFlow": "browser",
+ "registrationFlow": "registration",
+ "directGrantFlow": "direct grant",
+ "resetCredentialsFlow": "reset credentials",
+ "clientAuthenticationFlow": "clients",
+ "dockerAuthenticationFlow": "docker auth",
+ "attributes": {
+ "cibaBackchannelTokenDeliveryMode": "poll",
+ "cibaExpiresIn": "120",
+ "cibaAuthRequestedUserHint": "login_hint",
+ "parRequestUriLifespan": "60",
+ "cibaInterval": "5",
+ "realmReusableOtpCode": "false"
+ },
+ "keycloakVersion": "21.1.1",
+ "userManagedAccessAllowed": false,
+ "clientProfiles": {
+ "profiles": []
+ },
+ "clientPolicies": {
+ "policies": []
+ }
+}
diff --git a/examples/cernbox/nginx/mime.types b/examples/cernbox/nginx/mime.types
new file mode 100644
index 0000000000..0908f64c42
--- /dev/null
+++ b/examples/cernbox/nginx/mime.types
@@ -0,0 +1,96 @@
+ types {
+ text/html html htm shtml;
+ text/css css;
+ text/xml xml;
+ image/gif gif;
+ image/jpeg jpeg jpg;
+ application/javascript js mjs;
+ application/atom+xml atom;
+ application/rss+xml rss;
+
+ text/mathml mml;
+ text/plain txt;
+ text/vnd.sun.j2me.app-descriptor jad;
+ text/vnd.wap.wml wml;
+ text/x-component htc;
+
+ image/png png;
+ image/svg+xml svg svgz;
+ image/tiff tif tiff;
+ image/vnd.wap.wbmp wbmp;
+ image/webp webp;
+ image/x-icon ico;
+ image/x-jng jng;
+ image/x-ms-bmp bmp;
+
+ font/woff woff;
+ font/woff2 woff2;
+
+ application/java-archive jar war ear;
+ application/json json;
+ application/mac-binhex40 hqx;
+ application/msword doc;
+ application/pdf pdf;
+ application/postscript ps eps ai;
+ application/rtf rtf;
+ application/vnd.apple.mpegurl m3u8;
+ application/vnd.google-earth.kml+xml kml;
+ application/vnd.google-earth.kmz kmz;
+ application/vnd.ms-excel xls;
+ application/vnd.ms-fontobject eot;
+ application/vnd.ms-powerpoint ppt;
+ application/vnd.oasis.opendocument.graphics odg;
+ application/vnd.oasis.opendocument.presentation odp;
+ application/vnd.oasis.opendocument.spreadsheet ods;
+ application/vnd.oasis.opendocument.text odt;
+ application/vnd.openxmlformats-officedocument.presentationml.presentation
+ pptx;
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
+ xlsx;
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document
+ docx;
+ application/vnd.wap.wmlc wmlc;
+ application/x-7z-compressed 7z;
+ application/x-cocoa cco;
+ application/x-java-archive-diff jardiff;
+ application/x-java-jnlp-file jnlp;
+ application/x-makeself run;
+ application/x-perl pl pm;
+ application/x-pilot prc pdb;
+ application/x-rar-compressed rar;
+ application/x-redhat-package-manager rpm;
+ application/x-sea sea;
+ application/x-shockwave-flash swf;
+ application/x-stuffit sit;
+ application/x-tcl tcl tk;
+ application/x-x509-ca-cert der pem crt;
+ application/x-xpinstall xpi;
+ application/xhtml+xml xhtml;
+ application/xspf+xml xspf;
+ application/zip zip;
+
+ application/octet-stream bin exe dll;
+ application/octet-stream deb;
+ application/octet-stream dmg;
+ application/octet-stream iso img;
+ application/octet-stream msi msp msm;
+
+ audio/midi mid midi kar;
+ audio/mpeg mp3;
+ audio/ogg ogg;
+ audio/x-m4a m4a;
+ audio/x-realaudio ra;
+
+ video/3gpp 3gpp 3gp;
+ video/mp2t ts;
+ video/mp4 mp4;
+ video/mpeg mpeg mpg;
+ video/quicktime mov;
+ video/webm webm;
+ video/x-flv flv;
+ video/x-m4v m4v;
+ video/x-mng mng;
+ video/x-ms-asf asx asf;
+ video/x-ms-wmv wmv;
+ video/x-msvideo avi;
+}
diff --git a/examples/cernbox/nginx/nginx.conf b/examples/cernbox/nginx/nginx.conf
new file mode 100644
index 0000000000..7d82347969
--- /dev/null
+++ b/examples/cernbox/nginx/nginx.conf
@@ -0,0 +1,167 @@
+
+user nginx;
+worker_processes auto;
+
+pid /var/run/nginx.pid;
+
+# Load dynamic modules. See /usr/share/nginx/README.dynamic.
+include /usr/share/nginx/modules/*.conf;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ map $status $loggable {
+ ~^[23] 0;
+ default 1;
+ }
+
+ access_log /var/log/nginx/access.log combined if=$loggable;
+
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+ client_max_body_size 8G;
+ #gzip on;
+
+ # avoid nginx buffering all the payload, only available in > 1.7
+ proxy_buffering off;
+ proxy_request_buffering off;
+
+ include /etc/nginx/conf.d/*.conf;
+
+ upstream revad {
+ server your.revad.org:443;
+ }
+
+ server {
+ listen 80;
+ server_name localhost;
+ return 301 https://$host$request_uri;
+ }
+
+ # https://ssl-config.mozilla.org/#server=nginx&version=1.20.1&config=intermediate&openssl=1.0.2k&guideline=5.6
+ server {
+ listen 443 ssl http2;
+ server_name localhost;
+
+ ssl_certificate your.cert.pem;
+ ssl_certificate_key your.key.pem;
+
+ ssl_session_timeout 5m;
+
+ ssl_protocols TLSv1.2;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
+ ssl_prefer_server_ciphers off;
+
+ proxy_connect_timeout 1200;
+ proxy_send_timeout 1200;
+ proxy_read_timeout 1200;
+ send_timeout 1200;
+ proxy_buffering off;
+ proxy_request_buffering off;
+
+ location ^~ /data {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ~ /s/[^/]*/download {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /ocs/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /dav/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /webdav/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /remote.php/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /preferences {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /otg {
+ return 204;
+ }
+
+ location ^~ /app/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /ocm/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ~ ^/sciencemesh/ {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /ocm-provider {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ^~ /status.php {
+ proxy_pass https://revad;
+ proxy_set_header Host $host;
+ }
+
+ location ~ ^/(js|css|icons|fonts|assets)/ {
+ root /var/www/web;
+ add_header Cache-Control "public, max-age=31536000, immutable";
+ etag off;
+ gzip_static on;
+ }
+
+ location ^~ /cernbox {
+ root /var/www;
+ add_header Cache-Control "no-cache";
+ add_header Access-Control-Allow-Origin "https://idp.docker:8443" always;
+ etag off;
+ gzip_static on;
+ }
+
+ location / {
+ root /var/www/web;
+ add_header Cache-Control "no-cache";
+ add_header Access-Control-Allow-Origin "https://idp.docker:8443" always;
+ etag off;
+ gzip_static on;
+ try_files $uri /index.html;
+ }
+
+# location / {
+# proxy_pass https://revad/ui;
+# proxy_set_header Host $host;
+# }
+ }
+}
diff --git a/examples/cernbox/users.demo.json b/examples/cernbox/users.demo.json
new file mode 100644
index 0000000000..8452f49a08
--- /dev/null
+++ b/examples/cernbox/users.demo.json
@@ -0,0 +1,80 @@
+[
+ {
+ "id": {
+ "opaque_id": "4c510ada-c86b-4815-8820-42cdf82c3d51",
+ "idp": "cernbox",
+ "type": 1
+ },
+ "username": "einstein",
+ "secret": "relativity",
+ "mail": "einstein@cern.ch",
+ "display_name": "Albert Einstein",
+ "groups": ["sailing-lovers", "violin-haters", "physics-lovers"],
+ "opaque": {
+ "map": {
+ "gid": {
+ "_comment": "decodes to 987",
+ "decoder":"plain",
+ "value":"OTg3"
+ },
+ "uid":{
+ "_comment": "decodes to 123",
+ "decoder":"plain",
+ "value":"MTIz"
+ }
+ }
+ }
+ },
+ {
+ "id": {
+ "opaque_id": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c",
+ "idp": "cernbox",
+ "type": 1
+ },
+ "username": "marie",
+ "secret": "radioactivity",
+ "mail": "marie@cern.ch",
+ "display_name": "Marie Curie",
+ "groups": ["radium-lovers", "polonium-lovers", "physics-lovers"],
+ "opaque": {
+ "map": {
+ "gid": {
+ "_comment": "decodes to 987",
+ "decoder":"plain",
+ "value":"OTg3"
+ },
+ "uid":{
+ "_comment": "decodes to 456",
+ "decoder":"plain",
+ "value":"NDU2"
+ }
+ }
+ }
+ },
+ {
+ "id": {
+ "opaque_id": "932b4540-8d16-481e-8ef4-588e4b6b151c",
+ "idp": "cernbox",
+ "type": 1
+ },
+ "username": "richard",
+ "secret": "superfluidity",
+ "mail": "richard@cern.ch",
+ "display_name": "Richard Feynman",
+ "groups": ["quantum-lovers", "philosophy-haters", "physics-lovers"],
+ "opaque": {
+ "map": {
+ "gid": {
+ "_comment": "decodes to 135",
+ "decoder":"plain",
+ "value":"MTM1"
+ },
+ "uid":{
+ "_comment": "decodes to 246",
+ "decoder":"plain",
+ "value":"MjQ2"
+ }
+ }
+ }
+ }
+]
diff --git a/examples/cernbox/web.json b/examples/cernbox/web.json
new file mode 100644
index 0000000000..d712acca60
--- /dev/null
+++ b/examples/cernbox/web.json
@@ -0,0 +1,73 @@
+{
+ "server": "https://your.nginx.org",
+ "theme": "https://your.nginx.org/cernbox/theme-cernbox-0.2.0/theme.json",
+ "version": "0.0.0",
+ "openIdConnect": {
+ "metadata_url": "https://idp.docker:8443/realms/cernbox/.well-known/openid-configuration",
+ "authority": "https://idp.docker:8443/realms/cernbox",
+ "client_id": "cernbox-oidc",
+ "response_type": "code",
+ "scope": "openid profile email"
+ },
+ "options": {
+ "contextHelpers": true,
+ "enableAdvancedTable": true,
+ "cernFeatures": true,
+ "hoverableQuickActions": true,
+ "disableFeedbackLink": true,
+ "homeFolder": "/{{.Id}}",
+ "previewFileMimeTypes" : [
+ "image/gif",
+ "image/png",
+ "image/jpeg"
+ ],
+ "openAppsInTab": true,
+ "editor": {
+ "autosaveEnabled": true,
+ "autosaveInterval": 120
+ },
+ "breadcrumbItemMaxLength": 30,
+ "routing": {
+ "idBased": false
+ },
+ "upload": {
+ "xhr": {
+ "timeout": 3600000
+ }
+ }
+ },
+ "apps": [
+ "files",
+ "search",
+ "preview",
+ "external",
+ "pdf-viewer",
+ "sciencemesh-app"
+ ],
+ "external_apps": [
+ {
+ "id": "jupyter",
+ "path": "/cernbox/jupyter-2.0.0/main.js"
+ },
+ {
+ "id": "rootjs",
+ "path": "/cernbox/rootjs-2.0.0/main.js"
+ },
+ {
+ "id": "ifc-js",
+ "path": "/cernbox/ifc-js-2.0.2/main.js"
+ },
+ {
+ "id": "top-bar",
+ "path": "/cernbox/top-bar-1.0.0/main.js"
+ },
+ {
+ "id": "text-editor",
+ "path": "web-app-text-editor",
+ "config": {
+ "primaryExtensions": ["txt"],
+ "extraExtensions": ["htm", "html", "css", "js", "ts", "php", "yml", "toml", "qml", "pl", "pm", "sh", "tcsh", "zsh", "conf", "ini", "inf", "make", "cmake", "mk", "in"]
+ }
+ }
+ ]
+}
diff --git a/examples/ocm/server-1.toml b/examples/ocm/server-1.toml
index a4cb399427..424f5254b6 100644
--- a/examples/ocm/server-1.toml
+++ b/examples/ocm/server-1.toml
@@ -166,7 +166,7 @@ driver = "ocmreceived"
address = "0.0.0.0:8080"
expose_recipient_display_name = true
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
ocm_prefix = "ocm"
provider = "reva@cern"
endpoint = "http://localhost:{{ http.services.ocm.address.port }}"
diff --git a/examples/ocm/server-2.toml b/examples/ocm/server-2.toml
index 7b9bf24cb3..66a00b2249 100644
--- a/examples/ocm/server-2.toml
+++ b/examples/ocm/server-2.toml
@@ -166,7 +166,7 @@ driver = "ocmreceived"
address = "0.0.0.0:80"
expose_recipient_display_name = true
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
ocm_prefix = "ocm"
provider = "reva@cesnet"
endpoint = "http://localhost:{{ http.services.ocm.address.port }}"
diff --git a/examples/sciencemesh/custom-mime-types-demo.json b/examples/sciencemesh/custom-mime-types-demo.json
new file mode 100644
index 0000000000..390947ec09
--- /dev/null
+++ b/examples/sciencemesh/custom-mime-types-demo.json
@@ -0,0 +1,3 @@
+{
+ ".zmd": "application/compressed-markdown"
+}
diff --git a/examples/sciencemesh/metrics.json b/examples/sciencemesh/metrics.json
new file mode 100644
index 0000000000..da85d866d9
--- /dev/null
+++ b/examples/sciencemesh/metrics.json
@@ -0,0 +1,5 @@
+{
+ "cs3_org_sciencemesh_site_total_num_users": 0,
+ "cs3_org_sciencemesh_site_total_num_groups": 0,
+ "cs3_org_sciencemesh_site_total_amount_storage": 0
+}
\ No newline at end of file
diff --git a/examples/sciencemesh/providers.testnet.json b/examples/sciencemesh/providers.testnet.json
new file mode 100644
index 0000000000..1960fdd63c
--- /dev/null
+++ b/examples/sciencemesh/providers.testnet.json
@@ -0,0 +1,34 @@
+[
+ { "domain": "revad1.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revad1.docker/ocm/" }, "host": "revad1.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://revad1.docker/remote.php/webdav/" }, "host": "revad1.docker" }
+ ] },
+ { "domain": "revad2.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revad2.docker/ocm/" }, "host": "revad2.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://revad2.docker/remote.php/webdav/" }, "host": "revad2.docker" }
+ ] },
+ { "domain": "revanextcloud1.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revanextcloud1.docker/ocm/" }, "host": "revanextcloud1.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://nc1.docker/remote.php/webdav/" }, "host": "nextcloud1.docker" }
+ ] },
+ { "domain": "revanextcloud2.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revanextcloud2.docker/ocm/" }, "host": "revanextcloud2.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://nc2.docker/remote.php/webdav/" }, "host": "nextcloud2.docker" }
+ ] },
+ { "domain": "revaowncloud1.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revaowncloud1.docker/ocm/" }, "host": "revaowncloud1.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://owncloud1.docker/remote.php/webdav/" }, "host": "owncloud1.docker" }
+ ] },
+ { "domain": "revaowncloud2.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revaowncloud2.docker/ocm/" }, "host": "revaowncloud2.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://owncloud2.docker/remote.php/dav/" }, "host": "owncloud2.docker" }
+ ] },
+ { "domain": "revacernbox1.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revacernbox1.docker/ocm/" }, "host": "revacernbox1.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://cernbox1.docker/remote.php/dav/" }, "host": "cernbox1.docker" }
+ ] },
+ { "domain": "revacernbox2.docker", "services": [
+ { "endpoint": { "type": { "name": "OCM" }, "path": "https://revacernbox2.docker/ocm/" }, "host": "revacernbox2.docker" },
+ { "endpoint": { "type": { "name": "Webdav" }, "path": "https://cernbox2.docker/remote.php/dav/" }, "host": "cernbox2.docker" }
+ ] }
+]
diff --git a/examples/sciencemesh/sciencemesh-apps.toml b/examples/sciencemesh/sciencemesh-apps.toml
new file mode 100644
index 0000000000..00bef3e888
--- /dev/null
+++ b/examples/sciencemesh/sciencemesh-apps.toml
@@ -0,0 +1,49 @@
+## Example configuration for the ScienceMesh app in ownCloud 10 / Nextcloud - Apps support
+#
+## This configuration file is to be used to enable Apps support in ScienceMesh.
+## To contextualize this configuration for your deployment, please follow these steps:
+#
+# 1. In the [vars] section below, replace `your.revad.org` with your actual domain
+# 2. Populate `wopi_endpoint` with your wopiserver endpoint
+# 3. Define a shared secret, and match it with the secret defined in the wopiserver
+
+
+[vars]
+internal_gateway = "your.revad.org"
+provider_domain = "your.revad.org"
+wopi_endpoint = "http://your.wopi.org:8880"
+wopi_shared_secret = "shared-secret-2"
+
+[log]
+level = "debug"
+
+[shared]
+gatewaysvc = "{{ vars.provider_domain }}:19000"
+
+[[grpc.services.appprovider]]
+driver = "wopi"
+custom_mime_types_json = "/etc/revad/custom-mime-types-demo.json"
+mime_types = ["application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.presentation", "text/rtf"]
+app_provider_url = "{{ grpc.services.appprovider[0].address }}"
+language = "en-GB"
+
+[grpc.services.appprovider.drivers.wopi]
+iop_secret = "{{ vars.wopi_shared_secret }}"
+wopi_url = "{{ vars.wopi_endpoint }}"
+app_name = "Collabora"
+app_url = "http://collabora.docker:9980"
+app_int_url = "http://collabora.docker:9980"
+
+
+# [[grpc.services.appprovider]]
+# driver = "wopi"
+# custom_mime_types_json = "/etc/revad/custom-mime-types-demo.json"
+# mime_types = ["text/markdown", "application/compressed-markdown", "text/plain"]
+# app_provider_url = "{{ grpc.services.appprovider[1].address }}"
+#
+# [grpc.services.appprovider.drivers.wopi]
+# iop_secret = "{{ vars.wopi_shared_secret }}"
+# wopi_url = "{{ vars.wopi_endpoint }}"
+# app_name = "CodiMD"
+# app_url = "https://codimd.docker"
+# app_int_url = "https://codimd.docker"
diff --git a/examples/sciencemesh/sciencemesh.toml b/examples/sciencemesh/sciencemesh.toml
new file mode 100644
index 0000000000..d9fc44bfa9
--- /dev/null
+++ b/examples/sciencemesh/sciencemesh.toml
@@ -0,0 +1,288 @@
+## Example configuration for the ScienceMesh app in ownCloud 10 / Nextcloud
+#
+## To contextualize this configuration for your deployment, please follow these steps:
+#
+# 1. In the [vars] section below, replace `your.revad.org` with your actual domain
+# 2. If you have a Kubernetes deployment with an ingress and a route:
+# 2.1. Set the `external_reva_endpoint` var to your actual externally-visible route to reva
+# 3. Replace `your.efss.org` with the actual endpoint of your EFSS system
+# 4. Define appropriate secrets in the [vars] section: the `efss_shared_secret` must match the `oc_appconfig.configvalue` in your EFSS DB for `oc_appconfig.app_id` = `sciencemesh`
+# 5. Provide appropriate SSL full chain certificate and key files in the [http] section
+#
+# If you want to terminate the SSL connection to reva at your reverse proxy system
+# (e.g. at your Kubernetes ingress), then you can configure reva to use http instead.
+# For that, you need to follow these steps:
+#
+# 1. Remove the `certfile` and `keyfile` entries from the [http] section
+# 2. Replace the https port `443` with a port number of your choice everywhere you find it
+# 3. Look for `data_server_url` and replace the `https://localhost` address as indicated
+
+
+[vars]
+internal_gateway = "your.revad.org"
+provider_domain = "your.revad.org"
+external_reva_endpoint = "https://your.revad.org" # append here any route if applicable
+efss_sciencemesh_endpoint = "https://your.efss.org/index.php/apps/sciencemesh/"
+machine_api_key = "machine-api-key"
+efss_shared_secret = "shared-secret-1"
+
+[http]
+certfile = "/etc/tls/your.revad.ssl.crt"
+keyfile = "/etc/tls/your.revad.ssl.key"
+
+[log]
+level = "debug"
+
+[shared]
+gatewaysvc = "{{ vars.internal_gateway }}:19000"
+
+[grpc.services.gateway]
+address = ":19000"
+authregistrysvc = "{{ grpc.services.authregistry.address }}"
+appregistrysvc = "{{ grpc.services.appregistry.address }}"
+storageregistrysvc = "{{ grpc.services.storageregistry.address }}"
+preferencessvc = "{{ grpc.services.userprovider.address }}"
+userprovidersvc = "{{ grpc.services.userprovider.address }}"
+usershareprovidersvc = "{{ grpc.services.usershareprovider.address }}"
+ocmcoresvc = "{{ grpc.services.ocmcore.address }}"
+ocmshareprovidersvc = "{{ grpc.services.ocmshareprovider.address }}"
+ocminvitemanagersvc = "{{ grpc.services.ocminvitemanager.address }}"
+ocmproviderauthorizersvc = "{{ grpc.services.ocmproviderauthorizer.address }}"
+datagateway = "https://{{ http.services.datagateway.address }}/data"
+
+transfer_expires = 6 # give it a moment
+commit_share_to_storage_grant = true
+commit_share_to_storage_ref = true
+
+
+[grpc.services.appregistry]
+driver = "static"
+
+[grpc.services.appregistry.drivers.static]
+mime_types = [
+ {"mime_type" = "text/plain", "extension" = "txt", "name" = "Text file", "description" = "Text file", "allow_creation" = true},
+ {"mime_type" = "text/markdown", "extension" = "md", "name" = "Markdown file", "description" = "Markdown file", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.text", "extension" = "odt", "name" = "OpenDocument", "description" = "OpenDocument text document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.spreadsheet", "extension" = "ods", "name" = "OpenSpreadsheet", "description" = "OpenDocument spreadsheet document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.oasis.opendocument.presentation", "extension" = "odp", "name" = "OpenPresentation", "description" = "OpenDocument presentation document", "default_app" = "Collabora", "allow_creation" = true},
+ {"mime_type" = "application/vnd.jupyter", "extension" = "ipynb", "name" = "Jupyter Notebook", "description" = "Jupyter Notebook"}
+]
+
+
+### AUTH PROVIDERS ###
+
+[grpc.services.authregistry]
+driver = "static"
+
+[grpc.services.authregistry.drivers.static.rules]
+basic = "{{ grpc.services.authprovider[0].address }}"
+machine = "{{ grpc.services.authprovider[1].address }}"
+ocmshares = "{{ grpc.services.authprovider[2].address }}"
+
+[[grpc.services.authprovider]]
+auth_manager = "nextcloud"
+
+[grpc.services.authprovider.auth_managers.nextcloud]
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+
+[[grpc.services.authprovider]]
+auth_manager = "machine"
+
+[grpc.services.authprovider.auth_managers.machine]
+api_key = "{{ vars.machine_api_key }}"
+gateway_addr = "{{ vars.internal_gateway }}:19000"
+
+[[grpc.services.authprovider]]
+auth_manager = "ocmshares"
+
+
+### STORAGE PROVIDERS ###
+
+[grpc.services.storageregistry]
+driver = "static"
+
+[grpc.services.storageregistry.drivers.static]
+home_provider = "/home"
+
+[grpc.services.storageregistry.drivers.static.rules]
+"/home" = {"address" = "{{ grpc.services.storageprovider[0].address }}"}
+"nextcloud" = {"address" = "{{ grpc.services.storageprovider[0].address }}"}
+"/ocm" = {"address" = "{{ grpc.services.storageprovider[1].address }}"}
+"ocm" = {"address" = "{{ grpc.services.storageprovider[1].address }}"}
+
+[[grpc.services.storageprovider]]
+driver = "nextcloud"
+mount_id = "nextcloud"
+expose_data_server = true
+enable_home_creation = false
+# replace https://localhost with http://localhost if reva does not serve https traffic
+data_server_url = "https://localhost:{{ http.services.dataprovider[0].address.port }}/data"
+
+[grpc.services.storageprovider.drivers.nextcloud]
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+
+[[grpc.services.storageprovider]]
+driver = "ocmoutcoming"
+mount_id = "ocm"
+mount_path = "/ocm"
+expose_data_server = true
+enable_home_creation = false
+data_server_url = "{{ vars.external_reva_endpoint }}/data"
+
+[grpc.services.storageprovider.drivers.ocmoutcoming]
+machine_secret = "{{ vars.machine_api_key }}"
+
+
+### OTHER PROVIDERS ###
+
+[grpc.services.usershareprovider]
+driver = "memory"
+
+[grpc.services.ocmcore]
+driver = "nextcloud"
+
+[grpc.services.ocmcore.drivers.nextcloud]
+host = "{{ vars.external_reva_endpoint }}"
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+
+[grpc.services.ocminvitemanager]
+# TODO the driver should be "nextcloud" once it is implemented
+driver = "json"
+provider_domain = "{{ vars.provider_domain }}"
+
+[grpc.services.ocmshareprovider]
+driver = "nextcloud"
+provider_domain = "{{ vars.provider_domain }}"
+webdav_endpoint = "{{ vars.external_reva_endpoint }}"
+webdav_prefix = "{{ vars.external_reva_endpoint }}/remote.php/dav/files"
+webapp_template = "{{ vars.external_reva_endpoint }}/external/sciencemesh/{{.Token}}/{relative-path-to-shared-resource}"
+
+[grpc.services.ocmshareprovider.drivers.nextcloud]
+webdav_host = "{{ vars.external_reva_endpoint }}"
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+mount_id = "nextcloud"
+
+[grpc.services.ocmproviderauthorizer]
+driver = "mentix"
+
+[grpc.services.ocmproviderauthorizer.drivers.mentix]
+url = "https://iop.sciencemesh.uni-muenster.de/iop/mentix/cs3"
+verify_request_hostname = true
+insecure = false
+timeout = 10
+refresh = 900
+
+[grpc.services.ocmproviderauthorizer.drivers.json]
+# this is used by the docker-based test deployment, not in production
+providers = "/etc/revad/providers.testnet.json"
+verify_request_hostname = true
+
+[grpc.services.userprovider]
+driver = "nextcloud"
+
+[grpc.services.userprovider.drivers.nextcloud]
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+
+[grpc.services.datatx]
+txdriver = "rclone"
+storagedriver = "json"
+remove_transfer_on_cancel = true
+
+[grpc.services.datatx.txdrivers.rclone]
+# rclone endpoint
+endpoint = "http://rclone.docker"
+# basic auth is used
+auth_user = "rcloneuser"
+auth_pass = "eilohtho9oTahsuongeeTh7reedahPo1Ohwi3aek"
+auth_header = "x-access-token"
+job_status_check_interval = 2000
+job_timeout = 120000
+storagedriver = "json"
+remove_transfer_job_on_cancel = true
+
+[grpc.services.datatx.storagedrivers.json]
+file = ""
+
+[grpc.services.datatx.txdrivers.rclone.storagedrivers.json]
+file = ""
+
+
+### HTTP ENDPOINTS ###
+
+[http.services.appprovider]
+address = ":443"
+insecure = true
+
+[http.services.datagateway]
+address = ":443"
+
+[[http.services.dataprovider]]
+driver = "nextcloud"
+
+[http.services.dataprovider.drivers.nextcloud]
+endpoint = "{{ vars.efss_sciencemesh_endpoint }}"
+shared_secret = "{{ vars.efss_shared_secret }}"
+mock_http = false
+
+[[http.services.dataprovider]]
+address = ":443"
+driver = "ocmoutcoming"
+
+[http.services.dataprovider.drivers.ocmoutcoming]
+machine_secret = "{{ vars.machine_api_key }}"
+
+[http.services.sciencemesh]
+address = ":443"
+provider_domain = "{{ vars.provider_domain }}"
+mesh_directory_url = "https://sciencemesh.cesnet.cz/iop/meshdir"
+ocm_mount_point = "/sciencemesh"
+
+[http.services.sciencemesh.smtp_credentials]
+disable_auth = true
+sender_mail = "sciencemesh@{{ vars.provider_domain }}"
+smtp_server = "smtp.{{ vars.provider_domain }}"
+smtp_port = 25
+
+[http.services.wellknown.ocmprovider]
+address = ":443"
+ocm_prefix = "ocm"
+provider = "Reva for ownCloud/Nextcloud"
+endpoint = "{{ vars.external_reva_endpoint }}"
+enable_webapp = true
+enable_datatx = true
+
+[http.services.ocm]
+address = ":443"
+prefix = "ocm"
+
+[http.services.ocm.config]
+host = "{{ vars.provider_domain }}"
+
+[http.services.ocs]
+address = ":443"
+prefix = "ocs"
+
+[http.services.ocdav]
+address = ":443"
+
+[http.services.prometheus]
+address = ":443"
+
+[http.services.metrics]
+address = ":443"
+metrics_data_driver_type = "json"
+metrics_data_location = "/etc/revad/metrics.json"
+metrics_record_interval = 5000
+
+[http.middlewares.cors]
+[http.middlewares.log]
diff --git a/examples/standalone/standalone.toml b/examples/standalone/standalone.toml
index 5a63df304b..e7e83ad461 100644
--- a/examples/standalone/standalone.toml
+++ b/examples/standalone/standalone.toml
@@ -17,6 +17,6 @@
[http.services.dataprovider]
[http.services.prometheus]
[http.services.ocm]
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
[http.services.ocdav]
[http.services.ocs]
diff --git a/examples/storage-references/gateway.toml b/examples/storage-references/gateway.toml
index c57d035e51..fff03471bc 100644
--- a/examples/storage-references/gateway.toml
+++ b/examples/storage-references/gateway.toml
@@ -57,7 +57,7 @@ app_url = "https://your-collabora-server.org:9980"
[http.services.datagateway]
[http.services.prometheus]
[http.services.ocm]
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
[http.services.ocdav]
[http.services.ocs]
diff --git a/examples/two-server-setup/gateway-1.toml b/examples/two-server-setup/gateway-1.toml
index 1d3414071c..7d5d08731a 100644
--- a/examples/two-server-setup/gateway-1.toml
+++ b/examples/two-server-setup/gateway-1.toml
@@ -84,7 +84,7 @@ address = "0.0.0.0:19001"
[http.services.datagateway]
[http.services.prometheus]
[http.services.ocm]
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
provider = "Reva-Server-1"
endpoint = "http://localhost:19001"
enable_webapp = true
diff --git a/examples/two-server-setup/gateway-2.toml b/examples/two-server-setup/gateway-2.toml
index 8361b3c7e8..bf3f22406d 100644
--- a/examples/two-server-setup/gateway-2.toml
+++ b/examples/two-server-setup/gateway-2.toml
@@ -84,7 +84,7 @@ address = "0.0.0.0:29001"
[http.services.datagateway]
[http.services.prometheus]
[http.services.ocm]
-[http.services.ocmprovider]
+[http.services.wellknown.ocmprovider]
provider = "Reva-Server-2"
endpoint = "http://localhost:29001"
enable_webapp = true
diff --git a/go.mod b/go.mod
index f19d0e6213..b0c6ae50ca 100644
--- a/go.mod
+++ b/go.mod
@@ -125,7 +125,7 @@ require (
go.opentelemetry.io/otel v1.23.1 // indirect
go.opentelemetry.io/otel/trace v1.23.1 // indirect
golang.org/x/mod v0.13.0 // indirect
- golang.org/x/net v0.22.0 // indirect
+ golang.org/x/net v0.23.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
diff --git a/go.sum b/go.sum
index a0e0b36431..e033f0747d 100644
--- a/go.sum
+++ b/go.sum
@@ -1731,8 +1731,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
-golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
-golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
diff --git a/internal/grpc/services/ocmcore/ocmcore.go b/internal/grpc/services/ocmcore/ocmcore.go
index 218e3a3890..81f6f038da 100644
--- a/internal/grpc/services/ocmcore/ocmcore.go
+++ b/internal/grpc/services/ocmcore/ocmcore.go
@@ -18,6 +18,8 @@
package ocmcore
+// This package implements the core OCM API for receiving external shares from remote EFSS systems.
+
import (
"context"
"fmt"
@@ -102,7 +104,7 @@ func (s *service) UnprotectedEndpoints() []string {
return []string{"/cs3.ocm.core.v1beta1.OcmCoreAPI/CreateOCMCoreShare"}
}
-// CreateOCMCoreShare is called when an OCM request comes into this reva instance from.
+// CreateOCMCoreShare is called when a remote OCM request comes into this reva instance.
func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCMCoreShareRequest) (*ocmcore.CreateOCMCoreShareResponse, error) {
if req.ShareType != ocm.ShareType_SHARE_TYPE_USER {
return nil, errtypes.NotSupported("share type not supported")
diff --git a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go
index ac7956f6ff..a4f0d44039 100644
--- a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go
+++ b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go
@@ -26,9 +26,9 @@ import (
invitepb "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
+ "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmd"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
- "github.com/cs3org/reva/pkg/ocm/client"
"github.com/cs3org/reva/pkg/ocm/invite"
"github.com/cs3org/reva/pkg/ocm/invite/repository/registry"
"github.com/cs3org/reva/pkg/plugin"
@@ -66,7 +66,7 @@ type config struct {
type service struct {
conf *config
repo invite.Repository
- ocmClient *client.OCMClient
+ ocmClient *ocmd.OCMClient
}
func (c *config) ApplyDefaults() {
@@ -110,12 +110,9 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) {
}
service := &service{
- conf: &c,
- repo: repo,
- ocmClient: client.New(&client.Config{
- Timeout: time.Duration(c.OCMClientTimeout) * time.Second,
- Insecure: c.OCMClientInsecure,
- }),
+ conf: &c,
+ repo: repo,
+ ocmClient: ocmd.NewClient(time.Duration(c.OCMClientTimeout)*time.Second, c.OCMClientInsecure),
}
return service, nil
}
@@ -166,7 +163,7 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite
return nil, err
}
- remoteUser, err := s.ocmClient.InviteAccepted(ctx, ocmEndpoint, &client.InviteAcceptedRequest{
+ remoteUser, err := s.ocmClient.InviteAccepted(ctx, ocmEndpoint, &ocmd.InviteAcceptedRequest{
Token: req.InviteToken.GetToken(),
RecipientProvider: s.conf.ProviderDomain,
UserID: user.GetId().GetOpaqueId(),
@@ -175,19 +172,19 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite
})
if err != nil {
switch {
- case errors.Is(err, client.ErrTokenInvalid):
+ case errors.Is(err, ocmd.ErrTokenInvalid):
return &invitepb.ForwardInviteResponse{
Status: status.NewInvalid(ctx, "token not valid"),
}, nil
- case errors.Is(err, client.ErrTokenNotFound):
+ case errors.Is(err, ocmd.ErrTokenNotFound):
return &invitepb.ForwardInviteResponse{
Status: status.NewNotFound(ctx, "token not found"),
}, nil
- case errors.Is(err, client.ErrUserAlreadyAccepted):
+ case errors.Is(err, ocmd.ErrUserAlreadyAccepted):
return &invitepb.ForwardInviteResponse{
Status: status.NewAlreadyExists(ctx, err, err.Error()),
}, nil
- case errors.Is(err, client.ErrServiceNotTrusted):
+ case errors.Is(err, ocmd.ErrServiceNotTrusted):
return &invitepb.ForwardInviteResponse{
Status: status.NewPermissionDenied(ctx, err, err.Error()),
}, nil
diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go
index 1de9c8427c..e26e7b02e5 100644
--- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go
+++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go
@@ -18,6 +18,9 @@
package ocmshareprovider
+// This package implements the OCM client API: it allows shares created on this Reva instance
+// to be sent to a remote EFSS system via OCM.
+
import (
"context"
"fmt"
@@ -38,7 +41,6 @@ import (
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
- "github.com/cs3org/reva/pkg/ocm/client"
"github.com/cs3org/reva/pkg/ocm/share"
"github.com/cs3org/reva/pkg/ocm/share/repository/registry"
"github.com/cs3org/reva/pkg/plugin"
@@ -70,13 +72,13 @@ type config struct {
GatewaySVC string `mapstructure:"gatewaysvc" validate:"required"`
ProviderDomain string `docs:"The same domain registered in the provider authorizer" mapstructure:"provider_domain" validate:"required"`
WebDAVEndpoint string `mapstructure:"webdav_endpoint" validate:"required"`
- WebappTemplate string `mapstructure:"webapp_template"`
+ WebappTemplate string `mapstructure:"webapp_template" validate:"required"`
}
type service struct {
conf *config
repo share.Repository
- client *client.OCMClient
+ client *ocmd.OCMClient
gateway gateway.GatewayAPIClient
webappTmpl *template.Template
walker walker.Walker
@@ -89,9 +91,6 @@ func (c *config) ApplyDefaults() {
if c.ClientTimeout == 0 {
c.ClientTimeout = 10
}
- if c.WebappTemplate == "" {
- c.WebappTemplate = "https://cernbox.cern.ch/external/sciencemesh/{{.Token}}{relative-path-to-shared-resource}"
- }
c.GatewaySVC = sharedconf.GetGatewaySVC(c.GatewaySVC)
}
@@ -119,11 +118,6 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) {
return nil, err
}
- client := client.New(&client.Config{
- Timeout: time.Duration(c.ClientTimeout) * time.Second,
- Insecure: c.ClientInsecure,
- })
-
gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySVC))
if err != nil {
return nil, err
@@ -135,10 +129,11 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) {
}
walker := walker.NewWalker(gateway)
+ ocmcl := ocmd.NewClient(time.Duration(c.ClientTimeout)*time.Second, c.ClientInsecure)
service := &service{
conf: &c,
repo: repo,
- client: client,
+ client: ocmcl,
gateway: gateway,
webappTmpl: tpl,
walker: walker,
@@ -178,13 +173,14 @@ func getResourceType(info *providerpb.ResourceInfo) string {
return "unknown"
}
-func (s *service) webdavURL(ctx context.Context, share *ocm.Share) string {
- // the url is in the form of https://cernbox.cern.ch/remote.php/dav/ocm/token
- p, _ := url.JoinPath(s.conf.WebDAVEndpoint, "/remote.php/dav/ocm", share.Token)
+func (s *service) webdavURL(share *ocm.Share) string {
+ // the url is expected to be in the form https://ourserver/remote.php/dav/ocm/{ShareId}, see c.WebdavRoot in ocmprovider.go
+ // TODO(lopresti) take the root from http.services.wellknown.ocmprovider's config
+ p, _ := url.JoinPath(s.conf.WebDAVEndpoint, "/remote.php/dav/ocm", share.Id.OpaqueId)
return p
}
-func (s *service) getWebdavProtocol(ctx context.Context, share *ocm.Share, m *ocm.AccessMethod_WebdavOptions) *ocmd.WebDAV {
+func (s *service) getWebdavProtocol(share *ocm.Share, m *ocm.AccessMethod_WebdavOptions) *ocmd.WebDAV {
var perms []string
if m.WebdavOptions.Permissions.InitiateFileDownload {
perms = append(perms, "read")
@@ -195,7 +191,7 @@ func (s *service) getWebdavProtocol(ctx context.Context, share *ocm.Share, m *oc
return &ocmd.WebDAV{
Permissions: perms,
- URL: s.webdavURL(ctx, share),
+ URL: s.webdavURL(share),
SharedSecret: share.Token,
}
}
@@ -233,7 +229,7 @@ func (s *service) getDataTransferProtocol(ctx context.Context, share *ocm.Share)
panic(err)
}
return &ocmd.Datatx{
- SourceURI: s.webdavURL(ctx, share),
+ SourceURI: s.webdavURL(share),
Size: size,
}
}
@@ -248,7 +244,7 @@ func (s *service) getProtocols(ctx context.Context, share *ocm.Share) ocmd.Proto
for _, m := range share.AccessMethods {
switch t := m.Term.(type) {
case *ocm.AccessMethod_WebdavOptions:
- p = append(p, s.getWebdavProtocol(ctx, share, t))
+ p = append(p, s.getWebdavProtocol(share, t))
case *ocm.AccessMethod_WebappOptions:
p = append(p, s.getWebappProtocol(share))
case *ocm.AccessMethod_TransferOptions:
@@ -323,7 +319,7 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq
}, nil
}
- newShareReq := &client.NewShareRequest{
+ newShareReq := &ocmd.NewShareRequest{
ShareWith: formatOCMUser(req.Grantee.GetUserId()),
Name: ocmshare.Name,
ProviderID: ocmshare.Id.OpaqueId,
@@ -348,11 +344,11 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq
newShareRes, err := s.client.NewShare(ctx, ocmEndpoint, newShareReq)
if err != nil {
switch {
- case errors.Is(err, client.ErrInvalidParameters):
+ case errors.Is(err, ocmd.ErrInvalidParameters):
return &ocm.CreateOCMShareResponse{
Status: status.NewInvalidArg(ctx, err.Error()),
}, nil
- case errors.Is(err, client.ErrServiceNotTrusted):
+ case errors.Is(err, ocmd.ErrServiceNotTrusted):
return &ocm.CreateOCMShareResponse{
Status: status.NewInvalidArg(ctx, err.Error()),
}, nil
diff --git a/internal/http/services/loader/loader.go b/internal/http/services/loader/loader.go
index 37eabde578..437b1e8b3f 100644
--- a/internal/http/services/loader/loader.go
+++ b/internal/http/services/loader/loader.go
@@ -29,7 +29,6 @@ import (
_ "github.com/cs3org/reva/internal/http/services/helloworld"
_ "github.com/cs3org/reva/internal/http/services/metrics"
_ "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmd"
- _ "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmprovider"
_ "github.com/cs3org/reva/internal/http/services/owncloud/ocapi"
_ "github.com/cs3org/reva/internal/http/services/owncloud/ocdav"
_ "github.com/cs3org/reva/internal/http/services/owncloud/ocgraph"
@@ -39,5 +38,6 @@ import (
_ "github.com/cs3org/reva/internal/http/services/pprof"
_ "github.com/cs3org/reva/internal/http/services/preferences"
_ "github.com/cs3org/reva/internal/http/services/prometheus"
+ _ "github.com/cs3org/reva/internal/http/services/wellknown"
// Add your own service here.
)
diff --git a/pkg/ocm/client/client.go b/internal/http/services/opencloudmesh/ocmd/client.go
similarity index 76%
rename from pkg/ocm/client/client.go
rename to internal/http/services/opencloudmesh/ocmd/client.go
index faeb28d183..106f51e5ad 100644
--- a/pkg/ocm/client/client.go
+++ b/internal/http/services/opencloudmesh/ocmd/client.go
@@ -16,7 +16,7 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
-package client
+package ocmd
import (
"bytes"
@@ -28,7 +28,7 @@ import (
"net/url"
"time"
- "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmd"
+ "github.com/cs3org/reva/internal/http/services/wellknown"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/pkg/errors"
@@ -59,62 +59,28 @@ type OCMClient struct {
client *http.Client
}
-// Config is the configuration to be used for the OCMClient.
-type Config struct {
- Timeout time.Duration
- Insecure bool
-}
-
-// New returns a new OCMClient.
-func New(c *Config) *OCMClient {
+// NewClient returns a new OCMClient.
+func NewClient(timeout time.Duration, insecure bool) *OCMClient {
tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure},
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
}
return &OCMClient{
- client: &http.Client{Transport: tr},
- }
-}
-
-// InviteAcceptedRequest contains the parameters for accepting
-// an invitation.
-type InviteAcceptedRequest struct {
- UserID string `json:"userID"`
- Email string `json:"email"`
- Name string `json:"name"`
- RecipientProvider string `json:"recipientProvider"`
- Token string `json:"token"`
-}
-
-// User contains the remote user's information when accepting
-// an invitation.
-type User struct {
- UserID string `json:"userID"`
- Email string `json:"email"`
- Name string `json:"name"`
-}
-
-func (r *InviteAcceptedRequest) toJSON() (io.Reader, error) {
- var b bytes.Buffer
- if err := json.NewEncoder(&b).Encode(r); err != nil {
- return nil, err
+ client: &http.Client{
+ Transport: tr,
+ Timeout: timeout,
+ },
}
- return &b, nil
}
-// InviteAccepted informs the sender that the invitation was accepted to start sharing
-// https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1invite-accepted/post
-func (c *OCMClient) InviteAccepted(ctx context.Context, endpoint string, r *InviteAcceptedRequest) (*User, error) {
- url, err := url.JoinPath(endpoint, "invite-accepted")
- if err != nil {
- return nil, err
- }
-
- body, err := r.toJSON()
+// Discover returns a number of properties used to discover the capabilities offered by a remote cloud storage.
+// https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get
+func (c *OCMClient) Discover(ctx context.Context, endpoint string) (*wellknown.OcmDiscoveryData, error) {
+ url, err := url.JoinPath(endpoint, "/ocm-provider")
if err != nil {
return nil, err
}
- req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body)
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, errors.Wrap(err, "error creating request")
}
@@ -126,48 +92,36 @@ func (c *OCMClient) InviteAccepted(ctx context.Context, endpoint string, r *Invi
}
defer resp.Body.Close()
- return c.parseInviteAcceptedResponse(resp)
-}
-
-func (c *OCMClient) parseInviteAcceptedResponse(r *http.Response) (*User, error) {
- switch r.StatusCode {
- case http.StatusOK:
- var u User
- if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
- return nil, errors.Wrap(err, "error decoding response body")
- }
- return &u, nil
- case http.StatusBadRequest:
- return nil, ErrTokenInvalid
- case http.StatusNotFound:
- return nil, ErrTokenNotFound
- case http.StatusConflict:
- return nil, ErrUserAlreadyAccepted
- case http.StatusForbidden:
- return nil, ErrServiceNotTrusted
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
}
- body, err := io.ReadAll(r.Body)
+ var disco wellknown.OcmDiscoveryData
+ err = json.Unmarshal(body, &disco)
if err != nil {
- return nil, errors.Wrap(err, "error decoding response body")
+ log := appctx.GetLogger(ctx)
+ log.Warn().Str("sender", endpoint).Str("response", string(body)).Msg("malformed response")
+ return nil, errtypes.InternalError("Invalid payload on OCM discovery")
}
- return nil, errtypes.InternalError(string(body))
+
+ return &disco, nil
}
// NewShareRequest contains the parameters for creating a new OCM share.
type NewShareRequest struct {
- ShareWith string `json:"shareWith"`
- Name string `json:"name"`
- Description string `json:"description"`
- ProviderID string `json:"providerId"`
- Owner string `json:"owner"`
- Sender string `json:"sender"`
- OwnerDisplayName string `json:"ownerDisplayName"`
- SenderDisplayName string `json:"senderDisplayName"`
- ShareType string `json:"shareType"`
- Expiration uint64 `json:"expiration"`
- ResourceType string `json:"resourceType"`
- Protocols ocmd.Protocols `json:"protocol"`
+ ShareWith string `json:"shareWith"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ ProviderID string `json:"providerId"`
+ Owner string `json:"owner"`
+ Sender string `json:"sender"`
+ OwnerDisplayName string `json:"ownerDisplayName"`
+ SenderDisplayName string `json:"senderDisplayName"`
+ ShareType string `json:"shareType"`
+ Expiration uint64 `json:"expiration"`
+ ResourceType string `json:"resourceType"`
+ Protocols Protocols `json:"protocol"`
}
func (r *NewShareRequest) toJSON() (io.Reader, error) {
@@ -197,7 +151,7 @@ func (c *OCMClient) NewShare(ctx context.Context, endpoint string, r *NewShareRe
}
log := appctx.GetLogger(ctx)
- log.Debug().Msgf("Sending OCM /shares POST to %s: %s", url, body)
+ log.Info().Str("url", url).Msgf("Sending OCM share: %s", body)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body)
if err != nil {
return nil, errors.Wrap(err, "error creating request")
@@ -232,34 +186,46 @@ func (c *OCMClient) parseNewShareResponse(r *http.Response) (*NewShareResponse,
return nil, errtypes.InternalError(string(body))
}
-// Capabilities contains a set of properties exposed by
-// a remote cloud storage.
-type Capabilities struct {
- Enabled bool `json:"enabled"`
- APIVersion string `json:"apiVersion"`
- EndPoint string `json:"endPoint"`
- Provider string `json:"provider"`
- ResourceTypes []struct {
- Name string `json:"name"`
- ShareTypes []string `json:"shareTypes"`
- Protocols struct {
- Webdav *string `json:"webdav"`
- Webapp *string `json:"webapp"`
- Datatx *string `json:"datatx"`
- } `json:"protocols"`
- } `json:"resourceTypes"`
- Capabilities []string `json:"capabilities"`
+// InviteAcceptedRequest contains the parameters for accepting
+// an invitation.
+type InviteAcceptedRequest struct {
+ UserID string `json:"userID"`
+ Email string `json:"email"`
+ Name string `json:"name"`
+ RecipientProvider string `json:"recipientProvider"`
+ Token string `json:"token"`
}
-// Discovery returns a number of properties used to discover the capabilities offered by a remote cloud storage.
-// https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get
-func (c *OCMClient) Discovery(ctx context.Context, endpoint string) (*Capabilities, error) {
- url, err := url.JoinPath(endpoint, "shares")
+// User contains the remote user's information when accepting
+// an invitation.
+type User struct {
+ UserID string `json:"userID"`
+ Email string `json:"email"`
+ Name string `json:"name"`
+}
+
+func (r *InviteAcceptedRequest) toJSON() (io.Reader, error) {
+ var b bytes.Buffer
+ if err := json.NewEncoder(&b).Encode(r); err != nil {
+ return nil, err
+ }
+ return &b, nil
+}
+
+// InviteAccepted informs the sender that the invitation was accepted to start sharing
+// https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1invite-accepted/post
+func (c *OCMClient) InviteAccepted(ctx context.Context, endpoint string, r *InviteAcceptedRequest) (*User, error) {
+ url, err := url.JoinPath(endpoint, "invite-accepted")
if err != nil {
return nil, err
}
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
+ body, err := r.toJSON()
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body)
if err != nil {
return nil, errors.Wrap(err, "error creating request")
}
@@ -271,10 +237,30 @@ func (c *OCMClient) Discovery(ctx context.Context, endpoint string) (*Capabiliti
}
defer resp.Body.Close()
- var cap Capabilities
- if err := json.NewDecoder(resp.Body).Decode(&c); err != nil {
- return nil, err
+ return c.parseInviteAcceptedResponse(resp)
+}
+
+func (c *OCMClient) parseInviteAcceptedResponse(r *http.Response) (*User, error) {
+ switch r.StatusCode {
+ case http.StatusOK:
+ var u User
+ if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
+ return nil, errors.Wrap(err, "error decoding response body")
+ }
+ return &u, nil
+ case http.StatusBadRequest:
+ return nil, ErrTokenInvalid
+ case http.StatusNotFound:
+ return nil, ErrTokenNotFound
+ case http.StatusConflict:
+ return nil, ErrUserAlreadyAccepted
+ case http.StatusForbidden:
+ return nil, ErrServiceNotTrusted
}
- return &cap, nil
+ body, err := io.ReadAll(r.Body)
+ if err != nil {
+ return nil, errors.Wrap(err, "error decoding response body")
+ }
+ return nil, errtypes.InternalError(string(body))
}
diff --git a/internal/http/services/opencloudmesh/ocmd/shares.go b/internal/http/services/opencloudmesh/ocmd/shares.go
index a48f040f7e..954e72ccae 100644
--- a/internal/http/services/opencloudmesh/ocmd/shares.go
+++ b/internal/http/services/opencloudmesh/ocmd/shares.go
@@ -21,7 +21,6 @@ package ocmd
import (
"encoding/json"
"fmt"
- "io"
"mime"
"net/http"
"path/filepath"
@@ -37,13 +36,11 @@ import (
ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
- ocmproviderhttp "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmprovider"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
"github.com/cs3org/reva/internal/http/services/reqres"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
- "github.com/cs3org/reva/pkg/httpclient"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/utils"
"github.com/go-playground/validator/v10"
@@ -282,43 +279,21 @@ func discoverOcmWebdavRoot(r *http.Request) (string, error) {
log := appctx.GetLogger(ctx)
log.Debug().Str("sender", r.Host).Msg("received OCM 1.0 share, attempting to discover sender endpoint")
- httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, r.Host+"/ocm-provider", nil)
+ ocmClient := NewClient(time.Duration(10)*time.Second, true)
+ ocmCaps, err := ocmClient.Discover(ctx, r.Host)
if err != nil {
+ log.Warn().Str("sender", r.Host).Err(err).Msg("failed to discover OCM sender")
return "", err
}
- httpClient := httpclient.New(
- httpclient.Timeout(time.Duration(10 * int64(time.Second))),
- )
- httpRes, err := httpClient.Do(httpReq)
- if err != nil {
- return "", errors.Wrap(err, "failed to contact OCM sender server")
- }
- defer httpRes.Body.Close()
-
- if httpRes.StatusCode != http.StatusOK {
- return "", errtypes.InternalError("Invalid HTTP response on OCM discovery")
- }
- body, err := io.ReadAll(httpRes.Body)
- if err != nil {
- return "", err
- }
-
- var result ocmproviderhttp.DiscoveryData
- err = json.Unmarshal(body, &result)
- if err != nil {
- log.Warn().Str("sender", r.Host).Str("response", string(body)).Msg("malformed response")
- return "", errtypes.InternalError("Invalid payload on OCM discovery")
- }
-
- for _, t := range result.ResourceTypes {
+ for _, t := range ocmCaps.ResourceTypes {
webdavRoot, ok := t.Protocols["webdav"]
if ok {
// assume the first resourceType that exposes a webdav root is OK to use: as a matter of fact,
// no implementation exists yet that exposes multiple resource types with different roots.
- return filepath.Join(result.Endpoint, webdavRoot), nil
+ return filepath.Join(ocmCaps.Endpoint, webdavRoot), nil
}
}
- log.Warn().Str("sender", r.Host).Str("response", string(body)).Msg("missing webdav root")
+ log.Warn().Str("sender", r.Host).Interface("response", ocmCaps).Msg("missing webdav root")
return "", errtypes.NotFound("WebDAV root not found on OCM discovery")
}
diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go
index 57c662b5db..222f8461a9 100644
--- a/internal/http/services/owncloud/ocdav/dav.go
+++ b/internal/http/services/owncloud/ocdav/dav.go
@@ -216,24 +216,36 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
return
}
- // OC10 and Nextcloud (OCM 1.0) are using basic auth for carrying the
- // shared token.
- var token string
- username, _, ok := r.BasicAuth()
- if ok {
- // OCM 1.0
- token = username
- r.URL.Path = filepath.Join("/", token, r.URL.Path)
- ctx = context.WithValue(ctx, ctxOCM10, true)
+ var token, ocmshare string
+ // OCM v1.1 (OCIS et al.).
+ bearer := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
+ if bearer != "" {
+ // Bearer token is the shared secret, path is /{shareId}/path/to/resource.
+ // Here we're keeping the simpler public-share model, where the internal routing is done via the token,
+ // therefore we strip the shareId and reinject the token.
+ // TODO(lopresti) We should instead perform a lookup via shareId and leave the token just for auth.
+ var relPath string
+ token = bearer
+ ocmshare, relPath = router.ShiftPath(r.URL.Path)
+ r.URL.Path = filepath.Join("/", token, relPath)
} else {
- token, _ = router.ShiftPath(r.URL.Path)
- ctx = context.WithValue(ctx, ctxOCM10, false)
+ username, _, ok := r.BasicAuth()
+ if ok {
+ // OCM v1.0 (OC10 and Nextcloud) uses basic auth for carrying the shared secret,
+ // and does not pass the shareId.
+ token = username
+ r.URL.Path = filepath.Join("/", token, r.URL.Path)
+ } else {
+ // compatibility for ScienceMesh: no auth, shared secret is the first element
+ // of the path, the shareId is not given. Leave the URL as is.
+ token = strings.Split(r.URL.Path, "/")[1]
+ }
}
- authRes, err := handleOCMAuth(ctx, c, token)
+ authRes, err := handleOCMAuth(ctx, c, ocmshare, token)
switch {
case err != nil:
- log.Error().Err(err).Msg("error during ocm authentication")
+ log.Error().Err(err).Msg("error during OCM authentication")
w.WriteHeader(http.StatusInternalServerError)
return
case authRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED:
@@ -256,6 +268,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
ctx = appctx.ContextSetToken(ctx, authRes.Token)
ctx = appctx.ContextSetUser(ctx, authRes.User)
ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, authRes.Token)
+ ctx = context.WithValue(ctx, ctxOCM, true)
log.Debug().Str("token", token).Interface("user", authRes.User).Msg("OCM user authenticated")
@@ -375,9 +388,10 @@ func handleSignatureAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient,
return c.Authenticate(ctx, &authenticateRequest)
}
-func handleOCMAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, token string) (*gatewayv1beta1.AuthenticateResponse, error) {
+func handleOCMAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, ocmshare, token string) (*gatewayv1beta1.AuthenticateResponse, error) {
return c.Authenticate(ctx, &gatewayv1beta1.AuthenticateRequest{
- Type: "ocmshares",
- ClientId: token,
+ Type: "ocmshares",
+ ClientId: ocmshare,
+ ClientSecret: token,
})
}
diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go
index 3631860974..71d3c33473 100644
--- a/internal/http/services/owncloud/ocdav/ocdav.go
+++ b/internal/http/services/owncloud/ocdav/ocdav.go
@@ -51,7 +51,7 @@ type ctxKey int
const (
ctxKeyBaseURI ctxKey = iota
- ctxOCM10
+ ctxOCM
ctxSpaceID
ctxSpacePath
ctxSpaceFullPath
@@ -202,7 +202,7 @@ func (s *svc) Close() error {
}
func (s *svc) Unprotected() []string {
- return []string{"/status.php", "/remote.php/dav/public-files/", "/apps/files/", "/index.php/f/", "/index.php/s/", "/s/", "/remote.php/dav/ocm/"}
+ return []string{"/status.php", "/remote.php/dav/public-files/", "/apps/files/", "/index.php/f/", "/index.php/s/", "/s/", "/remote.php/dav/ocm/", "/ocm-provider"}
}
func (s *svc) Handler() http.Handler {
@@ -259,6 +259,10 @@ func (s *svc) Handler() http.Handler {
http.Redirect(w, r, rURL, http.StatusMovedPermanently)
return
}
+ case "ocm-provider":
+ // this is to support the current/legacy discovery endpoint for OCM
+ http.Redirect(w, r, "/.well-known/ocm", http.StatusMovedPermanently)
+ return
}
switch head {
// the old `/webdav` endpoint uses remote.php/webdav/$path
diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go
index 40d1b91a49..1dfd2604f5 100644
--- a/internal/http/services/owncloud/ocdav/propfind.go
+++ b/internal/http/services/owncloud/ocdav/propfind.go
@@ -505,25 +505,17 @@ func (s *svc) newPropRaw(key, val string) *propertyXML {
}
}
-func supportLegacyOCMAccess(ctx context.Context, md *provider.ResourceInfo) {
- ocm10, _ := ctx.Value(ctxOCM10).(bool)
- if ocm10 {
- // the path is something like //...
- // we need to strip the token part as this
- // is passed as username in the basic auth
- _, md.Path = router.ShiftPath(md.Path)
- }
-}
-
func spaceHref(ctx context.Context, baseURI, fullPath string) string {
// in the context of spaces, the final URL will be baseURI + //relative/path/to/space
spacePath, ok := ctx.Value(ctxSpacePath).(string)
if !ok {
+ // TODO fix panic
panic("space path expected to be in the context")
}
relativePath := strings.TrimPrefix(fullPath, spacePath)
spaceID, ok := ctx.Value(ctxSpaceID).(string)
if !ok {
+ // TODO fix panic
panic("space id expected to be in the context")
}
return path.Join(baseURI, spaceID, relativePath)
@@ -556,10 +548,14 @@ func (s *svc) isOpenable(path string) bool {
func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provider.ResourceInfo, ns string, usershares, linkshares map[string]struct{}) (*responseXML, error) {
sublog := appctx.GetLogger(ctx).With().Str("ns", ns).Logger()
- baseURI := ctx.Value(ctxKeyBaseURI).(string)
-
- supportLegacyOCMAccess(ctx, md)
+ md.Path = strings.TrimPrefix(md.Path, ns)
+ ocm, _ := ctx.Value(ctxOCM).(bool)
+ if ocm {
+ // // was injected in front of the OCM path for the routing to work, we now remove it (see internal/http/services/owncloud/ocdav/dav.go)
+ _, md.Path = router.ShiftPath(md.Path)
+ }
+ baseURI := ctx.Value(ctxKeyBaseURI).(string)
var ref string
if _, ok := ctx.Value(ctxSpaceID).(string); ok {
ref = spaceHref(ctx, baseURI, md.Path)
@@ -567,6 +563,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide
md.Path = strings.TrimPrefix(md.Path, ns)
ref = path.Join(baseURI, md.Path)
}
+
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
ref += "/"
}
diff --git a/internal/http/services/owncloud/ocs/conversions/role.go b/internal/http/services/owncloud/ocs/conversions/role.go
index 3fc4c8c224..3c67b4c835 100644
--- a/internal/http/services/owncloud/ocs/conversions/role.go
+++ b/internal/http/services/owncloud/ocs/conversions/role.go
@@ -181,7 +181,6 @@ func NewViewerRole() *Role {
Name: RoleViewer,
cS3ResourcePermissions: &provider.ResourcePermissions{
GetPath: true,
- GetQuota: true,
InitiateFileDownload: true,
ListGrants: true,
ListContainer: true,
@@ -200,7 +199,6 @@ func NewReaderRole() *Role {
cS3ResourcePermissions: &provider.ResourcePermissions{
// read
GetPath: true,
- GetQuota: true,
InitiateFileDownload: true,
ListGrants: true,
ListContainer: true,
@@ -218,7 +216,6 @@ func NewEditorRole() *Role {
Name: RoleEditor,
cS3ResourcePermissions: &provider.ResourcePermissions{
GetPath: true,
- GetQuota: true,
InitiateFileDownload: true,
ListGrants: true,
ListContainer: true,
@@ -243,7 +240,6 @@ func NewFileEditorRole() *Role {
Name: RoleEditor,
cS3ResourcePermissions: &provider.ResourcePermissions{
GetPath: true,
- GetQuota: true,
InitiateFileDownload: true,
ListGrants: true,
ListContainer: true,
@@ -368,7 +364,6 @@ func NewLegacyRoleFromOCSPermissions(p Permissions) *Role {
r.cS3ResourcePermissions.ListRecycle = true
r.cS3ResourcePermissions.Stat = true
r.cS3ResourcePermissions.GetPath = true
- r.cS3ResourcePermissions.GetQuota = true
r.cS3ResourcePermissions.InitiateFileDownload = true
}
if p.Contain(PermissionWrite) {
@@ -424,7 +419,6 @@ func RoleFromResourcePermissions(rp *provider.ResourcePermissions) *Role {
rp.ListRecycle &&
rp.Stat &&
rp.GetPath &&
- rp.GetQuota &&
rp.InitiateFileDownload {
r.ocsPermissions |= PermissionRead
}
diff --git a/internal/http/services/opencloudmesh/ocmprovider/ocmprovider.go b/internal/http/services/wellknown/ocm.go
similarity index 71%
rename from internal/http/services/opencloudmesh/ocmprovider/ocmprovider.go
rename to internal/http/services/wellknown/ocm.go
index 539c7aefca..f8f4d53612 100644
--- a/internal/http/services/opencloudmesh/ocmprovider/ocmprovider.go
+++ b/internal/http/services/wellknown/ocm.go
@@ -16,27 +16,20 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
-package ocmprovider
+package wellknown
import (
- "context"
"encoding/json"
"net/http"
"net/url"
"path/filepath"
"github.com/cs3org/reva/pkg/appctx"
- "github.com/cs3org/reva/pkg/rhttp/global"
- "github.com/cs3org/reva/pkg/utils/cfg"
)
const OCMAPIVersion = "1.1.0"
-func init() {
- global.Register("ocmprovider", New)
-}
-
-type config struct {
+type OcmProviderConfig struct {
OCMPrefix string `docs:"ocm;The prefix URL where the OCM API is served." mapstructure:"ocm_prefix"`
Endpoint string `docs:"This host's full URL. If it's not configured, it is assumed OCM is not available." mapstructure:"endpoint"`
Provider string `docs:"reva;A friendly name that defines this service." mapstructure:"provider"`
@@ -46,7 +39,7 @@ type config struct {
EnableDatatx bool `docs:"false;Whether data transfers are enabled in OCM shares." mapstructure:"enable_datatx"`
}
-type DiscoveryData struct {
+type OcmDiscoveryData struct {
Enabled bool `json:"enabled" xml:"enabled"`
APIVersion string `json:"apiVersion" xml:"apiVersion"`
Endpoint string `json:"endPoint" xml:"endPoint"`
@@ -61,11 +54,11 @@ type resourceTypes struct {
Protocols map[string]string `json:"protocols"`
}
-type svc struct {
- data *DiscoveryData
+type wkocmHandler struct {
+ data *OcmDiscoveryData
}
-func (c *config) ApplyDefaults() {
+func (c *OcmProviderConfig) ApplyDefaults() {
if c.OCMPrefix == "" {
c.OCMPrefix = "ocm"
}
@@ -86,10 +79,11 @@ func (c *config) ApplyDefaults() {
}
}
-func (c *config) prepare() *DiscoveryData {
- // generates the (static) data structure to be exposed by /ocm-provider:
+func (h *wkocmHandler) init(c *OcmProviderConfig) {
+ // generates the (static) data structure to be exposed by /.well-known/ocm:
// first prepare an empty and disabled payload
- d := &DiscoveryData{}
+ c.ApplyDefaults()
+ d := &OcmDiscoveryData{}
d.Enabled = false
d.Endpoint = ""
d.APIVersion = OCMAPIVersion
@@ -102,12 +96,14 @@ func (c *config) prepare() *DiscoveryData {
d.Capabilities = []string{}
if c.Endpoint == "" {
- return d
+ h.data = d
+ return
}
endpointURL, err := url.Parse(c.Endpoint)
if err != nil {
- return d
+ h.data = d
+ return
}
// now prepare the enabled one
@@ -129,49 +125,24 @@ func (c *config) prepare() *DiscoveryData {
}}
// for now we hardcode the capabilities, as this is currently only advisory
d.Capabilities = []string{"/invite-accepted"}
- return d
+ h.data = d
}
-// New returns a new ocmprovider object, that implements
-// the OCM discovery endpoint specified in
+// This handler implements the OCM discovery endpoint specified in
// https://cs3org.github.io/OCM-API/docs.html?repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get
-func New(ctx context.Context, m map[string]interface{}) (global.Service, error) {
- var c config
- if err := cfg.Decode(m, &c); err != nil {
- return nil, err
+func (h *wkocmHandler) Ocm(w http.ResponseWriter, r *http.Request) {
+ log := appctx.GetLogger(r.Context())
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ if r.UserAgent() == "Nextcloud Server Crawler" {
+ // Nextcloud decided to only support OCM 1.0 and 1.1, not any 1.x as per SemVer. See
+ // https://github.com/nextcloud/server/pull/39574#issuecomment-1679191188
+ h.data.APIVersion = "1.1"
+ } else {
+ h.data.APIVersion = OCMAPIVersion
+ }
+ indented, _ := json.MarshalIndent(h.data, "", " ")
+ if _, err := w.Write(indented); err != nil {
+ log.Err(err).Msg("Error writing to ResponseWriter")
}
- return &svc{data: c.prepare()}, nil
-}
-
-// Close performs cleanup.
-func (s *svc) Close() error {
- return nil
-}
-
-func (s *svc) Prefix() string {
- // this is hardcoded as per OCM specifications
- return "/ocm-provider"
-}
-
-func (s *svc) Unprotected() []string {
- return []string{"/"}
-}
-
-func (s *svc) Handler() http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log := appctx.GetLogger(r.Context())
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- if r.UserAgent() == "Nextcloud Server Crawler" {
- // Nextcloud decided to only support OCM 1.0 and 1.1, not any 1.x as per SemVer. See
- // https://github.com/nextcloud/server/pull/39574#issuecomment-1679191188
- s.data.APIVersion = "1.1"
- } else {
- s.data.APIVersion = OCMAPIVersion
- }
- indented, _ := json.MarshalIndent(s.data, "", " ")
- if _, err := w.Write(indented); err != nil {
- log.Err(err).Msg("Error writing to ResponseWriter")
- }
- })
}
diff --git a/internal/http/services/wellknown/wellknown.go b/internal/http/services/wellknown/wellknown.go
new file mode 100644
index 0000000000..5ca2c2fb0d
--- /dev/null
+++ b/internal/http/services/wellknown/wellknown.go
@@ -0,0 +1,91 @@
+// Copyright 2018-2024 CERN
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// In applying this license, CERN does not waive the privileges and immunities
+// granted to it by virtue of its status as an Intergovernmental Organization
+// or submit itself to any jurisdiction.
+
+package wellknown
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/cs3org/reva/pkg/appctx"
+ "github.com/cs3org/reva/pkg/rhttp/global"
+ "github.com/cs3org/reva/pkg/utils/cfg"
+ "github.com/go-chi/chi/v5"
+)
+
+func init() {
+ global.Register("wellknown", New)
+}
+
+type svc struct {
+ router chi.Router
+ Conf *config
+}
+
+type config struct {
+ OCMProvider OcmProviderConfig `mapstructure:"ocmprovider"`
+}
+
+// New returns a new wellknown object.
+func New(ctx context.Context, m map[string]interface{}) (global.Service, error) {
+ var c config
+ if err := cfg.Decode(m, &c); err != nil {
+ return nil, err
+ }
+
+ r := chi.NewRouter()
+ s := &svc{
+ router: r,
+ Conf: &c,
+ }
+ if err := s.routerInit(); err != nil {
+ return nil, err
+ }
+
+ return s, nil
+}
+
+func (s *svc) routerInit() error {
+ wkocmHandler := new(wkocmHandler)
+ wkocmHandler.init(&s.Conf.OCMProvider)
+ s.router.Get("/ocm", wkocmHandler.Ocm)
+ return nil
+}
+
+func (s *svc) Close() error {
+ return nil
+}
+
+func (s *svc) Prefix() string {
+ return "/.well-known"
+}
+
+func (s *svc) Unprotected() []string {
+ return []string{"/", "/ocm"}
+}
+
+func (s *svc) Handler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ log := appctx.GetLogger(r.Context())
+ log.Debug().Str("path", r.URL.Path).Msg(".well-known routing")
+
+ // unset raw path, otherwise chi uses it to route and then fails to match percent encoded path segments
+ r.URL.RawPath = ""
+ s.router.ServeHTTP(w, r)
+ })
+}
diff --git a/internal/serverless/services/notifications/notifications.go b/internal/serverless/services/notifications/notifications.go
index 579b8e3f34..05cb995093 100644
--- a/internal/serverless/services/notifications/notifications.go
+++ b/internal/serverless/services/notifications/notifications.go
@@ -45,9 +45,9 @@ import (
type config struct {
NatsAddress string `docs:";The NATS server address." mapstructure:"nats_address"`
- NatsToken string `docs:"The token to authenticate against the NATS server" mapstructure:"nats_token"`
+ NatsToken string `docs:";The token to authenticate against the NATS server" mapstructure:"nats_token"`
NatsPrefix string `docs:"reva-notifications;The notifications NATS stream." mapstructure:"nats_prefix"`
- HandlerConf map[string]map[string]interface{} `docs:";Settings for the different notification handlers." mapstructure:"handlers"`
+ HandlerConf map[string]map[string]interface{} `docs:"nil;Settings for the different notification handlers." mapstructure:"handlers"`
GroupingInterval int `docs:"60;Time in seconds to group incoming notification triggers" mapstructure:"grouping_interval"`
GroupingMaxSize int `docs:"100;Maximum number of notifications to group" mapstructure:"grouping_max_size"`
StorageDriver string `docs:"mysql;The driver used to store notifications" mapstructure:"storage_driver"`
diff --git a/netlify.toml b/netlify.toml
index 1bf2fe310c..9ae80aa9cb 100644
--- a/netlify.toml
+++ b/netlify.toml
@@ -1,8 +1,8 @@
[build]
publish = "docs/public"
- command = "git submodule update -f --init --recursive && cd docs/ && npm install postcss-cli && hugo --gc --minify"
+ command = "git submodule update -f --init --recursive && cd docs/ && npm install postcss-cli && cd themes/docsy && npm run _mkdir:hugo-mod && cd ../../ && hugo --gc --minify"
ignore = "git diff --quiet HEAD^ HEAD docs/"
[build.environment]
- HUGO_VERSION = "0.59.0"
+ HUGO_VERSION = "0.124.1"
HUGO_ENV = "production"
diff --git a/pkg/auth/manager/ocmshares/ocmshares.go b/pkg/auth/manager/ocmshares/ocmshares.go
index c53b00a085..b347cbe817 100644
--- a/pkg/auth/manager/ocmshares/ocmshares.go
+++ b/pkg/auth/manager/ocmshares/ocmshares.go
@@ -82,8 +82,8 @@ func (m *manager) Configure(ml map[string]interface{}) error {
return nil
}
-func (m *manager) Authenticate(ctx context.Context, token, _ string) (*userpb.User, map[string]*authpb.Scope, error) {
- log := appctx.GetLogger(ctx).With().Str("token", token).Logger()
+func (m *manager) Authenticate(ctx context.Context, ocmshare, token string) (*userpb.User, map[string]*authpb.Scope, error) {
+ log := appctx.GetLogger(ctx).With().Str("token", token).Str("ocmshare", ocmshare).Logger()
shareRes, err := m.gw.GetOCMShareByToken(ctx, &ocm.GetOCMShareByTokenRequest{
Token: token,
})
@@ -103,6 +103,12 @@ func (m *manager) Authenticate(ctx context.Context, token, _ string) (*userpb.Us
return nil, nil, errtypes.InternalError(shareRes.Status.Message)
}
+ // validate OCM share id if given (OCM v1.1)
+ if ocmshare != "" && shareRes.GetShare().GetId().GetOpaqueId() != ocmshare {
+ log.Error().Str("requested_share", ocmshare).Str("share_from_provider", shareRes.GetShare().GetId().GetOpaqueId()).Msg("mismatching ocm share id for existing secret")
+ return nil, nil, errtypes.InvalidCredentials("invalid shared secret")
+ }
+
// the user authenticated using the ocmshares authentication method
// is the recipient of the share
u := shareRes.Share.Grantee.GetUserId()
diff --git a/pkg/auth/manager/oidc/oidc.go b/pkg/auth/manager/oidc/oidc.go
index c9c29e7a83..bfdb9d29e1 100644
--- a/pkg/auth/manager/oidc/oidc.go
+++ b/pkg/auth/manager/oidc/oidc.go
@@ -185,13 +185,17 @@ func (am *mgr) isIssuerAllowed(issuer string) bool {
}
func (am *mgr) doUserMapping(tkn *oidc.IDToken, claims jwt.MapClaims) (string, error) {
+ var sub = tkn.Subject
+ if am.c.IDClaim != "sub" && claims[am.c.IDClaim] != nil {
+ sub, _ = claims[am.c.IDClaim].(string)
+ }
if len(am.oidcUsersMapping) == 0 {
- return tkn.Subject, nil
+ return sub, nil
}
// we need the custom claims for the mapping
if claims[am.c.GroupClaim] == nil {
// we are required to perform a user mapping but the group claim is not available
- return tkn.Subject, nil
+ return sub, nil
}
mappings := make([]string, 0, len(am.oidcUsersMapping))
@@ -222,7 +226,7 @@ func (am *mgr) Authenticate(ctx context.Context, _, clientSecret string) (*user.
claims, err := extractClaims(clientSecret)
if err != nil {
- return nil, nil, errtypes.PermissionDenied("oidc token not valid")
+ return nil, nil, errtypes.PermissionDenied(fmt.Sprintf("error extracting claims from oidc token: %+v", err))
}
issuer, ok := extractIssuer(claims)
@@ -248,7 +252,7 @@ func (am *mgr) Authenticate(ctx context.Context, _, clientSecret string) (*user.
tkn, err := provider.Verifier(config).Verify(ctx, clientSecret)
if err != nil {
- return nil, nil, errtypes.PermissionDenied(fmt.Sprintf("oidc token not valid: %+v", err))
+ return nil, nil, errtypes.PermissionDenied(fmt.Sprintf("oidc token failed verification: %+v", err))
}
sub, err := am.doUserMapping(tkn, claims)
diff --git a/pkg/eosclient/eosbinary/eosbinary.go b/pkg/eosclient/eosbinary/eosbinary.go
index 93c0f6a8fa..ecdf8f4f51 100644
--- a/pkg/eosclient/eosbinary/eosbinary.go
+++ b/pkg/eosclient/eosbinary/eosbinary.go
@@ -260,16 +260,18 @@ func (c *Client) executeEOS(ctx context.Context, cmdArgs []string, auth eosclien
case 0:
err = nil
case int(syscall.ENOENT):
- err = errtypes.NotFound(errBuf.String())
+ err = errtypes.NotFound("eosclient: " + errBuf.String())
case int(syscall.EPERM), int(syscall.E2BIG), int(syscall.EINVAL):
- // eos reports back error code 1 (EPERM) when ?
+ // eos reports back error code 1 (EPERM) as a PermissionDenied error
// eos reports back error code 7 (E2BIG) when the user is not allowed to read the directory
// eos reports back error code 22 (EINVAL) when the user is not allowed to enter the instance
errString := errBuf.String()
if errString == "" {
errString = fmt.Sprintf("rc = %d", exitStatus)
}
- err = errtypes.PermissionDenied(errString)
+ err = errtypes.PermissionDenied("eosclient: " + errString)
+ default:
+ err = errors.Wrap(err, fmt.Sprintf("eosclient: error while executing command: %s", errBuf.String()))
}
}
}
@@ -277,11 +279,6 @@ func (c *Client) executeEOS(ctx context.Context, cmdArgs []string, auth eosclien
args := fmt.Sprintf("%s", cmd.Args)
env := fmt.Sprintf("%s", cmd.Env)
log.Info().Str("args", args).Str("env", env).Int("exit", exitStatus).Str("err", errBuf.String()).Msg("eos cmd")
-
- if err != nil && exitStatus != int(syscall.ENOENT) { // don't wrap the errtypes.NotFoundError
- err = errors.Wrap(err, "eosclient: error while executing command")
- }
-
return outBuf.String(), errBuf.String(), err
}
diff --git a/pkg/notification/notificationhelper/notificationhelper.go b/pkg/notification/notificationhelper/notificationhelper.go
index 7fc9995be0..e17f6abc94 100644
--- a/pkg/notification/notificationhelper/notificationhelper.go
+++ b/pkg/notification/notificationhelper/notificationhelper.go
@@ -47,7 +47,7 @@ type Config struct {
NatsAddress string `docs:";The NATS server address." mapstructure:"nats_address"`
NatsToken string `docs:";The token to authenticate against the NATS server" mapstructure:"nats_token"`
NatsStream string `docs:"reva-notifications;The notifications NATS stream." mapstructure:"nats_stream"`
- Templates map[string]interface{} `docs:";Notification templates for the service." mapstructure:"templates"`
+ Templates map[string]interface{} `docs:"nil;Notification templates for the service." mapstructure:"templates"`
}
func defaultConfig() *Config {
diff --git a/pkg/ocm/provider/authorizer/open/open.go b/pkg/ocm/provider/authorizer/open/open.go
index 88516d6d3d..d0af08efb6 100644
--- a/pkg/ocm/provider/authorizer/open/open.go
+++ b/pkg/ocm/provider/authorizer/open/open.go
@@ -20,15 +20,17 @@ package open
import (
"context"
- "encoding/json"
- "os"
+ "net/url"
+ "path/filepath"
"strings"
+ "time"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
- "github.com/cs3org/reva/pkg/errtypes"
+ client "github.com/cs3org/reva/internal/http/services/opencloudmesh/ocmd"
"github.com/cs3org/reva/pkg/ocm/provider"
"github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry"
"github.com/cs3org/reva/pkg/utils/cfg"
+ "github.com/pkg/errors"
)
func init() {
@@ -42,19 +44,7 @@ func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, er
return nil, err
}
- f, err := os.ReadFile(c.Providers)
- if err != nil {
- return nil, err
- }
- providers := []*ocmprovider.ProviderInfo{}
- err = json.Unmarshal(f, &providers)
- if err != nil {
- return nil, err
- }
-
a := &authorizer{}
- a.providers = a.getOCMProviders(providers)
-
return a, nil
}
@@ -64,9 +54,6 @@ type config struct {
}
func (c *config) ApplyDefaults() {
- if c.Providers == "" {
- c.Providers = "/etc/revad/ocm-providers.json"
- }
}
type authorizer struct {
@@ -79,7 +66,51 @@ func (a *authorizer) GetInfoByDomain(ctx context.Context, domain string) (*ocmpr
return p, nil
}
}
- return nil, errtypes.NotFound(domain)
+
+ // not yet known: try to discover the remote OCM endpoint
+ ocmClient := client.NewClient(time.Duration(10)*time.Second, true)
+ ocmCaps, err := ocmClient.Discover(ctx, domain)
+ if err != nil {
+ return nil, errors.Wrap(err, "error probing OCM services at remote server")
+ }
+ var path string
+ for _, t := range ocmCaps.ResourceTypes {
+ webdavRoot, ok := t.Protocols["webdav"]
+ if ok {
+ // assume the first resourceType that exposes a webdav root is OK to use: as a matter of fact,
+ // no implementation exists yet that exposes multiple resource types with different roots.
+ path = filepath.Join(ocmCaps.Endpoint, webdavRoot)
+ }
+ }
+ host, _ := url.Parse(ocmCaps.Endpoint)
+
+ // return a provider info record for this domain, including the OCM service
+ return &ocmprovider.ProviderInfo{
+ Name: "ocm_" + domain,
+ FullName: ocmCaps.Provider,
+ Description: "OCM service at " + domain,
+ Organization: domain,
+ Domain: domain,
+ Homepage: "",
+ Email: "",
+ Properties: map[string]string{},
+ Services: []*ocmprovider.Service{
+ {
+ Endpoint: &ocmprovider.ServiceEndpoint{
+ Type: &ocmprovider.ServiceType{Name: "OCM"},
+ Path: ocmCaps.Endpoint,
+ },
+ Host: host.Hostname(),
+ },
+ {
+ Endpoint: &ocmprovider.ServiceEndpoint{
+ Type: &ocmprovider.ServiceType{Name: "Webdav"},
+ Path: path,
+ },
+ Host: host.Hostname(),
+ },
+ },
+ }, nil
}
func (a *authorizer) IsProviderAllowed(ctx context.Context, provider *ocmprovider.ProviderInfo) error {
@@ -89,22 +120,3 @@ func (a *authorizer) IsProviderAllowed(ctx context.Context, provider *ocmprovide
func (a *authorizer) ListAllProviders(ctx context.Context) ([]*ocmprovider.ProviderInfo, error) {
return a.providers, nil
}
-
-func (a *authorizer) getOCMProviders(providers []*ocmprovider.ProviderInfo) (po []*ocmprovider.ProviderInfo) {
- for _, p := range providers {
- _, err := a.getOCMHost(p)
- if err == nil {
- po = append(po, p)
- }
- }
- return
-}
-
-func (a *authorizer) getOCMHost(provider *ocmprovider.ProviderInfo) (string, error) {
- for _, s := range provider.Services {
- if s.Endpoint.Type.Name == "OCM" {
- return s.Host, nil
- }
- }
- return "", errtypes.NotFound("OCM Host")
-}
diff --git a/pkg/ocm/share/sender/sender.go b/pkg/ocm/share/sender/sender.go
deleted file mode 100644
index 05d6890bde..0000000000
--- a/pkg/ocm/share/sender/sender.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2018-2024 CERN
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// In applying this license, CERN does not waive the privileges and immunities
-// granted to it by virtue of its status as an Intergovernmental Organization
-// or submit itself to any jurisdiction.
-
-package sender
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "path"
- "strings"
- "time"
-
- ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
- "github.com/cs3org/reva/pkg/appctx"
- "github.com/cs3org/reva/pkg/httpclient"
- "github.com/pkg/errors"
-)
-
-const createOCMCoreShareEndpoint = "shares"
-
-func getOCMEndpoint(originProvider *ocmprovider.ProviderInfo) (string, error) {
- for _, s := range originProvider.Services {
- if s.Endpoint.Type.Name == "OCM" {
- return s.Endpoint.Path, nil
- }
- }
- return "", errors.New("json: ocm endpoint not specified for mesh provider")
-}
-
-// Send executes the POST to the OCM shares endpoint to create the share at the
-// remote site.
-func Send(ctx context.Context, requestBodyMap map[string]interface{}, pi *ocmprovider.ProviderInfo) error {
- requestBody, err := json.Marshal(requestBodyMap)
- if err != nil {
- err = errors.Wrap(err, "error marshalling request body")
- return err
- }
- ocmEndpoint, err := getOCMEndpoint(pi)
- if err != nil {
- return err
- }
- u, err := url.Parse(ocmEndpoint)
- if err != nil {
- return err
- }
- u.Path = path.Join(u.Path, createOCMCoreShareEndpoint)
- recipientURL := u.String()
-
- log := appctx.GetLogger(ctx)
- log.Info().Msgf("in OCM Send! %s %s", recipientURL, requestBody)
-
- req, err := http.NewRequest(http.MethodPost, recipientURL, strings.NewReader(string(requestBody)))
- if err != nil {
- return errors.Wrap(err, "sender: error framing post request")
- }
- req.Header.Set("Content-Type", "application/json")
- client := httpclient.New(
- httpclient.Timeout(5 * time.Second),
- )
-
- resp, err := client.Do(req)
- if err != nil {
- err = errors.Wrap(err, "sender: error sending post request")
- return err
- }
-
- defer resp.Body.Close()
- if (resp.StatusCode != http.StatusCreated) && (resp.StatusCode != http.StatusOK) {
- respBody, e := io.ReadAll(resp.Body)
- if e != nil {
- e = errors.Wrap(e, "sender: error reading request body")
- return e
- }
- err = errors.Wrap(fmt.Errorf("%s: %s", resp.Status, string(respBody)), "sender: error from "+ocmEndpoint)
- return err
- }
- return nil
-}
diff --git a/pkg/ocm/storage/outcoming/ocm.go b/pkg/ocm/storage/outcoming/ocm.go
index ed843a8b20..ac80120f7c 100644
--- a/pkg/ocm/storage/outcoming/ocm.go
+++ b/pkg/ocm/storage/outcoming/ocm.go
@@ -68,6 +68,7 @@ func (c *config) ApplyDefaults() {
}
// New creates an OCM storage driver.
+// This driver exposes local resources to remote OCM users.
func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) {
var c config
if err := cfg.Decode(m, &c); err != nil {
@@ -148,6 +149,9 @@ func (d *driver) shareAndRelativePathFromRef(ctx context.Context, ref *provider.
}
path = makeRelative(path)
+ log := appctx.GetLogger(ctx)
+ log.Info().Interface("ref", ref).Str("path", path).Str("token", token).Msg("Accessing OCM share")
+
share, err := d.resolveToken(ctx, token)
if err != nil {
return nil, "", err
diff --git a/pkg/ocm/storage/received/ocm.go b/pkg/ocm/storage/received/ocm.go
index bcb684b9a8..89e73ef29b 100644
--- a/pkg/ocm/storage/received/ocm.go
+++ b/pkg/ocm/storage/received/ocm.go
@@ -33,6 +33,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typepb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/internal/http/services/owncloud/ocdav"
+ "github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/mime"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
@@ -62,6 +63,7 @@ func (c *config) ApplyDefaults() {
}
// New creates an OCM storage driver.
+// This driver exposes remote OCM resources to local users.
func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) {
var c config
if err := cfg.Decode(m, &c); err != nil {
@@ -153,11 +155,12 @@ func (d *driver) webdavClient(ctx context.Context, ref *provider.Reference) (*go
return nil, nil, "", err
}
- // FIXME: it's still not clear from the OCM APIs how to use the shared secret
- // will use as a token in the bearer authentication as this is the reva implementation
+ // use the secret as bearer authentication according to OCM v1.1+
c := gowebdav.NewClient(endpoint, "", "")
c.SetHeader("Authorization", "Bearer "+secret)
+ log := appctx.GetLogger(ctx)
+ log.Info().Str("endpoint", endpoint).Interface("share", share).Str("rel", rel).Str("secret", secret).Msg("Accessing OCM share")
return c, share, rel, nil
}
diff --git a/pkg/storage/utils/eosfs/config.go b/pkg/storage/utils/eosfs/config.go
index 853d3b90df..6017edf671 100644
--- a/pkg/storage/utils/eosfs/config.go
+++ b/pkg/storage/utils/eosfs/config.go
@@ -29,6 +29,9 @@ type Config struct {
// DefaultQuotaBytes sets the default maximum bytes available for a user
DefaultQuotaBytes uint64 `mapstructure:"default_quota_bytes"`
+ // DefaultSecondaryQuotaBytes sets the default maximum bytes available for a secondary user
+ DefaultSecondaryQuotaBytes uint64 `mapstructure:"default_secondary_quota_bytes"`
+
// DefaultQuotaFiles sets the default maximum files available for a user
DefaultQuotaFiles uint64 `mapstructure:"default_quota_files"`
diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go
index 2082de76af..c322b6b93b 100644
--- a/pkg/storage/utils/eosfs/eosfs.go
+++ b/pkg/storage/utils/eosfs/eosfs.go
@@ -101,6 +101,9 @@ func (c *Config) ApplyDefaults() {
if c.DefaultQuotaBytes == 0 {
c.DefaultQuotaBytes = 2000000000000 // 1 TB logical
}
+ if c.DefaultSecondaryQuotaBytes == 0 {
+ c.DefaultSecondaryQuotaBytes = c.DefaultQuotaBytes
+ }
if c.DefaultQuotaFiles == 0 {
c.DefaultQuotaFiles = 1000000 // 1 Million
}
@@ -1489,12 +1492,16 @@ func (fs *eosfs) createNominalHome(ctx context.Context) error {
return err
}
- // set quota for user
+ // set quota for user, depending on its type
+ quotaBytes := fs.conf.DefaultQuotaBytes
+ if u.Id.Type != userpb.UserType_USER_TYPE_PRIMARY {
+ quotaBytes = fs.conf.DefaultSecondaryQuotaBytes
+ }
quotaInfo := &eosclient.SetQuotaInfo{
Username: u.Username,
UID: auth.Role.UID,
GID: auth.Role.GID,
- MaxBytes: fs.conf.DefaultQuotaBytes,
+ MaxBytes: quotaBytes,
MaxFiles: fs.conf.DefaultQuotaFiles,
QuotaNode: fs.conf.QuotaNode,
}
diff --git a/pkg/storage/utils/grants/grants.go b/pkg/storage/utils/grants/grants.go
index 021efe0d63..07e7262a25 100644
--- a/pkg/storage/utils/grants/grants.go
+++ b/pkg/storage/utils/grants/grants.go
@@ -29,7 +29,8 @@ import (
var noPermissions = &provider.ResourcePermissions{}
-// GetACLPerm generates a string representation of CS3APIs' ResourcePermissions
+// GetACLPerm generates a string representation of CS3APIs' ResourcePermissions,
+// modeled after the EOS ACLs.
// TODO(labkode): fine grained permission controls.
func GetACLPerm(set *provider.ResourcePermissions) (string, error) {
// resource permission is denied
@@ -39,7 +40,7 @@ func GetACLPerm(set *provider.ResourcePermissions) (string, error) {
var b strings.Builder
- if set.Stat || set.InitiateFileDownload {
+ if set.Stat || set.InitiateFileDownload || set.ListGrants {
b.WriteString("r")
}
if set.CreateContainer || set.InitiateFileUpload || set.Delete || set.Move {
@@ -48,12 +49,9 @@ func GetACLPerm(set *provider.ResourcePermissions) (string, error) {
if set.ListContainer || set.ListFileVersions {
b.WriteString("x")
}
- if set.AddGrant || set.ListGrants || set.RemoveGrant {
+ if set.AddGrant || set.RemoveGrant {
b.WriteString("m")
}
- if set.GetQuota {
- b.WriteString("q")
- }
if set.Delete {
b.WriteString("+d")
@@ -64,10 +62,10 @@ func GetACLPerm(set *provider.ResourcePermissions) (string, error) {
return b.String(), nil
}
-// GetGrantPermissionSet converts CS3APIs' ResourcePermissions from a string
-// TODO(labkode): add more fine grained controls.
+// GetGrantPermissionSet converts CS3APIs' ResourcePermissions from a string:
// EOS acls are a mix of ACLs and POSIX permissions. More details can be found in
-// https://github.com/cern-eos/eos/blob/master/doc/configuration/permission.rst
+// https://github.com/cern-eos/eos/blob/master/doc/citrine/configuration/permission.rst.
+// TODO(labkode): add more fine grained controls.
func GetGrantPermissionSet(perm string) *provider.ResourcePermissions {
var rp provider.ResourcePermissions // default to 0 == all denied
@@ -75,6 +73,7 @@ func GetGrantPermissionSet(perm string) *provider.ResourcePermissions {
rp.GetPath = true
rp.Stat = true
rp.InitiateFileDownload = true
+ rp.ListGrants = true
}
if strings.Contains(perm, "w") && !strings.Contains(perm, "!w") {
@@ -100,14 +99,9 @@ func GetGrantPermissionSet(perm string) *provider.ResourcePermissions {
if strings.Contains(perm, "m") && !strings.Contains(perm, "!m") {
rp.AddGrant = true
- rp.ListGrants = true
rp.RemoveGrant = true
}
- if strings.Contains(perm, "q") && !strings.Contains(perm, "!q") {
- rp.GetQuota = true
- }
-
return &rp
}
diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml
index c2c077b74c..9e40fe48f6 100644
--- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml
+++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml
@@ -58,6 +58,7 @@ providers = "{{file_providers}}"
[grpc.services.ocmshareprovider]
driver = "json"
webdav_endpoint = "http://{{cernboxwebdav_address}}"
+webapp_template = "http://{{cernboxwebdav_address}}/external/sciencemesh/{{.Token}}{relative-path-to-shared-resource}"
provider_domain = "cernbox.cern.ch"
[grpc.services.ocmshareprovider.drivers.json]
diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml
index 3a225319ab..399b310561 100644
--- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml
+++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml
@@ -38,6 +38,7 @@ providers = "{{file_providers}}"
[grpc.services.ocmshareprovider]
driver = "json"
webdav_endpoint = "http://{{cesnethttp_address}}"
+webapp_template = "http://{{cesnethttp_address}}/external/sciencemesh/{{.Token}}{relative-path-to-shared-resource}"
provider_domain = "cesnet.cz"
[grpc.services.ocmshareprovider.drivers.json]
diff --git a/tests/integration/grpc/ocm_share_test.go b/tests/integration/grpc/ocm_share_test.go
index 7851805556..fdf6056e74 100644
--- a/tests/integration/grpc/ocm_share_test.go
+++ b/tests/integration/grpc/ocm_share_test.go
@@ -219,6 +219,7 @@ var _ = Describe("ocm share", func() {
Expect(ok).To(BeTrue())
webdavClient := gowebdav.NewClient(webdav.WebdavOptions.Uri, "", "")
+ webdavClient.SetHeader("Authorization", "Bearer "+webdav.WebdavOptions.SharedSecret)
d, err := webdavClient.Read(".")
Expect(err).ToNot(HaveOccurred())
Expect(d).To(Equal([]byte("test")))
@@ -299,6 +300,7 @@ var _ = Describe("ocm share", func() {
Expect(ok).To(BeTrue())
webdavClient := gowebdav.NewClient(webdav.WebdavOptions.Uri, "", "")
+ webdavClient.SetHeader("Authorization", "Bearer "+webdav.WebdavOptions.SharedSecret)
data := []byte("new-content")
webdavClient.SetHeader(ocdav.HeaderUploadLength, strconv.Itoa(len(data)))
err = webdavClient.Write(".", data, 0)
@@ -394,7 +396,7 @@ var _ = Describe("ocm share", func() {
Expect(ok).To(BeTrue())
webdavClient := gowebdav.NewClient(webdav.WebdavOptions.Uri, "", "")
-
+ webdavClient.SetHeader("Authorization", "Bearer "+webdav.WebdavOptions.SharedSecret)
ok, err = helpers.SameContentWebDAV(webdavClient, fileToShare.Path, structure)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
@@ -499,6 +501,7 @@ var _ = Describe("ocm share", func() {
webdavClient := gowebdav.NewClient(webdav.WebdavOptions.Uri, "", "")
data := []byte("new-content")
webdavClient.SetHeader(ocdav.HeaderUploadLength, strconv.Itoa(len(data)))
+ webdavClient.SetHeader("Authorization", "Bearer "+webdav.WebdavOptions.SharedSecret)
err = webdavClient.Write("new-file", data, 0)
Expect(err).ToNot(HaveOccurred())