mirror of
https://github.com/owncloud/ocis.git
synced 2026-10-23 23:29:02 +03:00
[full-ci] chore: [OCISDEV-5] merge and relicense ownCloud Web into oCIS (#12491)
* chore: [OCISDEV-5] Merge and relicense ownCloud Web into oCIS Consolidate the ownCloud Web frontend into this repository as a single product with one contribution surface and one license. The web/ source is imported as-is from the final standalone owncloud/web release (v12.5.0 / last-agpl-release @ b16a34fdf5569d2fd63b1ff3c575c1a4ee569ad3); the archived owncloud/web repository remains the historical record for everything at and before that commit. Relicensing: - All web/ contributors have signed the ownCloud CLA, granting ownCloud GmbH the right to relicense their contributions. - web/LICENSE (AGPL-3.0) removed; the repository root LICENSE (Apache-2.0) now governs web/ as well, matching how the rest of the repo is already licensed. - All 25 web/packages/*/package.json license fields flipped to Apache-2.0; root NOTICE added documenting the relicensing provenance. - Added REUSE.toml + LICENSES/ so the whole repository (including vendored Go dependencies) is REUSE 3.3 compliant. CI/build: - services/web/Makefile now builds web assets from the in-tree source instead of downloading a release tarball from owncloud/web; license checking/saving likewise runs against the in-tree source. - ci.env and tests/acceptance/run-e2e.py no longer clone owncloud/web for Playwright e2e tests. - Added the app-provider and ocm e2e suites to acceptance-tests.yml's matrix, closing a coverage gap where they were silently excluded; ported the Collabora/OnlyOffice/federated-instance orchestration web's old CI used to run them. - Added web-tests.yml (typecheck/format/lint/unit-test), a check-licenses.yml, commit-message.yml, and release-npm-packages.yml for the @ownclouders/* packages, replacing web's old standalone CI. - Removed dead CI tooling inherited from the standalone repo (web/tests/drone, web/tests/actions, web/.github, and an orphaned ci.env-dependent cache-check script). Docs: - Rewrote docs/services/web/releasing.md and web/docs/releasing to describe the in-tree build/release process. - Updated remaining references to github.com/owncloud/web across docs, services/web/README.md, and the deployment example to point at the in-tree web/ directory. Signed-off-by: Lukas Hirt <info@hirt.cz> * ci: sync web/ translations via Transifex web/ is a pnpm workspace nested inside the repo, so it isn't covered by the existing translation-sync job (sub_path: ., no package.json at the repo root). Add a second sync-web job invoking the same reusable workflow with sub_path: web and package_manager: pnpm, so its l10n-read/ push/pull/write targets actually install web's dependencies instead of silently running against an empty node_modules. Sequenced after the existing sync job since both push to the same hardcoded chore/translations-update branch. * ci: fix pnpm cache setup order in web-tests and check-licenses actions/setup-node's cache: pnpm input shells out to pnpm to resolve the cache directory, so pnpm must already be on PATH when that step runs. Both workflows ran `corepack enable` *after* setup-node, which still failed: corepack writes its pnpm shim into the currently active Node installation's bin dir, and setup-node had already swapped PATH to the newly-installed Node version by that point, leaving the shim behind. Use pnpm/action-setup instead, which installs a standalone pnpm binary independent of the Node version, before setup-node runs. Also set cache-dependency-path explicitly: the lockfile lives at web/pnpm-lock.yaml, and cache-dependency-path resolves relative to GITHUB_WORKSPACE regardless of the job's working-directory default (that default only applies to run: steps, not to setup-node itself). * fix(web): resolve 19 HIGH trivy findings in pnpm-lock.yaml All 19 findings had fixes available upstream, so per this repo's own .trivyignore policy (reserved for cases with no fix available), these get fixed rather than suppressed. vite (7.3.2 -> 7.3.5) is a direct dependency, bumped directly in every package.json that pins it. The other 8 (@xmldom/xmldom, flatted, form-data, immutable, js-cookie, linkify-it, minimatch, ws) are purely transitive. Verified empirically that `pnpm update <pkg>` silently no-ops on packages not declared in any workspace manifest, even when a parent's semver range would allow the fix (e.g. glob@10.5.0's `^9.0.4` covers 9.0.7) -- so pnpm.overrides is genuinely required here, not just convenient. minimatch is overridden with a version-range key (minimatch@>=9.0.0 <9.0.7) rather than a blanket override, since 6 different major versions of minimatch coexist in the tree for different consumers (3.x/5.x/10.x elsewhere); a blanket override would have forced all of them to 9.0.7 and likely broken callers expecting a different major's API. * fix(web): unify @types/node resolution to stop duplicate vite types The previous vite 7.3.2 -> 7.3.5 bump caused pnpm to resolve two different @types/node versions (25.7.0 and 26.1.0) as vite's optional peer across different workspace packages. vue-tsc then saw two structurally-different copies of vite's types (e.g. Plugin, HotUpdateOptions) and failed with TS2769 in design-system, web-client, web-pkg and web-test-helpers' vite.config.ts files. Force a single resolution via pnpm.overrides, pinned to 24.13.2 to match the Node 24 runtime (engines/volta) rather than an arbitrary newer major. * fix(tests): fix ocm/app-provider e2e suites' oCIS orchestration Both suites were newly wired up by the previous merge-web-repo commit and hadn't run against real CI yet, so their setup had two latent bugs: e2e-ocm: the federated instance's env only offset *_DEBUG_ADDR ports, leaving the actual service ports (e.g. gateway's default 127.0.0.1:9142) unset. The federated "ocis server" process then crashed trying to bind the same ports the primary instance already held. run-github.py's Behat apiOcm suite already solved this with a canonical tests/config/local/.env-federation port map (proven working, since apiOcm passes) -- reuse it instead of the ad-hoc offset. Also adds OCIS_ADD_RUN_SERVICES=ocm/OCIS_ENABLE_OCM, missing from the primary instance too. e2e-app-provider: tests/config/ci/app-registry.yaml maps its one mimetype to "FakeOffice" (the stub used by apiCollaboration) and has no docx entry at all, so the real Collabora/OnlyOffice containers this suite drives never appeared in the web UI's "New file" menu. Add a dedicated app-registry mapping both odt->Collabora and docx->OnlyOffice with allow_creation, and use it only when COLLABORATION_NEEDED is set. Signed-off-by: Lukas Hirt <info@hirt.cz> * fix(tests): trust federated oCIS cert, register office templates by target_ext e2e-ocm: the primary and federated instances each generate their own self-signed proxy cert. Only the primary's was ever added to the system CA trust store, so Chromium refused the federated instance's TLS handshake ("tls: unknown certificate") once federation began. Trust the federated cert too, and thread OCIS_BASE_DATA_PATH through its `ocis init` call (previously only set for the running server), since that's where the cert actually gets written. e2e-app-provider: reproduced the suite locally (real Collabora/ OnlyOffice containers + `ocis collaboration server`) and diffed `/app/list` before/after. allow_creation and default_app alone don't make the web UI's "New file" menu show an entry -- it additionally requires app_providers[].target_ext, which reva's app-provider only stamps onto a hardcoded set of "-template" mimetypes (vendor/github.com/owncloud/reva/v2/.../appprovider/templates.go), not the plain document mimetypes the previous config used. Existing odt/ docx files still open fine without a static entry, since Collabora/ OnlyOffice register their full supported mimetype list dynamically via WOPI discovery -- it's specifically file *creation* that needs this. Signed-off-by: Lukas Hirt <info@hirt.cz> * fix(changelog): shorten title over the 80-char lint limit changelog/unreleased/bugfix-personal-space-fail-closed.md landed on master (#12442) with a 97-char title, which changelog-lint rejects. GitHub tests PRs against a merge with the current master tip, so this started failing build-and-test on every open PR once master picked up that commit -- unrelated to this branch's own changes. Fixing it here since master needed to be merged in anyway. * fix(tests): load web apps the ocm/app-provider e2e suites depend on Both suites drive the web UI, and web only loads the web apps listed in its UI config's "apps" array. run-e2e.py reuses tests/config/ci/ocis-config.json, which predates the playwright suites and lists neither app they need, so both failed deterministically while the API-only Behat suites (apiOcm, apiCollaboration) kept passing: e2e-ocm: the "open-cloud-mesh" app menu item can never render because "ocm" was missing, so web-app-ocm was never loaded. Add it for the federated suite. Behind that sat a second bug: the invite flow embeds token@<BASE_URL_OCIS host> (127.0.0.1:9200) into invite codes, but the federated instance authorizes providers against tests/config/local/providers.json, which only lists localhost:9200. Address the primary as https://localhost:9200 when federated, mirroring run-github.py's passing apiOcm setup (the self-signed cert covers both hosts; other suites keep 127.0.0.1). e2e-app-provider: web-runtime only builds the per-provider Collabora/ OnlyOffice editor apps -- including their "New file" menu entries -- when web-app-external is loaded (web/packages/web-runtime/src/index.ts gates on applicationStore.has('web-app-external')), and "external" was missing. This also falsifies the previous target_ext theory: the template-mimetype registry was active in the failing run and the menu still never appeared, because the New-file menu needs only allow_creation plus a registered provider (web-app-external/src/index.ts). Revert the app registry to the plain odt->Collabora / docx->OnlyOffice mimetypes web's own e2e CI proved out (web/dev/docker/ocis/app-registry.yaml). Create-from-template still works without static entries: reva stamps target_ext onto the -template mimetypes the providers register via WOPI discovery. Signed-off-by: Lukas Hirt <info@hirt.cz> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: upload playwright traces and a11y report from e2e suites Port the two upload-artifact steps the standalone web repo's e2e workflow had: playwright error contexts/report output on failure, and the a11y report on any non-cancelled run. Paths are prefixed with web/ since the web repo now lives in that subdirectory, artifact names use the suite name instead of the job index, and the action pin matches the one already used in this workflow. Signed-off-by: Lukas Hirt <info@hirt.cz> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(tests): allow office editor iframes in the e2e proxy CSP The app-provider suite got past file creation but every office test then timed out waiting for the editor to render: ocis's default proxy CSP only allows frame-src 'self' (exact scheme+host+port), so the browser refused to embed the Collabora/OnlyOffice iframes served on other ports. The COLLABORA_DOMAIN/ONLYOFFICE_DOMAIN env vars do nothing on their own -- they are only substituted into a custom CSP file, which is why the pre-merge web CI always set PROXY_CSP_CONFIG_FILE_LOCATION (tests/drone/csp.yaml there). The localStorage SecurityError seen in the logs was a downstream symptom: the CSP-blocked frame ends up with an opaque origin where storage access throws. Add the two editor domains to tests/config/ci/csp.yaml's frame-src and img-src (mirroring web's proven csp.yaml) and point the collaboration suite at it. The keycloak suite shares this file; for it the new entries fall back to nonexistent default hosts and are inert. Signed-off-by: Lukas Hirt <info@hirt.cz> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(licenses): attribute REUSE.toml copyright to ownCloud contributors The web/ tree carries community contributions dating back to 2016; the CLA grants a relicensing right, not a copyright transfer, so declaring sole 2020-2026 ownCloud GmbH authorship was inaccurate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(tests): trust the Keycloak cert in e2e TLS setup The Keycloak cert had no SAN, and NODE_EXTRA_CA_CERTS only ever pointed at the oCIS cert, so any node-fetch/axios call made directly against Keycloak (admin token fetch, user provisioning) failed TLS validation and aborted the keycloak/mfa matrix jobs before a spec could run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(web): don't wipe assets/ before a successful build build-assets ran `git clean -xfd assets` before the pnpm build; a failed typecheck or vite build left assets/core/ empty, so the next Go embed or docker deployment served no web UI. Clean only after the build succeeds. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ci: fail clearly when a release tag matches no known package If the tag-prefix loop found no match, the workflow silently fell through to a jq lookup against "packages//package.json", failing with a confusing path error instead of naming the problem. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ci: drop duplicate dependency-license-check job web-tests.yml already enforces the license allow-list via `pnpm licenses:check` (license-checker-rseidelsohn) on every PR. check-licenses.yml's dependency-license-check ran a second, differently configured tool (npx license-checker, GPL/AGPL deny-list only), which could disagree with the first without adding coverage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Signed-off-by: Lukas Hirt <info@hirt.cz> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
71
.github/workflows/acceptance-tests.yml
vendored
71
.github/workflows/acceptance-tests.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
node-version: "24"
|
||||
|
||||
- name: Enable pnpm
|
||||
run: corepack enable && corepack prepare pnpm@10.28.1 --activate
|
||||
run: corepack enable && corepack prepare pnpm@10.33.3 --activate
|
||||
|
||||
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2.37.2
|
||||
with:
|
||||
@@ -428,6 +428,12 @@ jobs:
|
||||
- suite: oidc-iframe
|
||||
args: "--type playwright specs/oidc/iframeTokenRenewal.spec.ts"
|
||||
oidc_iframe: true
|
||||
- suite: app-provider
|
||||
args: "--type playwright --suites app-provider"
|
||||
collaboration: true
|
||||
- suite: ocm
|
||||
args: "--type playwright --suites ocm"
|
||||
federated: true
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
@@ -437,7 +443,7 @@ jobs:
|
||||
node-version: "24.15.0"
|
||||
- name: Enable pnpm
|
||||
run: |
|
||||
corepack enable && corepack prepare pnpm@10.28.1 --activate
|
||||
corepack enable && corepack prepare pnpm@10.33.3 --activate
|
||||
pnpm config set store-dir ./.pnpm-store
|
||||
|
||||
- name: Install libvips runtime
|
||||
@@ -458,7 +464,7 @@ jobs:
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: playwright-chromium-${{ hashFiles('ci.env') }}
|
||||
key: playwright-chromium-${{ hashFiles('web/pnpm-lock.yaml') }}
|
||||
|
||||
# --- Tika (search suite only) ---
|
||||
- name: Start Tika
|
||||
@@ -476,7 +482,8 @@ jobs:
|
||||
openssl req -x509 -newkey rsa:2048 \
|
||||
-keyout keycloak-certs/keycloakkey.pem \
|
||||
-out keycloak-certs/keycloakcrt.pem \
|
||||
-nodes -days 365 -subj '/CN=keycloak'
|
||||
-nodes -days 365 -subj '/CN=keycloak' \
|
||||
-addext 'subjectAltName=DNS:localhost,IP:127.0.0.1'
|
||||
chmod -R 777 keycloak-certs
|
||||
|
||||
- name: Start Postgres
|
||||
@@ -526,6 +533,44 @@ jobs:
|
||||
|| (echo "=== keycloak logs ===" && docker logs keycloak --tail 80 && exit 1)
|
||||
echo "keycloak ready."
|
||||
|
||||
# --- Collabora + OnlyOffice (app-provider suite only) ---
|
||||
- name: Start Collabora
|
||||
if: matrix.collaboration == true
|
||||
run: |
|
||||
docker run -d \
|
||||
--name collabora \
|
||||
--network host \
|
||||
--entrypoint bash \
|
||||
-e DONT_GEN_SSL_CERT=set \
|
||||
-e "extra_params=--o:ssl.enable=true --o:ssl.termination=true --o:welcome.enable=false --o:net.frame_ancestors=https://127.0.0.1:9200" \
|
||||
collabora/code:25.04.7.3.1 \
|
||||
-c "coolconfig generate-proof-key && bash /start-collabora-online.sh"
|
||||
timeout 150 bash -c 'until curl -kfsSL https://localhost:9980/hosting/discovery > /dev/null; do sleep 5; done'
|
||||
echo "collabora ready."
|
||||
|
||||
- name: Start OnlyOffice
|
||||
if: matrix.collaboration == true
|
||||
run: |
|
||||
sudo systemctl stop postgresql || true
|
||||
docker run -d \
|
||||
--name onlyoffice \
|
||||
--network host \
|
||||
-e WOPI_ENABLED=true \
|
||||
-e USE_UNAUTHORIZED_STORAGE=true \
|
||||
-v "${{ github.workspace }}/tests/config/ci/only-office.json:/tmp/local.json:ro" \
|
||||
--entrypoint /bin/sh \
|
||||
onlyoffice/documentserver:9.2.1 \
|
||||
-c "set -e
|
||||
cp /tmp/local.json /etc/onlyoffice/documentserver/local.json
|
||||
openssl req -x509 -newkey rsa:4096 -keyout onlyoffice.key -out onlyoffice.crt -sha256 -days 365 -batch -nodes
|
||||
mkdir -p /var/www/onlyoffice/Data/certs
|
||||
cp onlyoffice.key /var/www/onlyoffice/Data/certs/
|
||||
cp onlyoffice.crt /var/www/onlyoffice/Data/certs/
|
||||
chmod 400 /var/www/onlyoffice/Data/certs/onlyoffice.key
|
||||
/app/ds/run-document-server.sh"
|
||||
timeout 150 bash -c 'until curl -kfsSL https://localhost:443/hosting/discovery > /dev/null; do sleep 5; done'
|
||||
echo "onlyoffice ready."
|
||||
|
||||
- name: Run e2e-${{ matrix.suite }}
|
||||
run: E2E_ARGS="${{ matrix.args }}" python3 tests/acceptance/run-e2e.py
|
||||
env:
|
||||
@@ -534,6 +579,24 @@ jobs:
|
||||
MFA_NEEDED: ${{ matrix.mfa == true && 'true' || 'false' }}
|
||||
OIDC_NEEDED: ${{ matrix.oidc == true && 'true' || 'false' }}
|
||||
OIDC_IFRAME_NEEDED: ${{ matrix.oidc_iframe == true && 'true' || 'false' }}
|
||||
COLLABORATION_NEEDED: ${{ matrix.collaboration == true && 'true' || 'false' }}
|
||||
FEDERATED_NEEDED: ${{ matrix.federated == true && 'true' || 'false' }}
|
||||
|
||||
- name: Upload tracing result
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: playwright-traces-${{ matrix.suite }}-${{ github.run_attempt }}
|
||||
path: web/reports/e2e
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload a11y result
|
||||
if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: playwright-a11y-result-${{ matrix.suite }}-${{ github.run_attempt }}
|
||||
path: web/reports/e2e/a11y-report.json
|
||||
retention-days: 7
|
||||
|
||||
litmus:
|
||||
name: litmus
|
||||
|
||||
18
.github/workflows/check-licenses.yml
vendored
Normal file
18
.github/workflows/check-licenses.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Check licenses
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [master, stable-*]
|
||||
|
||||
jobs:
|
||||
license-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install REUSE tool
|
||||
run: pip install reuse
|
||||
|
||||
- name: Run REUSE lint
|
||||
run: reuse lint
|
||||
12
.github/workflows/commit-message.yml
vendored
Normal file
12
.github/workflows/commit-message.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Validate commit message
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, stable-*]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
uses: owncloud/reusable-workflows/.github/workflows/semantic-git-message.yml@main
|
||||
84
.github/workflows/release-npm-packages.yml
vendored
Normal file
84
.github/workflows/release-npm-packages.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
name: Release NPM packages
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "babel-preset-v*"
|
||||
- "design-system-v*"
|
||||
- "eslint-config-v*"
|
||||
- "extension-sdk-v*"
|
||||
- "prettier-config-v*"
|
||||
- "tsconfig-v*"
|
||||
- "web-client-v*"
|
||||
- "web-pkg-v*"
|
||||
- "web-test-helpers-v*"
|
||||
|
||||
jobs:
|
||||
release-npm:
|
||||
name: Publish NPM package
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: 24.15.0
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Setup pnpm
|
||||
run: corepack enable && corepack prepare pnpm@10.33.3 --activate
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Determine package
|
||||
id: package
|
||||
run: |
|
||||
TAG="${{ github.ref_name }}"
|
||||
PACKAGES="babel-preset design-system eslint-config extension-sdk prettier-config tsconfig web-client web-pkg web-test-helpers"
|
||||
for pkg in $PACKAGES; do
|
||||
if [[ "$TAG" == "${pkg}-v"* ]]; then
|
||||
echo "name=$pkg" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${TAG#${pkg}-v}" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
echo "tag '$TAG' does not match any known package prefix: $PACKAGES"
|
||||
exit 1
|
||||
|
||||
- name: Verify package version
|
||||
run: |
|
||||
PKG="${{ steps.package.outputs.name }}"
|
||||
VERSION="${{ steps.package.outputs.version }}"
|
||||
ACTUAL_VERSION=$(jq -r '.version' < "packages/${PKG}/package.json")
|
||||
echo "Build ${PKG} ${VERSION} package.json: ${ACTUAL_VERSION}"
|
||||
if [ "${ACTUAL_VERSION}" != "${VERSION}" ]; then
|
||||
echo "git tag does not match version in web/packages/${PKG}/package.json"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build tokens
|
||||
run: pnpm build:tokens
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
PKG="${{ steps.package.outputs.name }}"
|
||||
case "$PKG" in
|
||||
design-system|web-client|web-pkg|web-test-helpers)
|
||||
pnpm --filter "@ownclouders/${PKG}" vite build
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Publish to NPM
|
||||
run: |
|
||||
pnpm publish \
|
||||
--no-git-checks --filter "@ownclouders/${{ steps.package.outputs.name }}" \
|
||||
--access public --tag latest
|
||||
19
.github/workflows/translation-sync.yml
vendored
19
.github/workflows/translation-sync.yml
vendored
@@ -20,3 +20,22 @@ jobs:
|
||||
TX_TOKEN: ${{ secrets.TX_TOKEN }}
|
||||
TRANSLATION_APP_ID: ${{ secrets.TRANSLATION_APP_ID }}
|
||||
TRANSLATION_APP_PRIVATE_KEY: ${{ secrets.TRANSLATION_APP_PRIVATE_KEY }}
|
||||
|
||||
# web/ is a pnpm workspace nested inside the repo, not covered by the
|
||||
# root-level L10N_MODULES/sub_path: . sync above (that job has no
|
||||
# package.json at the repo root, so a pnpm install there would be a
|
||||
# no-op/fail). Run it as its own invocation scoped to sub_path: web,
|
||||
# sequenced after `sync` since the reusable workflow always pushes to
|
||||
# the same hardcoded chore/translations-update branch.
|
||||
sync-web:
|
||||
needs: sync
|
||||
uses: owncloud/reusable-workflows/.github/workflows/translation-sync.yml@main
|
||||
with:
|
||||
mode: make
|
||||
package_manager: pnpm
|
||||
reviewers: kobergj,mmattel
|
||||
sub_path: web
|
||||
secrets:
|
||||
TX_TOKEN: ${{ secrets.TX_TOKEN }}
|
||||
TRANSLATION_APP_ID: ${{ secrets.TRANSLATION_APP_ID }}
|
||||
TRANSLATION_APP_PRIVATE_KEY: ${{ secrets.TRANSLATION_APP_PRIVATE_KEY }}
|
||||
|
||||
105
.github/workflows/web-tests.yml
vendored
Normal file
105
.github/workflows/web-tests.yml
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
name: Web Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [master, stable-*]
|
||||
|
||||
jobs:
|
||||
detect-web-changes:
|
||||
name: detect-web-changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
web-changed: ${{ steps.check.outputs.web-changed }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check if web/ changed
|
||||
id: check
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "push" ]]; then
|
||||
echo "web-changed=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PR_TITLE="${{ github.event.pull_request.title }}"
|
||||
if echo "$PR_TITLE" | grep -qi "\[full-ci\]"; then
|
||||
echo "web-changed=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CHANGED_FILES=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}" 2>/dev/null || git diff --name-only HEAD~1)
|
||||
|
||||
WEB_CHANGED=false
|
||||
while IFS= read -r file; do
|
||||
case "$file" in
|
||||
web/*) WEB_CHANGED=true; break ;;
|
||||
.github/workflows/web-tests.yml) WEB_CHANGED=true; break ;;
|
||||
esac
|
||||
done <<< "$CHANGED_FILES"
|
||||
|
||||
echo "web-changed=$WEB_CHANGED" >> "$GITHUB_OUTPUT"
|
||||
echo "web/ changed: $WEB_CHANGED"
|
||||
|
||||
web-build-test:
|
||||
name: web-build-test
|
||||
needs: [detect-web-changes]
|
||||
if: needs.detect-web-changes.outputs.web-changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
with:
|
||||
version: 10.33.3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: 24.15.0
|
||||
cache: pnpm
|
||||
cache-dependency-path: web/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Check licenses
|
||||
run: pnpm licenses:check
|
||||
|
||||
- name: Save licenses
|
||||
run: pnpm licenses:csv && pnpm licenses:save
|
||||
|
||||
- name: Check types
|
||||
run: pnpm check:types
|
||||
|
||||
- name: Check format
|
||||
run: pnpm check:format
|
||||
|
||||
- name: Lint
|
||||
run: pnpm lint
|
||||
|
||||
- name: Run unit tests
|
||||
run: pnpm test:unit --coverage
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
web-tests-passed:
|
||||
name: web-tests-passed
|
||||
needs: [detect-web-changes, web-build-test]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check web-build-test passed or was skipped
|
||||
run: |
|
||||
if [[ "${{ needs.web-build-test.result }}" == "failure" || "${{ needs.web-build-test.result }}" == "cancelled" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
8
CODE_OF_CONDUCT.md
Normal file
8
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Code of Conduct
|
||||
|
||||
This project follows the ownCloud Code of Conduct.
|
||||
|
||||
Please read the full Code of Conduct at:
|
||||
**<https://owncloud.com/contribute/code-of-conduct/>**
|
||||
|
||||
By participating in this project, you agree to abide by its terms.
|
||||
266
CONTRIBUTING.md
266
CONTRIBUTING.md
@@ -1,263 +1,9 @@
|
||||
First of all, thank you for taking the time to read this and your interest in contributing to ownCloud Infinite Scale!
|
||||
# Contributing
|
||||
|
||||
The following is a set of guidelines for contributing to most of the projects hosted in the [ownCloud Organization](https://github.com/owncloud) on [GitHub](https://www.github.com). These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
||||
Thank you for your interest in contributing to this project!
|
||||
|
||||
For simplicity reasons, this document mostly refers to the ownCloud [Infinite Scale project](https://www.github.com/owncloud/ocis), but it should be easily transferable to other (sub)projects.
|
||||
Please read the full contributing guidelines at:
|
||||
**<https://owncloud.com/contribute/>**
|
||||
|
||||
#### Table Of Contents
|
||||
|
||||
[I don't want to read this whole thing, I just have a question](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
|
||||
|
||||
[What should I know before I get started](#what-should-i-know-before-i-get-started)
|
||||
* [ownCloud is hosted on GitHub](#owncloud-is-hosted-on-github)
|
||||
* [ownCloud Company, Engineering Partners and Community](#owncloud-company,-engineering-partners-and-community)
|
||||
* [Licensing and CLA](#licensing-and-cla)
|
||||
|
||||
[How Can I Contribute](#how-can-i-contribute)
|
||||
* [Help spreading the word](#help-spreading-the-word)
|
||||
* [Reporting Bugs](#reporting-bugs)
|
||||
* [Suggesting Enhancements](#suggesting-enhancements)
|
||||
* [Your First Code Contribution](#your-first-code-contribution)
|
||||
* [Pull Requests](#pull-requests)
|
||||
* [Documentation Contributions](#documentation-contributions)
|
||||
* [Internationalization](#internationalization)
|
||||
* [Deployments: Docker, Ansible and friends](#deployments-docker-ansible-and-friends)
|
||||
|
||||
[Styleguides](#styleguides)
|
||||
* [Git Commit Messages](#git-commit-messages)
|
||||
* [Golang Styleguide](#golang-styleguide)
|
||||
* [Web Styleguide](#web-styleguide)
|
||||
* [Documentation Styleguide](#documentation-styleguide)
|
||||
|
||||
[Additional Notes](#additional-notes)
|
||||
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
|
||||
|
||||
## I don't want to read this whole thing I just have a question
|
||||
|
||||
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
|
||||
|
||||
For general questions, please refer to [ownCloud's FAQs](https://owncloud.com/faq/) or ask on the [ownCloud Central Server](https://central.owncloud.org/).
|
||||
|
||||
We also have a [Matrix channel](https://matrix.to/#/#ocis:matrix.org) to answer your questions specifically about ownCloud Infinite Scale.
|
||||
|
||||
## What should I know before I get started
|
||||
|
||||
### ownCloud is hosted on GitHub
|
||||
|
||||
To effectively contribute to ownCloud Infinite Scale, you need a GitHub account. You can get that for free at [GitHub](https://github.com/join). You can find howtos on the internet, for example [here](https://www.wikihow.com/Create-an-Account-on-GitHub).
|
||||
|
||||
For other ways of contributing, for example with translations, other systems require you to have an account as well, for example [Transifex](https://www.transifex.com).
|
||||
|
||||
The ownCloud project follows the strict GitHub workflow of development as briefly [described here](https://guides.github.com/introduction/flow/).
|
||||
|
||||
### ownCloud Company, Engineering Partners and Community
|
||||
|
||||
ownCloud Infinite Scale is largely created by developers who are employed by the [ownCloud company](https://www.owncloud.com), which is located in Germany. It is providing support for ownCloud for customers worldwide. In addition, there are engineering partners who also work full time on ownCloud related code, for example in [CERN REVA](https://github.com/cs3org/reva/).
|
||||
|
||||
Because of that fact, the pace that the development is moving forward is sometimes high for people who are not willing and/or able to spend a comparable amount of time to contribute. Even though this can be a challenge, it should not scare anybody away. Here is our clear commitment that we feel honored by everybody who is interested in our work and improves it, no matter how big the contribution might be.
|
||||
|
||||
We as the full time devs from either organization are doing our best to listen, review and consider all changes that are brought forward following this guideline and make sense for the project.
|
||||
|
||||
### Licensing and CLA
|
||||
|
||||
We are very happy that there is *no CLA* required for most of the code of ownCloud Infinite Scale.
|
||||
|
||||
Currently, only for the following components you need to sign a [Contributors License Agreement](https://en.wikipedia.org/wiki/Contributor_License_Agreement):
|
||||
|
||||
* [ownCloud Web](https://github.com/owncloud/web/): [Link to CLA](https://owncloud.com/contribute/join-the-development/contributor-agreement/)
|
||||
|
||||
Please make sure to read and understand the details of the CLA before starting to invest time on a component that requires it. If you have any questions or concerns please feel free to raise them with us.
|
||||
|
||||
## How Can I Contribute
|
||||
|
||||
There are many ways to contribute to open source projects, and all are equally valuable and appreciated.
|
||||
|
||||
### Help spreading the word
|
||||
|
||||
This way to contribute to the project can not be overestimated: People who talk about their experience with ownCloud Infinite Scale and help others with that are the key to success of the project.
|
||||
|
||||
There are too many ways of doing that to line them up here, but examples are answering questions in [ownCloud Central](https://central.owncloud.org/) or on [ownCloud Talk](https://talk.owncloud.com/channel/ocis), writing blog posts etc. pp.
|
||||
|
||||
There is no formal guideline to this, just do it :-)
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
This section guides you through submitting a bug report for ownCloud Infinite Scale. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/owncloud/ocis/issues/new?Type%3ABug&template=bug_report.md), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. If you have permission to reopen the issue, feel free to do so.
|
||||
|
||||
#### Before Submitting A Bug Report
|
||||
|
||||
* **Make sure you are running a recent version** Usually, developers' interest in old versions of software drops very fast once a new shiny version has been released. So the general recommendation is: Use the latest released version or even the current master to reproduce problems that you might encounter. That helps a lot to attract developers attention.
|
||||
* **Determine which [repository](https://github.com/owncloud) the problem should be reported in**.
|
||||
* **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Aowncloud)** with possibly a more granular filter on the repository, to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one **if you have new information**. Please abstain from adding "plus ones", except using the GitHub emojis. That might indicate how many users are affected.
|
||||
|
||||
#### How Do I Submit A (Good) Bug Report
|
||||
|
||||
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](https://github.com/owncloud) your bug is related to, create an issue on that repository and provide the following information by filling in [the template](https://github.com/owncloud/ocis/issues/new?Type%3ABug&template=bug_report.md).
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
* **Describe the exact steps which reproduce the problem** in as many details as possible. Start with describing, from a user perspective, what you tried to achieve, i.e. "I want to share some pictures with Grandma". When listing steps, **don't just say what you did, but explain how you did it**. For example, if you uploaded a file to ownCloud, say which client you used, which way of uploading you chose, if the name was special somehow and how big it was.
|
||||
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
|
||||
* **Explain which behavior you expected to see instead and why.**
|
||||
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
|
||||
* **If you report a web browser related problem**, consider to using the browser's Web developer tools (such as the debugger, console or network monitor) to check what happened. Make sure to add screenshots of the utilities if you are short of time to interpret it.
|
||||
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
|
||||
|
||||
Provide more context by answering these questions:
|
||||
|
||||
* **Did the problem start happening recently** (e.g. after updating to a new version) or was this always a problem?
|
||||
* If the problem started happening recently, **can you reproduce the problem in an older version?** What's the most recent version in which the problem doesn't happen? You can find more information about how to set up [test environments](https://owncloud.dev/ocis/development/testing/) in the [developer documentation](https://owncloud.dev/#developer-documentation).
|
||||
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||
|
||||
Include details about your configuration and environment as asked for in the template.
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for ownCloud Infinite Scale, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:.
|
||||
|
||||
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](https://github.com/owncloud/ocis/.github/blob/master/.github/ISSUE_TEMPLATE/feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed.
|
||||
|
||||
#### Before Submitting An Enhancement Suggestion
|
||||
|
||||
* **Check if there's already an extension or other component which provides that enhancement, even in a different way.**
|
||||
* **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Aowncloud)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. Feel free to use the GitHub emojis to indicate that you are in favour of an enhancement request.
|
||||
|
||||
#### How Do I Submit A (Good) Enhancement Suggestion
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](https://github.com/owncloud) your enhancement suggestion is related to, create an issue on that repository and provide the following information:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the suggestion.
|
||||
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Explain why this enhancement would be useful** to most ownCloud users.
|
||||
* **List some other projects or products where this enhancement exists.**
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to ownCloud? You can start by looking through these `Needs-help` issues:
|
||||
|
||||
* The [Good first issue](https://github.com/owncloud/ocis/labels/Topic%3Agood-first-issue) label marks good items to start with.
|
||||
* [Tests needed](https://github.com/owncloud/ocis/labels/Interaction%3ANeeds-tests) - issues which would benefit from a test.
|
||||
* [Help wanted issues](https://github.com/owncloud/ocis/labels/Interaction%3ANeeds-help) - issues which should be a bit more involved.
|
||||
|
||||
It is fine to pick one of the list following personal preference. While not perfect, number of comments is a reasonable proxy for impact a given change will have.
|
||||
|
||||
To find out how to set up ownCloud Infinite Scale for local development please refer to the [Developer Documentation](https://owncloud.dev/ocis/development/getting-started/). It contains a lot of information that will come in handy when starting to work on the project.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
All contributions to ownClouds projects use so-called pull requests following the [GitHub PR workflow](https://guides.github.com/introduction/flow/).
|
||||
|
||||
Please follow these steps to have your contribution considered by the maintainers:
|
||||
|
||||
* Follow all instructions in [the template](https://github.com/owncloud/ocis/blob/master/.github/pull_request_template.md)
|
||||
* Follow the [styleguides](#styleguides) where applicable
|
||||
* After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing <details><summary>What if the status checks are failing?</summary>If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.</details>
|
||||
|
||||
While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.
|
||||
|
||||
### Documentation Contributions
|
||||
|
||||
ownCloud is very proud of the documentation it has, which is the work of a great team of people. Of course, also the documentation is open to contributions.
|
||||
|
||||
See the [Getting Started Guide](https://owncloud.dev/ocis/development/getting-started/) on how to get started. Other useful information is summarized in the [Documentation Readme](https://github.com/owncloud/docs).
|
||||
|
||||
### Internationalization
|
||||
|
||||
Our projects are getting translated into many languages to allow people from all over the world to use ownCloud in their native language. For translations, ownCloud uses [Transifex](https://www.transifex.com) as a community based collaboration platform for internationalization.
|
||||
|
||||
For contributions please refer to the [Transifex Resources](https://www.transifex.com/resources/) to learn how to improve ownClouds translations there.
|
||||
|
||||
### Deployments: Docker, Ansible and friends
|
||||
|
||||
Depending on the ownCloud component, there is complex deployment tooling to install in various environments. There is for example [ownCloud Ansible](https://github.com/owncloud-ansible) with Ansible resources. Contributions to that are very appreciated and follow the same guidelines as every other code contribution.
|
||||
|
||||
## Styleguides
|
||||
|
||||
To keep up with a consistent code and tooling landscape, some ownCloud modules maintain styleguides for contributions. It is mandatory to follow them in contributions.
|
||||
|
||||
### Git Commit Messages
|
||||
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally after the first line
|
||||
* When only changing documentation, include `[docs-only]` in the commit title
|
||||
|
||||
### Golang Styleguide
|
||||
|
||||
Use the built-in golang code formatter before submitting the patch. Also, consulting documentation like [Effective Go](https://golang.org/doc/effective_go) or [Practical Go](http://bit.ly/gcsg-2019) helps to improve the code quality.
|
||||
|
||||
### Web Styleguide
|
||||
|
||||
Refer to related documents in the [ownCloud Web Repository](https://github.com/owncloud/web).
|
||||
|
||||
#### Documentation Styleguide
|
||||
|
||||
See the [ownCloud Documentation Styleguide](https://github.com/owncloud/docs/blob/master/docs/style-guide.md).
|
||||
|
||||
## Additional Notes
|
||||
|
||||
### Issue and Pull Request Labels
|
||||
|
||||
This section lists the labels we use to help us track and manage issues and pull requests. Most labels are used across all ownCloud repositories, but some are specific.
|
||||
|
||||
[GitHub search](https://help.github.com/articles/searching-issues/) makes it easy to use labels for finding groups of issues or pull requests you're interested in. To help you find issues and pull requests, each label can be used in search links for finding open items with that label in the ownCloud repositories.
|
||||
|
||||
The labels are loosely grouped by their purpose, but it's not required that every issue has a label from every group or that an issue can't have more than one label from the same group.
|
||||
|
||||
The list here contains all the more general categories of issues which are followed by a colon and a specific value. For example severity 1 looks like `Severity:sev1-critical`.
|
||||
|
||||
#### Platform
|
||||
|
||||
Describes the platform the issue is happening on, i.e. iOS or Windows.
|
||||
|
||||
#### Estimation
|
||||
|
||||
T-Shirt sizes for effort estimation to fix that bug or implement an enhancement. Ranges from XS to XXXL.
|
||||
|
||||
#### Priority
|
||||
|
||||
P1 to P4 (lowest) to indicate a priority. Mostly a tool for internal project management and support.
|
||||
|
||||
#### QA
|
||||
|
||||
Flags to indicate the internal QA status in terms of process and priority. Please leave alone unless you're QA ;-)
|
||||
|
||||
#### Severity
|
||||
|
||||
Severity for the product, mostly impact on user.
|
||||
|
||||
#### Type
|
||||
|
||||
The issue type, helps to structure the issues in the agile categories (Epic, Story...) but also organizational ones.
|
||||
|
||||
#### Topic
|
||||
|
||||
A general category of the topic of a ticket.
|
||||
|
||||
#### Category
|
||||
|
||||
Categorizes the issue to also indicate the type of the issue.
|
||||
|
||||
#### Status
|
||||
|
||||
The status in the ticket life cycle. Keep an eye on that one, especially for the `Waiting-for-Feedback` tag which might indicate that the reporter is asked for feedback.
|
||||
|
||||
#### Interaction
|
||||
|
||||
Another label that indicates the type of the issue.
|
||||
|
||||
#### Browser
|
||||
|
||||
Important for browser dependent web issues. It specifies the browser that shows the error.
|
||||
|
||||
#### Early-Adopter
|
||||
|
||||
Tags issues that were reported by one of the oCIS early adopters, i.e. customers and users who start using ownCloud Infinite Scale before its general availability.
|
||||
For development setup, coding standards, and pull request process,
|
||||
see the README in this repository.
|
||||
|
||||
188
LICENSES/Apache-2.0.txt
Normal file
188
LICENSES/Apache-2.0.txt
Normal file
@@ -0,0 +1,188 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
11
LICENSES/BSD-3-Clause.txt
Normal file
11
LICENSES/BSD-3-Clause.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Copyright (c) <year> <owner>.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
18
LICENSES/MIT.txt
Normal file
18
LICENSES/MIT.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) <year> <copyright holders>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
373
LICENSES/MPL-2.0.txt
Normal file
373
LICENSES/MPL-2.0.txt
Normal file
@@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
31
NOTICE
Normal file
31
NOTICE
Normal file
@@ -0,0 +1,31 @@
|
||||
ownCloud Infinite Scale (ocis)
|
||||
Copyright 2020-2026 ownCloud GmbH
|
||||
|
||||
This product includes software developed by ownCloud GmbH and the
|
||||
ownCloud community, licensed under the Apache License, Version 2.0
|
||||
(see the LICENSE file in this repository's root directory).
|
||||
|
||||
--------------------------------------------------------------------
|
||||
Provenance note: the ownCloud Web frontend (web/)
|
||||
--------------------------------------------------------------------
|
||||
|
||||
The `web/` directory contains the source of the ownCloud Web frontend.
|
||||
It was formerly maintained as the independent repository
|
||||
https://github.com/owncloud/web and, through its final release
|
||||
(tag `v12.5.0`, also tagged `last-agpl-release`, commit
|
||||
b16a34fdf5569d2fd63b1ff3c575c1a4ee569ad3), was historically licensed
|
||||
under the GNU Affero General Public License, version 3.0 (AGPL-3.0).
|
||||
|
||||
All contributors to that repository accepted the ownCloud Contributor
|
||||
License Agreement (CLA), which grants ownCloud GmbH the right to
|
||||
relicense their contributions. Under that grant, ownCloud GmbH has
|
||||
relicensed the source tree at the commit above from AGPL-3.0 to the
|
||||
Apache License, Version 2.0 -- the same license that covers the rest
|
||||
of this repository -- and merged it into this repository.
|
||||
|
||||
The pre-relicense, AGPL-3.0-licensed development history remains
|
||||
publicly available in the archived https://github.com/owncloud/web
|
||||
repository for historical and attribution purposes. That history is
|
||||
not the license under which the code in this repository is
|
||||
distributed; this repository's root LICENSE (Apache-2.0) governs the
|
||||
entirety of this repository, including web/.
|
||||
9
REUSE.toml
Normal file
9
REUSE.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
version = 1
|
||||
SPDX-PackageName = "ocis"
|
||||
SPDX-PackageSupplier = "ownCloud GmbH <devops@owncloud.com>"
|
||||
SPDX-PackageDownloadLocation = "https://github.com/owncloud/ocis"
|
||||
|
||||
[[annotations]]
|
||||
path = "**"
|
||||
SPDX-FileCopyrightText = "2016-2026 ownCloud GmbH - A Kiteworks Company and ownCloud contributors"
|
||||
SPDX-License-Identifier = "Apache-2.0"
|
||||
11
SECURITY.md
Normal file
11
SECURITY.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Do NOT open a public GitHub issue for security vulnerabilities.**
|
||||
|
||||
Please report security issues responsibly via:
|
||||
**<https://security.owncloud.com>**
|
||||
|
||||
You can also report vulnerabilities through our YesWeHack bug bounty program:
|
||||
**<https://yeswehack.com/programs/owncloud-bug-bounty-program>**
|
||||
10
SUPPORT.md
Normal file
10
SUPPORT.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Support
|
||||
|
||||
For support with this project, please use the following channels:
|
||||
|
||||
- **Enterprise Support**: <https://owncloud.com/contact-us/>
|
||||
- **Community discussions**: https://github.com/orgs/owncloud/discussions
|
||||
- **Matrix Chat**: <https://app.element.io/#/room/#owncloud:matrix.org>
|
||||
- **Documentation**: <https://doc.owncloud.com>
|
||||
|
||||
Please do not use GitHub issues for general support questions.
|
||||
@@ -1,4 +1,4 @@
|
||||
Bugfix: Fail closed on inconclusive Drives.Create check; preserve personal space
|
||||
Bugfix: Do not disable personal space on inconclusive permission check
|
||||
|
||||
When a user's role is (re-)assigned, both the proxy (on OIDC login) and the graph
|
||||
appRoleAssignment handler check the `Drives.Create` permission to decide whether to
|
||||
|
||||
4
ci.env
4
ci.env
@@ -1,4 +0,0 @@
|
||||
# Pins the ownCloud Web frontend version used in CI tests.
|
||||
# Read by: tests/acceptance/run-e2e.py and .github/workflows/acceptance-tests.yml (Playwright cache key).
|
||||
WEB_COMMITID=7dbf6ee5d4df704d19cc33da5564042e226e6871
|
||||
WEB_BRANCH=stable-12.4
|
||||
@@ -22,7 +22,7 @@ Welcome to our developer documentation. Here you find documentation with focus f
|
||||
- [oCIS]({{< ref "./ocis" >}}) server
|
||||
- oCIS Services
|
||||
- Clients like:
|
||||
- [ownCloud Web](https://github.com/owncloud/web) - the new web frontend for oCIS and ownCloud
|
||||
- [ownCloud Web](https://github.com/owncloud/ocis/tree/master/web) - the new web frontend for oCIS and ownCloud, shipped in-tree as part of oCIS
|
||||
- [ownCloud Android app](https://github.com/owncloud/android)
|
||||
- [ownCloud iOS app](https://github.com/owncloud/ios-app)
|
||||
- [ownCloud Desktop Syncing Client](https://github.com/owncloud/client)
|
||||
@@ -37,7 +37,7 @@ You can also find all client sources on [GitHub](https://github.com/owncloud/).
|
||||
|
||||
## Join the oCIS Community
|
||||
|
||||
The [server repository](https://github.com/owncloud/ocis) on [GitHub](https://www.github.com) is a good entry point to the oCIS project. In addition to that there are also ownCloud projects for clients for [iOS](https://github.com/owncloud/ios-app), [Android](https://github.com/owncloud/android), the major [Desktop](https://github.com/owncloud/desktop) platforms and [ownCloud Web](https://github.com/owncloud/web).
|
||||
The [server repository](https://github.com/owncloud/ocis) on [GitHub](https://www.github.com) is a good entry point to the oCIS project -- it also contains the [ownCloud Web](https://github.com/owncloud/ocis/tree/master/web) frontend source in-tree. In addition to that there are also ownCloud projects for clients for [iOS](https://github.com/owncloud/ios-app), [Android](https://github.com/owncloud/android) and the major [Desktop](https://github.com/owncloud/desktop) platforms.
|
||||
|
||||
To chat about development, join our public chat on [matrix: ownCloud Infinite Scale](https://matrix.to/#/#ocis:matrix.org).
|
||||
|
||||
|
||||
@@ -386,13 +386,12 @@ The frontend for the minio server is available at `http://minio.owncloud.test` a
|
||||
|
||||
In case you want to run ownCloud Web from a development branch together with this deployment example (e.g. for feature development for the app provider frontend) you can use this deployment example with the local setup and some additional steps as described below.
|
||||
|
||||
1. Clone the [ownCloud Web repository](https://github.com/owncloud/web) on your development machine.
|
||||
2. Run `pnpm i && pnpm build:w` for `web`, so that it creates and continuously updates the `dist` folder for web.
|
||||
3. Add the dist folder as read only volume to `volumes` section of the `ocis` service in the `docker-compose.yml` file:
|
||||
1. From your local clone of the [ocis repository](https://github.com/owncloud/ocis), run `pnpm i && pnpm build:w` inside the `web/` directory, so that it creates and continuously updates the `dist` folder for web.
|
||||
2. Add the dist folder as read only volume to `volumes` section of the `ocis` service in the `docker-compose.yml` file:
|
||||
```yaml
|
||||
- /your/local/path/to/web/dist/:/web/dist:ro
|
||||
- /your/local/path/to/ocis/web/dist/:/web/dist:ro
|
||||
```
|
||||
Make sure to point to the `dist` folder inside your local copy of the web repository.
|
||||
Make sure to point to the `web/dist` folder inside your local copy of the ocis repository.
|
||||
4. Set the oCIS environment variables `WEB_ASSET_CORE_PATH` and `WEB_ASSET_APPS_PATH` in the `environment` section of the `ocis` service, so that it uses your mounted dist folder for the web assets, instead of the assets that are embedded into oCIS.
|
||||
```yaml
|
||||
WEB_ASSET_CORE_PATH: "/web/dist"
|
||||
|
||||
@@ -36,7 +36,7 @@ Depending on the functionality of your extension, you might need to integrate wi
|
||||
|
||||
### ownCloud Web
|
||||
|
||||
If your extension is not just doing something in the background, you will need a UI in order to allow the user to interact with your extension. You could just provide your own web frontend for that purpose, but for a better user experience you can easily integrate into the web frontend of oCIS, the new [ownCloud Web](https://github.com/owncloud/web).
|
||||
If your extension is not just doing something in the background, you will need a UI in order to allow the user to interact with your extension. You could just provide your own web frontend for that purpose, but for a better user experience you can easily integrate into the web frontend of oCIS, [ownCloud Web](https://github.com/owncloud/ocis/tree/master/web), which ships in-tree as part of oCIS.
|
||||
|
||||
ownCloud Web allows you to write an extension for itself and therefore offers a seamless user experience. Upon login, the user will be able to use the application switcher to switch between the files view, settings and other available and installed extensions, yours included. Furthermore it is also possible to register your extension for different file actions. As an example, you could offer your extension to the user for creating and editing office documents. The user will then be able to create or open a file with your application directly from the files view. How to provide create an extension for ownCloud Web can be seen best in [the Hello extension](https://github.com/owncloud/ocis-hello/blob/master/ui/app.js), whereas plain file handling without any web frontend is available in the [WOPI server extension](https://github.com/owncloud/ocis-wopiserver/blob/master/ui/app.js).
|
||||
|
||||
|
||||
@@ -10,28 +10,14 @@ geekdocFilePath: releasing.md
|
||||
|
||||
## Releasing
|
||||
|
||||
The next generation Web Frontend is shipped as an oCIS Extension. The `ocis-web` extension is also embedded in the single binary and part of the `ocis server` command.
|
||||
The Web Frontend source lives in-tree under `web/` and is built as part of the regular oCIS
|
||||
generate/release process — there is no separate repository, version pin, or release step to
|
||||
coordinate anymore.
|
||||
|
||||
To update this package within all the deliveries, we need to update the package in the following chain from the bottom to the top.
|
||||
Running `make generate` (or `make -C services/web ci-node-generate`) builds the web frontend
|
||||
from `web/` via `pnpm install && pnpm build` and copies the resulting assets into
|
||||
`services/web/assets/core`, from where they are embedded into the `ocis` binary via Go's
|
||||
`//go:embed` directive in `services/web/web.go`.
|
||||
|
||||
### Package Hierarchy
|
||||
|
||||
- [ocis](https://github.com/owncloud/ocis)
|
||||
- [ocis-web](https://github.com/owncloud/ocis/tree/master/web)
|
||||
- [ocis-pkg](https://github.com/owncloud/ocis/tree/master/ocis-pkg)
|
||||
- [ownCloud Web](https://github.com/owncloud/web)
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
Before updating the assets, make sure that [ownCloud Web](https://github.com/owncloud/web) has been released first
|
||||
and take note of its release tag name.
|
||||
|
||||
#### Updating ocis-web
|
||||
|
||||
1. Create a branch `update-web-$version` in the [ocis repository](https://github.com/owncloud/ocis)
|
||||
2. Change into web package folder via `cd web`
|
||||
3. Inside `web/`, update the `Makefile` so that the WEB_ASSETS_VERSION variable references the currently released version of https://github.com/owncloud/web
|
||||
4. Move to the changelog (`cd ../changelog/`) and add a changelog file to the `unreleased/` folder (You can copy an old web release changelog item as a template)
|
||||
5. Move to the repo root (`cd ..`) and update the `WEB_COMMITID` in `/ci.env` to the commit id from the released version (unless the existing commit id is already newer)
|
||||
6. **Optional:** Test the changes locally by running `cd ocis && go run cmd/ocis/main.go server`, visiting [https://localhost:9200](https://localhost:9200) and confirming everything renders correctly
|
||||
7. Commit your changes, push them and [create a PR](https://github.com/owncloud/ocis/pulls)
|
||||
To make changes to the web frontend, edit the source under `web/` directly and open a PR
|
||||
against this repository, the same as any other oCIS change.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SHELL := bash
|
||||
NAME := web
|
||||
WEB_ASSETS_VERSION = v12.4.0
|
||||
WEB_DIR := ../../web
|
||||
|
||||
include ../../.make/recursion.mk
|
||||
|
||||
@@ -28,18 +28,22 @@ include ../../.make/generate.mk
|
||||
ci-go-generate: # CI runs ci-node-generate automatically before this target
|
||||
|
||||
.PHONY: ci-node-generate
|
||||
ci-node-generate: pull-assets
|
||||
ci-node-generate: build-assets
|
||||
|
||||
.PHONY: pull-assets
|
||||
pull-assets:
|
||||
.PHONY: build-assets
|
||||
build-assets:
|
||||
cd $(WEB_DIR) && pnpm install && pnpm check:types && pnpm build
|
||||
cp $(WEB_DIR)/config/config.json.dist $(WEB_DIR)/dist/
|
||||
git clean -xfd assets
|
||||
curl --fail -slL -o- https://github.com/owncloud/web/releases/download/$(WEB_ASSETS_VERSION)/web.tar.gz | tar xzf - -C assets/core/
|
||||
cp -r $(WEB_DIR)/dist/. assets/core/
|
||||
|
||||
############ licenses ############
|
||||
.PHONY: ci-node-check-licenses
|
||||
ci-node-check-licenses: # ownCloud Web does the check on it's own
|
||||
ci-node-check-licenses:
|
||||
cd $(WEB_DIR) && pnpm licenses:check
|
||||
|
||||
.PHONY: ci-node-save-licenses
|
||||
ci-node-save-licenses:
|
||||
@mkdir -p ../../third-party-licenses/node/web
|
||||
@curl --fail -slL -o- https://github.com/owncloud/web/releases/download/$(WEB_ASSETS_VERSION)/third-party-licenses.tar.gz | tar xzf - -C ../../third-party-licenses/node/web
|
||||
cd $(WEB_DIR) && pnpm licenses:csv && pnpm licenses:save
|
||||
cp -r $(WEB_DIR)/third-party-licenses/third-party-licenses/. ../../third-party-licenses/node/web/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Web
|
||||
|
||||
The web service embeds and serves the static files for the [Infinite Scale Web Client](https://github.com/owncloud/web).
|
||||
The web service embeds and serves the static files for the Infinite Scale Web Client, whose source lives in-tree under [`web/`](https://github.com/owncloud/ocis/tree/master/web).
|
||||
Note that clients will respond with a connection error if the web service is not available.
|
||||
|
||||
The web service also provides a minimal API for branding functionality like changing the logo shown.
|
||||
@@ -25,7 +25,7 @@ for more details.
|
||||
### Web UI Config File
|
||||
|
||||
When defined via the `WEB_UI_CONFIG_FILE` environment variable, the configuration of the web UI can be made
|
||||
with a [json based](https://github.com/owncloud/web/tree/master/config) file.
|
||||
with a [json based](https://github.com/owncloud/ocis/tree/master/web/config) file.
|
||||
|
||||
### Embedding Web
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ services:
|
||||
# email
|
||||
EMAIL_HOST: email
|
||||
EMAIL_PORT: 8025
|
||||
env_file:
|
||||
- ../../../../ci.env
|
||||
volumes:
|
||||
- ./run-tests.sh:/test/run-tests.sh
|
||||
- ../../../../:/ocis
|
||||
|
||||
@@ -12,13 +12,11 @@ import sys
|
||||
import shlex
|
||||
import subprocess
|
||||
import signal
|
||||
import tempfile
|
||||
import time
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
WEB_REPO = "https://github.com/owncloud/web.git"
|
||||
|
||||
|
||||
def wait_for(condition_fn, timeout: int, label: str) -> None:
|
||||
deadline = time.time() + timeout
|
||||
while not condition_fn():
|
||||
@@ -78,6 +76,38 @@ def tika_warm(tika_url: str) -> bool:
|
||||
return r.stdout.strip() == "200"
|
||||
|
||||
|
||||
def app_providers_ready(ocis_url: str) -> bool:
|
||||
# Collabora and OnlyOffice register asynchronously with the app registry
|
||||
# over their WOPI bridge connection; don't start tests until both are up.
|
||||
cmd = ["curl", "-sk", "-uadmin:admin", f"{ocis_url}/app/list"]
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if r.returncode != 0 or not r.stdout.strip():
|
||||
return False
|
||||
try:
|
||||
data = json.loads(r.stdout)
|
||||
except json.JSONDecodeError:
|
||||
return False
|
||||
names = set()
|
||||
for mime in data.get("mime-types", []):
|
||||
for provider in mime.get("app_providers", []):
|
||||
names.add(provider.get("name"))
|
||||
return "Collabora" in names and "OnlyOffice" in names
|
||||
|
||||
|
||||
def load_env_file(path: Path) -> dict:
|
||||
"""Parse a bash-style env file (export KEY=value) into a dict."""
|
||||
env = {}
|
||||
for line in path.read_text().splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or line.startswith("!"):
|
||||
continue
|
||||
line = line.removeprefix("export ").strip()
|
||||
if "=" in line:
|
||||
k, v = line.split("=", 1)
|
||||
env[k.strip()] = v.strip()
|
||||
return env
|
||||
|
||||
|
||||
def run(cmd: list, env: dict = None, check: bool = True, cwd=None):
|
||||
e = {**os.environ, **(env or {})}
|
||||
return subprocess.run(cmd, env=e, check=check, cwd=cwd)
|
||||
@@ -95,15 +125,22 @@ def main() -> int:
|
||||
mfa_needed = os.environ.get("MFA_NEEDED", "").lower() == "true"
|
||||
oidc_needed = os.environ.get("OIDC_NEEDED", "").lower() == "true"
|
||||
oidc_iframe_needed = os.environ.get("OIDC_IFRAME_NEEDED", "").lower() == "true"
|
||||
collaboration_needed = os.environ.get("COLLABORATION_NEEDED", "").lower() == "true"
|
||||
federated_needed = os.environ.get("FEDERATED_NEEDED", "").lower() == "true"
|
||||
# MFA mode runs ocis behind keycloak with TOTP enforced
|
||||
keycloak_needed = keycloak_needed or mfa_needed
|
||||
|
||||
repo_root = Path(__file__).resolve().parents[2]
|
||||
ocis_bin = repo_root / "ocis/bin/ocis"
|
||||
wrapper_bin = repo_root / "tests/ociswrapper/bin/ociswrapper"
|
||||
ocis_url = "https://127.0.0.1:9200"
|
||||
# The federated suite must address the primary as localhost instead of
|
||||
# 127.0.0.1: the ocm invite flow bakes this host into invite codes
|
||||
# (token@host), and the federated instance authorizes it against
|
||||
# tests/config/local/providers.json (shared with run-github.py's apiOcm
|
||||
# suite), which only lists localhost:9200.
|
||||
ocis_url = "https://localhost:9200" if federated_needed else "https://127.0.0.1:9200"
|
||||
ocis_config_dir = Path.home() / ".ocis/config"
|
||||
web_dir = repo_root / "webTestRunner"
|
||||
web_dir = repo_root / "web"
|
||||
|
||||
# build ocis + ociswrapper only if not already provided (e.g. via artifact)
|
||||
if not ocis_bin.exists():
|
||||
@@ -112,22 +149,6 @@ def main() -> int:
|
||||
run(["make", "-C", str(repo_root / "tests/ociswrapper"), "build"],
|
||||
env={"GOWORK": "off"})
|
||||
|
||||
# clone + install web only if not already provided (e.g. via artifact)
|
||||
if not web_dir.exists():
|
||||
ci_env = {}
|
||||
ci_env_file = repo_root / "ci.env"
|
||||
if ci_env_file.exists():
|
||||
for line in ci_env_file.read_text().splitlines():
|
||||
if "=" in line and not line.startswith("#"):
|
||||
k, v = line.split("=", 1)
|
||||
ci_env[k.strip()] = v.strip()
|
||||
web_branch = ci_env.get("WEB_BRANCH", "master")
|
||||
web_commitid = ci_env.get("WEB_COMMITID", "")
|
||||
run(["git", "clone", "-b", web_branch, "--single-branch", "--no-tags",
|
||||
WEB_REPO, str(web_dir)])
|
||||
if web_commitid:
|
||||
subprocess.run(["git", "checkout", web_commitid], cwd=web_dir, check=True)
|
||||
|
||||
if not (web_dir / "node_modules").exists():
|
||||
pkg_manager = json.loads((web_dir / "package.json").read_text()).get("packageManager", "pnpm")
|
||||
run(["npm", "install", "--silent", "--global", "--force", pkg_manager])
|
||||
@@ -139,8 +160,17 @@ def main() -> int:
|
||||
|
||||
# init ocis
|
||||
run([str(ocis_bin), "init", "--insecure", "true"])
|
||||
# tests/config/ci/app-registry.yaml maps its one mimetype to "FakeOffice", the
|
||||
# stub used by run-github.py's (Behat) apiCollaboration suite. The app-provider
|
||||
# e2e suite drives real Collabora/OnlyOffice containers instead, so it needs its
|
||||
# own mapping to those app names, for both the odt and docx mimetypes it exercises.
|
||||
app_registry_src = (
|
||||
"tests/config/local/app-registry-office-suites.yaml"
|
||||
if collaboration_needed
|
||||
else "tests/config/ci/app-registry.yaml"
|
||||
)
|
||||
shutil.copy(
|
||||
repo_root / "tests/config/ci/app-registry.yaml",
|
||||
repo_root / app_registry_src,
|
||||
ocis_config_dir / "app-registry.yaml",
|
||||
)
|
||||
|
||||
@@ -170,6 +200,19 @@ def main() -> int:
|
||||
|
||||
gha_web_cfg = _patch_urls(drone_web_cfg, "https://ocis-server:9200", ocis_url)
|
||||
|
||||
# The web UI only loads the apps listed in its config. ocis-config.json predates
|
||||
# the playwright suites, so add what specific suites depend on:
|
||||
# - "external" is the blueprint app for the office editors: web-runtime builds
|
||||
# the per-provider Collabora/OnlyOffice apps (including their "New file" menu
|
||||
# entries) only when web-app-external itself is loaded.
|
||||
# - "ocm" provides the "open-cloud-mesh" federation UI the ocm suite drives.
|
||||
# (The federated instance's own config, tests/config/local/fed-ocis-web.json,
|
||||
# already lists it.)
|
||||
if collaboration_needed:
|
||||
gha_web_cfg["apps"].append("external")
|
||||
if federated_needed:
|
||||
gha_web_cfg["apps"].append("ocm")
|
||||
|
||||
# The web client reads its OIDC scope from openIdConnect.scope in this UI
|
||||
# config, NOT from the WEB_OIDC_SCOPE server env var, so override it here.
|
||||
# - oidc (refresh-token) spec asserts the scope contains `offline_access`.
|
||||
@@ -297,6 +340,56 @@ def main() -> int:
|
||||
if oidc_iframe_needed:
|
||||
server_env["IDP_ACCESS_TOKEN_EXPIRATION"] = "30"
|
||||
|
||||
if collaboration_needed:
|
||||
server_env.update({
|
||||
"MICRO_REGISTRY": "nats-js-kv",
|
||||
"MICRO_REGISTRY_ADDRESS": "127.0.0.1:9233",
|
||||
"FRONTEND_APP_HANDLER_SECURE_VIEW_APP_ADDR": "com.owncloud.api.collaboration.Collabora",
|
||||
# These two domains, the page origin, and Collabora's frame_ancestors
|
||||
# (workflow) must all use the same host literal: CSP source
|
||||
# expressions match by exact host.
|
||||
"COLLABORA_DOMAIN": "127.0.0.1:9980",
|
||||
"ONLYOFFICE_DOMAIN": "127.0.0.1:443",
|
||||
# The default proxy CSP only allows frame-src 'self', so the browser
|
||||
# refuses to embed the office editor iframes (different port). The CSP
|
||||
# file whitelists ${COLLABORA_DOMAIN}/${ONLYOFFICE_DOMAIN} in frame-src
|
||||
# -- without it the editors never load and every office test times out.
|
||||
"PROXY_CSP_CONFIG_FILE_LOCATION": str(repo_root / "tests/config/ci/csp.yaml"),
|
||||
})
|
||||
|
||||
federated_url = "https://localhost:10200"
|
||||
federated_env = None
|
||||
if federated_needed:
|
||||
# run-github.py's (Behat apiOcm) federation setup already solved this exact
|
||||
# problem, so reuse its canonical port-mapping file instead of re-deriving one:
|
||||
# only offsetting *_DEBUG_ADDR left the actual service ports (e.g. gateway's
|
||||
# GATEWAY_GRPC_ADDR 127.0.0.1:9142) on their defaults, so the federated
|
||||
# "ocis server" process crashed trying to bind the same ports the primary
|
||||
# instance already held.
|
||||
providers_file = str(repo_root / "tests/config/local/providers.json")
|
||||
server_env.update({
|
||||
"OCIS_ADD_RUN_SERVICES": "ocm",
|
||||
"OCIS_ENABLE_OCM": "true",
|
||||
"OCM_OCM_INVITE_MANAGER_INSECURE": "true",
|
||||
"OCM_OCM_SHARE_PROVIDER_INSECURE": "true",
|
||||
"OCM_OCM_STORAGE_PROVIDER_INSECURE": "true",
|
||||
"OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE": providers_file,
|
||||
})
|
||||
|
||||
federated_config_dir = Path.home() / ".ocis-federated/config"
|
||||
federated_data_dir = Path.home() / ".ocis-federated"
|
||||
federated_env = {**server_env}
|
||||
federated_env.update(load_env_file(repo_root / "tests/config/local/.env-federation"))
|
||||
# override the file's ${HOME}-prefixed paths (load_env_file doesn't expand
|
||||
# shell variables) and anything specific to this script's own layout
|
||||
federated_env.update({
|
||||
"OCIS_URL": federated_url,
|
||||
"OCIS_BASE_DATA_PATH": str(federated_data_dir),
|
||||
"OCIS_CONFIG_DIR": str(federated_config_dir),
|
||||
"OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE": providers_file,
|
||||
"MICRO_REGISTRY_ADDRESS": "127.0.0.1:10233",
|
||||
})
|
||||
|
||||
procs = []
|
||||
|
||||
print("Starting ocis...")
|
||||
@@ -341,6 +434,72 @@ def main() -> int:
|
||||
wait_for(lambda: search_ready(ocis_url), 60, "search service")
|
||||
print("search ready.")
|
||||
|
||||
if collaboration_needed:
|
||||
# WOPI bridges: one per office app, started only after ocis itself is up
|
||||
# so they can register with its gateway. Ported from setup_wopi_collabora
|
||||
# / setup_wopi_onlyoffice in tests/actions/setup-services.sh.
|
||||
wopi_common = {
|
||||
"MICRO_REGISTRY": "nats-js-kv",
|
||||
"MICRO_REGISTRY_ADDRESS": "127.0.0.1:9233",
|
||||
"COLLABORATION_APP_INSECURE": "true",
|
||||
"COLLABORATION_CS3API_DATAGATEWAY_INSECURE": "true",
|
||||
"OCIS_JWT_SECRET": "some-ocis-jwt-secret",
|
||||
"COLLABORATION_WOPI_SECRET": "some-wopi-secret",
|
||||
}
|
||||
collabora_env = {
|
||||
**os.environ, **wopi_common,
|
||||
"COLLABORATION_GRPC_ADDR": "0.0.0.0:9301",
|
||||
"COLLABORATION_HTTP_ADDR": "0.0.0.0:9300",
|
||||
"COLLABORATION_DEBUG_ADDR": "0.0.0.0:9304",
|
||||
"COLLABORATION_APP_NAME": "Collabora",
|
||||
"COLLABORATION_APP_ADDR": "https://127.0.0.1:9980",
|
||||
"COLLABORATION_APP_ICON": "https://127.0.0.1:9980/favicon.ico",
|
||||
"COLLABORATION_WOPI_SRC": "http://127.0.0.1:9300",
|
||||
}
|
||||
onlyoffice_env = {
|
||||
**os.environ, **wopi_common,
|
||||
"COLLABORATION_GRPC_ADDR": "0.0.0.0:9303",
|
||||
"COLLABORATION_HTTP_ADDR": "0.0.0.0:9302",
|
||||
"COLLABORATION_DEBUG_ADDR": "0.0.0.0:9305",
|
||||
"COLLABORATION_APP_NAME": "OnlyOffice",
|
||||
"COLLABORATION_APP_PRODUCT": "OnlyOffice",
|
||||
"COLLABORATION_APP_ADDR": "https://127.0.0.1:443",
|
||||
"COLLABORATION_APP_ICON": "https://127.0.0.1/web-apps/apps/documenteditor/main/resources/img/favicon.ico",
|
||||
"COLLABORATION_WOPI_SRC": "http://127.0.0.1:9302",
|
||||
}
|
||||
procs.append(subprocess.Popen([str(ocis_bin), "collaboration", "server"], env=collabora_env))
|
||||
procs.append(subprocess.Popen([str(ocis_bin), "collaboration", "server"], env=onlyoffice_env))
|
||||
wait_for(lambda: app_providers_ready(ocis_url), 150, "Collabora/OnlyOffice app providers")
|
||||
print("app providers ready.")
|
||||
|
||||
if federated_needed:
|
||||
# Second, independent ocis instance for OCM federation tests. See the
|
||||
# federated_env comment above main() for its port-mapping source.
|
||||
# OCIS_BASE_DATA_PATH must match federated_env's, or init writes the
|
||||
# proxy cert under the default ~/.ocis (colliding with the primary
|
||||
# instance's) instead of federated_data_dir, and the server then
|
||||
# generates its own untrusted one lazily at startup.
|
||||
run([str(ocis_bin), "init", "--insecure", "true"],
|
||||
env={
|
||||
"OCIS_CONFIG_DIR": str(federated_config_dir),
|
||||
"OCIS_BASE_DATA_PATH": str(federated_data_dir),
|
||||
})
|
||||
federated_cert = federated_data_dir / "proxy/server.crt"
|
||||
if federated_cert.exists():
|
||||
subprocess.run(
|
||||
["sudo", "cp", str(federated_cert),
|
||||
"/usr/local/share/ca-certificates/ocis-federated.crt"],
|
||||
check=True,
|
||||
)
|
||||
subprocess.run(["sudo", "update-ca-certificates"], check=True)
|
||||
federated_proc = subprocess.Popen(
|
||||
[str(ocis_bin), "server"],
|
||||
env=federated_env,
|
||||
)
|
||||
procs.append(federated_proc)
|
||||
wait_for(lambda: ocis_healthy(federated_url, use_basic_auth=True), 300, "ocis-federated")
|
||||
print("ocis-federated ready.")
|
||||
|
||||
playwright_env = {
|
||||
**os.environ,
|
||||
"BASE_URL_OCIS": ocis_url,
|
||||
@@ -354,15 +513,35 @@ def main() -> int:
|
||||
"BROWSER": "chromium",
|
||||
}
|
||||
|
||||
trusted_certs = [ocis_cert]
|
||||
|
||||
if keycloak_needed:
|
||||
playwright_env.update({
|
||||
"KEYCLOAK": "true",
|
||||
"KEYCLOAK_HOST": "localhost:8443",
|
||||
})
|
||||
keycloak_cert = repo_root / "keycloak-certs/keycloakcrt.pem"
|
||||
if keycloak_cert.exists():
|
||||
trusted_certs.append(keycloak_cert)
|
||||
|
||||
if mfa_needed:
|
||||
playwright_env["MFA"] = "true"
|
||||
|
||||
if federated_needed:
|
||||
playwright_env["FEDERATED_BASE_URL_OCIS"] = "localhost:10200"
|
||||
trusted_certs.append(federated_cert)
|
||||
|
||||
if len(trusted_certs) > 1:
|
||||
# NODE_EXTRA_CA_CERTS takes a single file; concatenate every self-signed
|
||||
# cert in play (oCIS, Keycloak, federated instance) so node-fetch/axios
|
||||
# calls made directly against any of them are trusted too.
|
||||
bundle = tempfile.NamedTemporaryFile(
|
||||
mode="w", suffix=".pem", prefix="ocis-ca-bundle-", delete=False)
|
||||
for cert in trusted_certs:
|
||||
bundle.write(cert.read_text())
|
||||
bundle.close()
|
||||
playwright_env["NODE_EXTRA_CA_CERTS"] = bundle.name
|
||||
|
||||
print(f"Running e2e: {e2e_args}")
|
||||
result = subprocess.run(
|
||||
["bash", "run-e2e.sh"] + shlex.split(e2e_args),
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Checks S3 MinIO cache for web test runner artifacts (acceptance/e2e/web).
|
||||
# Sources ci.env to get WEB_COMMITID used as the cache key.
|
||||
source ci.env
|
||||
|
||||
# if no $1 is supplied end the script
|
||||
# Can be web, acceptance or e2e
|
||||
if [ -z "$1" ]; then
|
||||
echo "No cache item is supplied."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking web version - $WEB_COMMITID in cache"
|
||||
web_cache=$(mc find s3/$CACHE_BUCKET/ocis/web-test-runner/$WEB_COMMITID/$1 2>&1 | grep 'Object does not exist')
|
||||
|
||||
if [[ -z "$web_cache" ]]; then
|
||||
echo "$1 cache with commit id $WEB_COMMITID already available."
|
||||
exit 78
|
||||
else
|
||||
echo "$1 cache with commit id $WEB_COMMITID was not available."
|
||||
fi
|
||||
@@ -18,11 +18,17 @@ directives:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
- 'https://embed.diagrams.net/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice:443}/'
|
||||
- 'https://${COLLABORA_DOMAIN|collabora:9980}/'
|
||||
img-src:
|
||||
- '''self'''
|
||||
- 'data:'
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|onlyoffice:443}/'
|
||||
- 'https://${COLLABORA_DOMAIN|collabora:9980}/'
|
||||
manifest-src:
|
||||
- '''self'''
|
||||
media-src:
|
||||
|
||||
24
tests/config/local/app-registry-office-suites.yaml
Normal file
24
tests/config/local/app-registry-office-suites.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
app_registry:
|
||||
mimetypes:
|
||||
# Mirrors web/dev/docker/ocis/app-registry.yaml, the registry web's own e2e
|
||||
# CI ran the app-provider suite against. The web UI's "New file" menu shows
|
||||
# an entry for every /app/list mimetype that has allow_creation plus a
|
||||
# registered provider, so the plain document mimetypes are the right ones
|
||||
# here -- Collabora/OnlyOffice register them dynamically via WOPI discovery.
|
||||
# "Create from template" needs no static entry either: reva stamps
|
||||
# target_ext onto the -template mimetypes the providers register themselves
|
||||
# (vendor/.../appprovider/templates.go).
|
||||
- mime_type: application/vnd.oasis.opendocument.text
|
||||
extension: odt
|
||||
name: OpenDocument
|
||||
description: OpenDocument text document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
extension: docx
|
||||
name: Microsoft Word
|
||||
description: Microsoft Word document
|
||||
icon: ""
|
||||
default_app: OnlyOffice
|
||||
allow_creation: true
|
||||
4
web/.clean-publish
Normal file
4
web/.clean-publish
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"withoutPublish": true,
|
||||
"tempDir": "package"
|
||||
}
|
||||
6
web/.depcheckrc
Normal file
6
web/.depcheckrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ignores": [
|
||||
"requirejs",
|
||||
"@babel/register"
|
||||
]
|
||||
}
|
||||
2
web/.dockerignore
Normal file
2
web/.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
apps/*/node_modules
|
||||
14
web/.editorconfig
Normal file
14
web/.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
|
||||
[*.{js,json,vue,feature,ts}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{md,markdown}]
|
||||
trim_trailing_whitespace = false
|
||||
66
web/.gitignore
vendored
Normal file
66
web/.gitignore
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
release/*
|
||||
|
||||
**/l10n/locale
|
||||
**/l10n/template.pot
|
||||
**/hugo
|
||||
|
||||
build/version.json
|
||||
|
||||
.env
|
||||
.idea
|
||||
.vscode
|
||||
*.bundle.js
|
||||
*.bundle.js.map
|
||||
*.chunk.js
|
||||
*.chunk.js.map
|
||||
|
||||
config.json
|
||||
package-lock.json
|
||||
|
||||
node_modules
|
||||
dist
|
||||
|
||||
*.log
|
||||
.DS_Store
|
||||
.envrc
|
||||
|
||||
reports
|
||||
tests/e2e/cucumber/report/cucumber_report.json
|
||||
tests/e2e/cucumber/reportGenerator/cucumber_report.json
|
||||
tests/ocis
|
||||
tests/testing-app
|
||||
playwright-report
|
||||
|
||||
/webpack.json
|
||||
/webpack-build-log.json
|
||||
|
||||
/.vite-inspect
|
||||
|
||||
/coverage
|
||||
**/coverage/
|
||||
|
||||
/.pnpm-store/
|
||||
|
||||
# drone CI is in .drone.star, do not let someone accidentally commit a local .drone.yml
|
||||
.drone.yml
|
||||
|
||||
# Themes
|
||||
/packages/web-runtime/themes/*
|
||||
!/packages/web-runtime/themes/owncloud/
|
||||
|
||||
# Compiled tokens
|
||||
/packages/design-system/src/assets/tokens/
|
||||
|
||||
# Report for tests
|
||||
tests/e2e/cucumber/report/*
|
||||
!tests/e2e/cucumber/report/index.mjs
|
||||
.vscode/settings.json
|
||||
|
||||
# third party licenses
|
||||
/third-party-licenses
|
||||
|
||||
# dev setup
|
||||
/dev/docker/ocis-ca
|
||||
/dev/docker/traefik/certificates
|
||||
docker-compose.override.yml
|
||||
/dev/docker/apps
|
||||
17
web/.npmrc
Normal file
17
web/.npmrc
Normal file
@@ -0,0 +1,17 @@
|
||||
auto-install-peers=true
|
||||
shared-workspace-lockfile=true
|
||||
|
||||
# @vue/component-compiler-utils
|
||||
hoist-pattern[]=sass
|
||||
hoist-pattern[]=*@codemirror*
|
||||
hoist-pattern[]=*@lezer*
|
||||
|
||||
# eslint (public so they are picked up by IDEs)
|
||||
public-hoist-pattern[]=*eslint*
|
||||
|
||||
# Make ODS available to tests, even if the main package does not require it
|
||||
public-hoist-pattern[]=@ownclouders/design-system
|
||||
|
||||
# c.f. https://github.com/vuejs/test-utils/pull/2197
|
||||
hoist-pattern[]=@vue/server-renderer
|
||||
|
||||
1
web/.prettierignore
Normal file
1
web/.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
**/src/graph/generated
|
||||
1
web/.prettierrc.json
Normal file
1
web/.prettierrc.json
Normal file
@@ -0,0 +1 @@
|
||||
"@ownclouders/prettier-config"
|
||||
136
web/Makefile
Normal file
136
web/Makefile
Normal file
@@ -0,0 +1,136 @@
|
||||
SHELL := bash
|
||||
DIST := ${CURDIR}/dist
|
||||
HUGO := docs/hugo
|
||||
RELEASE := ${CURDIR}/release
|
||||
NODE_MODULES := ${CURDIR}/node_modules
|
||||
|
||||
# define standard colors
|
||||
BLACK := $(shell tput -Txterm setaf 0)
|
||||
RED := $(shell tput -Txterm setaf 1)
|
||||
GREEN := $(shell tput -Txterm setaf 2)
|
||||
YELLOW := $(shell tput -Txterm setaf 3)
|
||||
LIGHTPURPLE := $(shell tput -Txterm setaf 4)
|
||||
PURPLE := $(shell tput -Txterm setaf 5)
|
||||
BLUE := $(shell tput -Txterm setaf 6)
|
||||
WHITE := $(shell tput -Txterm setaf 7)
|
||||
|
||||
RESET := $(shell tput -Txterm sgr0)
|
||||
|
||||
node_modules: package.json pnpm-lock.yaml
|
||||
[ -n "${NO_INSTALL}" ] || pnpm install
|
||||
touch ${NODE_MODULES}
|
||||
|
||||
.PHONY: help
|
||||
DEFAULT_GOAL := help
|
||||
help:
|
||||
@echo "Please use 'make <target>' where <target> is one of the following:"
|
||||
@echo
|
||||
@echo -e "${GREEN}List all available .PHONY targets:${RESET}\n"
|
||||
@echo -e "\tmake list\t\t${BLUE}sorted alphabetically${RESET}"
|
||||
@echo -e "${BLACK}---------------------------------------------------------${RESET}"
|
||||
@echo -e "${GREEN}Install/update required packages:${RESET}\n"
|
||||
@echo -e "\tmake\t\t\t${BLUE}run make without target${RESET}"
|
||||
@echo -e "${BLACK}---------------------------------------------------------${RESET}"
|
||||
@echo
|
||||
@echo -e "${GREEN}Documentation:${RESET}\n"
|
||||
@echo -e "${PURPLE}\tdocs: https://owncloud.dev/ocis/build-docs/${RESET}\n"
|
||||
@echo -e "\trun ${YELLOW}make list | grep docs-\t\t${BLUE}note: run all docs command via this makefile${RESET}"
|
||||
@echo
|
||||
|
||||
.PHONY: list
|
||||
list:
|
||||
@echo -e 'Available .PHONY targets: \n'
|
||||
@grep -P -o '(?<=^\.PHONY: )(.*)' Makefile | sort -u
|
||||
@echo -e ''
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf ${DIST} ${HUGO} ${RELEASE} ${NODE_MODULES}
|
||||
|
||||
.PHONY: release
|
||||
release: clean
|
||||
make -f Makefile.release
|
||||
|
||||
#
|
||||
# Release
|
||||
# make this app compatible with the ownCloud
|
||||
# default build tools
|
||||
#
|
||||
.PHONY: dist
|
||||
dist:
|
||||
make -f Makefile.release
|
||||
|
||||
# note that everything docs related is located in the docs/ folder
|
||||
# we keep this original calls for the sake of history and ease of use
|
||||
# for drone only, prepare docs, do not run manually
|
||||
.PHONY: docs-generate # 1. prepare docs
|
||||
docs-generate:
|
||||
# initialize the docs build environment
|
||||
@$(MAKE) --no-print-directory -C docs docs-init
|
||||
|
||||
# remind one that web needs prerequisites installed
|
||||
@$(MAKE) --no-print-directory -C docs docs-first-time-message
|
||||
|
||||
# copy required resources into hugo/content
|
||||
.PHONY: docs-copy # 2. copy required doc resources
|
||||
docs-copy:
|
||||
@$(MAKE) --no-print-directory -C docs docs-copy
|
||||
|
||||
# the docs-build|serve commands requires that docs-init was run first for the required data to exists
|
||||
# create a docs build
|
||||
.PHONY: docs-build # 3. build prepared docs
|
||||
docs-build:
|
||||
@$(MAKE) --no-print-directory -C docs docs-build
|
||||
|
||||
# serve built docs with hugo
|
||||
.PHONY: docs-serve # serve the docs build
|
||||
docs-serve:
|
||||
@$(MAKE) --no-print-directory -C docs docs-serve
|
||||
|
||||
# clean up doc build artifacts
|
||||
.PHONY: docs-clean # clean all docs artifacts, must be run as sudo
|
||||
docs-clean:
|
||||
@$(MAKE) --no-print-directory -C docs docs-clean
|
||||
|
||||
# imitate a full drone run locally to build docs without pushing to the web.
|
||||
# this can help identify uncaught issues when running `make docs-serve` only.
|
||||
.PHONY: docs-local # run all steps as drone would do it (1, 2, 3)
|
||||
docs-local:
|
||||
@$(MAKE) --no-print-directory docs-generate
|
||||
@$(MAKE) --no-print-directory docs-copy
|
||||
@$(MAKE) --no-print-directory docs-build
|
||||
|
||||
# prepare a link from the root to the hugo folder because the image requires it
|
||||
# note that on local building, the referenced container of inside the hugo/makefile is used
|
||||
.PHONY: docs-hugo-drone-prep # only used for drone !
|
||||
docs-hugo-drone-prep:
|
||||
@$(MAKE) --no-print-directory -C docs docs-hugo-drone-prep
|
||||
|
||||
# translation relevant
|
||||
.PHONY: l10n-push
|
||||
l10n-push:
|
||||
@$(MAKE) --no-print-directory -C packages/web-runtime/l10n push
|
||||
|
||||
.PHONY: l10n-pull
|
||||
l10n-pull:
|
||||
@$(MAKE) --no-print-directory -C packages/web-runtime/l10n pull
|
||||
|
||||
.PHONY: l10n-clean
|
||||
l10n-clean:
|
||||
@$(MAKE) --no-print-directory -C packages/web-runtime/l10n clean
|
||||
|
||||
.PHONY: l10n-read
|
||||
l10n-read: node_modules
|
||||
@$(MAKE) --no-print-directory -C packages/web-runtime/l10n extract
|
||||
|
||||
.PHONY: l10n-write
|
||||
l10n-write: node_modules
|
||||
@$(MAKE) --no-print-directory -C packages/web-runtime/l10n translations
|
||||
|
||||
.PHONY: generate-qa-activity-report
|
||||
generate-qa-activity-report: node_modules
|
||||
@if [ -z "${MONTH}" ] || [ -z "${YEAR}" ]; then \
|
||||
echo "Please set the MONTH and YEAR environment variables. Usage: make generate-qa-activity-report MONTH=<month> YEAR=<year>"; \
|
||||
exit 1; \
|
||||
fi
|
||||
pnpm exec node generate-qa-activity-report.js --month ${MONTH} --year ${YEAR}
|
||||
71
web/Makefile.release
Normal file
71
web/Makefile.release
Normal file
@@ -0,0 +1,71 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
PNPM := $(shell command -v pnpm 2> /dev/null)
|
||||
ifndef PNPM
|
||||
$(error pnpm is not available on your system, please install npm)
|
||||
endif
|
||||
|
||||
app_name=web
|
||||
cur_dir=$(CURDIR)
|
||||
dist_dir=$(CURDIR)/dist
|
||||
third_party_licenses_dir=$(CURDIR)/third-party-licenses
|
||||
|
||||
occ=$(CURDIR)/../../occ
|
||||
private_key=$(HOME)/.owncloud/certificates/$(app_name).key
|
||||
certificate=$(HOME)/.owncloud/certificates/$(app_name).crt
|
||||
sign=$(occ) integrity:sign-app --privateKey="$(private_key)" --certificate="$(certificate)"
|
||||
sign_skip_msg="Skipping signing, either no key and certificate found in $(private_key) and $(certificate) or occ can not be found at $(occ)"
|
||||
ifneq (,$(wildcard $(private_key)))
|
||||
ifneq (,$(wildcard $(certificate)))
|
||||
ifneq (,$(wildcard $(occ)))
|
||||
CAN_SIGN=true
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
.DEFAULT_GOAL := build-release
|
||||
|
||||
.PHONY: build-release
|
||||
build-release: build package
|
||||
|
||||
.PHONY: build
|
||||
build: build-web copy-config
|
||||
|
||||
.PHONY: build-web
|
||||
build-web:
|
||||
[ -n "${NO_INSTALL}" ] || $(PNPM) install
|
||||
$(PNPM) check:types
|
||||
$(PNPM) build
|
||||
|
||||
.PHONY: copy-config
|
||||
copy-config:
|
||||
cp config/config.json.dist $(dist_dir)/
|
||||
|
||||
.PHONY: package
|
||||
package: create-release-folder create-packages
|
||||
|
||||
.PHONY: create-release-folder
|
||||
create-release-folder:
|
||||
rm -rf $(CURDIR)/release
|
||||
mkdir $(CURDIR)/release
|
||||
|
||||
.PHONY: create-packages
|
||||
create-packages: package-plain package-licenses
|
||||
|
||||
.PHONY: package-plain
|
||||
package-plain:
|
||||
cd $(dist_dir) && tar -czf $(CURDIR)/release/$(app_name).tar.gz -C $(dist_dir) *
|
||||
|
||||
.PHONY: package-licenses
|
||||
package-licenses:
|
||||
pnpm licenses:csv
|
||||
pnpm licenses:save
|
||||
cd $(third_party_licenses_dir) && tar -czf $(CURDIR)/release/third-party-licenses.tar.gz -C $(third_party_licenses_dir) *
|
||||
|
||||
.PHONY: sign
|
||||
sign:
|
||||
ifdef CAN_SIGN
|
||||
$(sign) --path="$(dist_dir)"
|
||||
else
|
||||
@echo $(sign_skip_msg)
|
||||
endif
|
||||
45
web/README.md
Normal file
45
web/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# ownCloud Web
|
||||
|
||||
ownCloud Web is the next-generation frontend for ownCloud Infinite Scale, built as a single-page application with Vue.js and TypeScript. It provides a modern, accessible and themeable user interface for managing files, sharing, real-time collaboration and administration -- designed to be extensible through a plugin-based architecture that allows third-party developers to build custom apps and extensions.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Set up a local development environment for ownCloud Web:
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org/) (LTS recommended)
|
||||
- [pnpm](https://pnpm.io/)
|
||||
- [Docker Compose](https://docs.docker.com/compose/) (for backend)
|
||||
|
||||
For the complete development setup, see the [setup guide](https://owncloud.dev/clients/web/getting-started/).
|
||||
|
||||
### Structure
|
||||
|
||||
The `web/packages` directory contains the core modules:
|
||||
|
||||
- **client** -- Generated TypeScript client for the oCIS Graph API
|
||||
- **container** -- Static assets and base files
|
||||
- **extension-sdk** -- Utilities for developing custom extensions
|
||||
- **pkg** -- Shared logic used across the codebase
|
||||
- **runtime** -- Authentication, routing, theming and application handling
|
||||
|
||||
Built-in apps (also in `web/packages`):
|
||||
|
||||
- **files** -- Core file sync-and-share functionality
|
||||
- **admin-settings** -- User, group and space administration
|
||||
- **activities** -- Activity stream
|
||||
- **app-store** -- Browse and install extensions
|
||||
- **epub-reader** -- Ebook file viewer
|
||||
- **external** -- WOPI-based document editing (Collabora, ONLYOFFICE)
|
||||
- **pdf-viewer** -- PDF file viewer
|
||||
- **preview** -- Audio, video and image previewer
|
||||
- **text-editor** -- Plain text editor
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ownCloud Web Documentation](https://owncloud.dev/clients/web)
|
||||
- [Development Guide](https://owncloud.dev/clients/web/getting-started/)
|
||||
- [Extension System](https://owncloud.dev/clients/web/extension-system/)
|
||||
- [Testing Documentation](https://owncloud.dev/clients/web/testing/testing/)
|
||||
- [Repository Structure](https://owncloud.dev/clients/web/development/repo-structure/)
|
||||
3
web/babel.config.cjs
Normal file
3
web/babel.config.cjs
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['@ownclouders/babel-preset']
|
||||
}
|
||||
19
web/config/config.json.dist
Normal file
19
web/config/config.json.dist
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"server" : "",
|
||||
"theme": "https://localhost:9200/themes/owncloud/theme.json",
|
||||
"auth": {
|
||||
"clientId": "",
|
||||
"url": "",
|
||||
"authUrl": ""
|
||||
},
|
||||
"apps" : [
|
||||
"files",
|
||||
"pdf-viewer",
|
||||
"preview",
|
||||
"search",
|
||||
"text-editor",
|
||||
"html-editor",
|
||||
"epub-reader"
|
||||
],
|
||||
"applications" : []
|
||||
}
|
||||
25
web/config/config.json.sample-ocis
Normal file
25
web/config/config.json.sample-ocis
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"server": "https://localhost:9200",
|
||||
"theme": "https://localhost:9200/themes/owncloud/theme.json",
|
||||
"openIdConnect": {
|
||||
"metadata_url": "https://localhost:9200/.well-known/openid-configuration",
|
||||
"authority": "https://localhost:9200",
|
||||
"client_id": "web",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email"
|
||||
},
|
||||
"apps": [
|
||||
"files",
|
||||
"preview",
|
||||
"pdf-viewer",
|
||||
"search",
|
||||
"text-editor",
|
||||
"html-editor",
|
||||
"external",
|
||||
"admin-settings",
|
||||
"epub-reader"
|
||||
],
|
||||
"options": {
|
||||
"contextHelpersReadMore": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
- name: continuous-deployment-ocis-web-master
|
||||
server:
|
||||
server_type: cpx21
|
||||
image: ubuntu-22.04
|
||||
location: nbg1
|
||||
initial_ssh_key_names:
|
||||
- owncloud-web@drone.owncloud.com
|
||||
labels:
|
||||
owner: web-team
|
||||
for: oCIS-continuous-deployment-examples
|
||||
rebuild: $REBUILD
|
||||
rebuild_carry_paths:
|
||||
- /var/lib/docker/volumes/web_certs
|
||||
|
||||
domains:
|
||||
- "*.ocis-web.master.owncloud.works"
|
||||
|
||||
vars:
|
||||
ssh_authorized_keys:
|
||||
- https://github.com/butonic.keys
|
||||
- https://github.com/fschade.keys
|
||||
- https://github.com/kulmann.keys
|
||||
- https://github.com/micbar.keys
|
||||
- https://github.com/wkloucek.keys
|
||||
docker_compose_projects:
|
||||
# web now lives in-tree in the ocis repo (previously a separate
|
||||
# owncloud/web checkout); ops team should confirm this deployment
|
||||
# example is still needed/relevant now that web ships as part of ocis.
|
||||
- name: web
|
||||
git_url: https://github.com/owncloud/ocis.git
|
||||
ref: master
|
||||
docker_compose_path: web/deployments/examples/ocis_web
|
||||
env:
|
||||
INSECURE: "false"
|
||||
TRAEFIK_ACME_MAIL: bkulmann@owncloud.com
|
||||
OCIS_DOCKER_TAG: latest
|
||||
WEB_DOCKER_TAG: latest
|
||||
OCIS_DOMAIN: ocis.ocis-web.master.owncloud.works
|
||||
WOPISERVER_DOMAIN: wopiserver.ocis-web.master.owncloud.works
|
||||
COLLABORA_DOMAIN: collabora.ocis-web.master.owncloud.works
|
||||
INBUCKET_DOMAIN: mail.ocis-web.master.owncloud.works
|
||||
DEMO_USERS: true
|
||||
SHARE_DENIALS: true
|
||||
COMPOSE_FILE: docker-compose.yml:monitoring_tracing/docker-compose-additions.yml
|
||||
- name: monitoring
|
||||
git_url: https://github.com/owncloud-devops/monitoring-tracing-client.git
|
||||
ref: master
|
||||
env:
|
||||
NETWORK_NAME: ocis-net
|
||||
TELEMETRY_SERVE_DOMAIN: telemetry.ocis-web.master.owncloud.works
|
||||
JAEGER_COLLECTOR: jaeger-collector.infra.owncloud.works:443
|
||||
TELEGRAF_SPECIFIC_CONFIG: ocis_single_container
|
||||
OCIS_URL: ocis.ocis-web.master.owncloud.works
|
||||
OCIS_DEPLOYMENT_ID: continuous-deployment-ocis-web-master
|
||||
5
web/deployments/examples/ocis_web/README.md
Normal file
5
web/deployments/examples/ocis_web/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
---
|
||||
|
||||
Please refer to [our documentation](https://owncloud.dev/ocis/deployment/)
|
||||
for deployment instructions.
|
||||
@@ -0,0 +1,58 @@
|
||||
app_registry:
|
||||
mimetypes:
|
||||
- mime_type: application/pdf
|
||||
extension: pdf
|
||||
name: PDF
|
||||
description: PDF document
|
||||
icon: ""
|
||||
default_app: ""
|
||||
allow_creation: false
|
||||
- mime_type: application/vnd.oasis.opendocument.text
|
||||
extension: odt
|
||||
name: OpenDocument
|
||||
description: OpenDocument text document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.oasis.opendocument.spreadsheet
|
||||
extension: ods
|
||||
name: OpenSpreadsheet
|
||||
description: OpenDocument spreadsheet document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.oasis.opendocument.presentation
|
||||
extension: odp
|
||||
name: OpenPresentation
|
||||
description: OpenDocument presentation document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
extension: docx
|
||||
name: Microsoft Word
|
||||
description: Microsoft Word document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
extension: xlsx
|
||||
name: Microsoft Excel
|
||||
description: Microsoft Excel document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
extension: pptx
|
||||
name: Microsoft PowerPoint
|
||||
description: Microsoft PowerPoint document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.jupyter
|
||||
extension: ipynb
|
||||
name: Jupyter Notebook
|
||||
description: Jupyter Notebook
|
||||
icon: ""
|
||||
default_app: ""
|
||||
allow_creation: true
|
||||
@@ -0,0 +1,9 @@
|
||||
Password@123
|
||||
Welcome@1
|
||||
Admin@123!
|
||||
Summer2023!
|
||||
Hello123!
|
||||
Password1!
|
||||
Qwerty@123
|
||||
Abc12345!
|
||||
MyPass@123
|
||||
39
web/deployments/examples/ocis_web/config/ocis/csp.yaml
Normal file
39
web/deployments/examples/ocis_web/config/ocis/csp.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
directives:
|
||||
child-src:
|
||||
- '''self'''
|
||||
connect-src:
|
||||
- '''self'''
|
||||
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
|
||||
- 'https://${COMPANION_DOMAIN|companion.owncloud.test}/'
|
||||
- 'wss://${COMPANION_DOMAIN|companion.owncloud.test}/'
|
||||
default-src:
|
||||
- '''none'''
|
||||
font-src:
|
||||
- '''self'''
|
||||
frame-ancestors:
|
||||
- '''self'''
|
||||
frame-src:
|
||||
- '''self'''
|
||||
- 'https://embed.diagrams.net/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${COLLABORA_DOMAIN|collabora.owncloud.test}/'
|
||||
img-src:
|
||||
- '''self'''
|
||||
- 'data:'
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
|
||||
# In contrary to bash and docker the default is given after the | character
|
||||
- 'https://${COLLABORA_DOMAIN|collabora.owncloud.test}/'
|
||||
manifest-src:
|
||||
- '''self'''
|
||||
media-src:
|
||||
- '''self'''
|
||||
object-src:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
script-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
style-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
106
web/deployments/examples/ocis_web/config/ocis/proxy.yaml
Normal file
106
web/deployments/examples/ocis_web/config/ocis/proxy.yaml
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
policy_selector:
|
||||
static:
|
||||
policy: ocis
|
||||
policies:
|
||||
- name: ocis
|
||||
routes:
|
||||
# serve oC Web assets from the Web container
|
||||
- endpoint: /
|
||||
backend: http://web:8080
|
||||
unprotected: true
|
||||
# serve oC Web config from oCIS
|
||||
- endpoint: /config.json
|
||||
backend: http://localhost:9100
|
||||
unprotected: true
|
||||
|
||||
# begin of regular oCIS proxy configuration
|
||||
# we don't need the root rule for oC Web, since we replaced it
|
||||
# with the both rules above
|
||||
# - endpoint: /
|
||||
# service: com.owncloud.web.web
|
||||
# unprotected: true
|
||||
- endpoint: /.well-known/webfinger
|
||||
service: com.owncloud.web.webfinger
|
||||
unprotected: true
|
||||
- endpoint: /.well-known/openid-configuration
|
||||
service: com.owncloud.web.idp
|
||||
unprotected: true
|
||||
- endpoint: /branding/logo
|
||||
service: com.owncloud.web.web
|
||||
- endpoint: /konnect/
|
||||
service: com.owncloud.web.idp
|
||||
unprotected: true
|
||||
- endpoint: /signin/
|
||||
service: com.owncloud.web.idp
|
||||
unprotected: true
|
||||
- endpoint: /archiver
|
||||
service: com.owncloud.web.frontend
|
||||
- endpoint: /ocs/v2.php/apps/notifications/api/v1/notifications/sse
|
||||
service: com.owncloud.sse.sse
|
||||
- endpoint: /ocs/v2.php/apps/notifications/api/v1/notifications
|
||||
service: com.owncloud.web.userlog
|
||||
- type: regex
|
||||
endpoint: /ocs/v[12].php/cloud/user/signing-key
|
||||
service: com.owncloud.web.ocs
|
||||
- type: regex
|
||||
endpoint: /ocs/v[12].php/config
|
||||
service: com.owncloud.web.frontend
|
||||
unprotected: true
|
||||
- endpoint: /sciencemesh/
|
||||
service: com.owncloud.web.ocm
|
||||
- endpoint: /ocm/
|
||||
service: com.owncloud.web.ocm
|
||||
- endpoint: /ocs/
|
||||
service: com.owncloud.web.frontend
|
||||
- type: query
|
||||
endpoint: /remote.php/?preview=1
|
||||
service: com.owncloud.web.webdav
|
||||
- type: regex
|
||||
method: REPORT
|
||||
endpoint: /remote.php/dav/
|
||||
service: com.owncloud.web.webdav
|
||||
- method: REPORT
|
||||
endpoint: (/remote.php)?/(web)?dav
|
||||
service: com.owncloud.web.webdav
|
||||
- method: REPORT
|
||||
endpoint: /dav/spaces
|
||||
service: com.owncloud.web.webdav
|
||||
- type: query
|
||||
endpoint: /dav/?preview=1
|
||||
service: com.owncloud.web.webdav
|
||||
- type: query
|
||||
endpoint: /webdav/?preview=1
|
||||
service: com.owncloud.web.webdav
|
||||
- endpoint: /remote.php/
|
||||
service: com.owncloud.web.ocdav
|
||||
- endpoint: /dav/
|
||||
service: com.owncloud.web.ocdav
|
||||
- endpoint: /webdav/
|
||||
service: com.owncloud.web.ocdav
|
||||
- endpoint: /status
|
||||
service: com.owncloud.web.ocdav
|
||||
unprotected: true
|
||||
- endpoint: /status.php
|
||||
service: com.owncloud.web.ocdav
|
||||
unprotected: true
|
||||
- endpoint: /index.php/
|
||||
service: com.owncloud.web.ocdav
|
||||
- endpoint: /apps/
|
||||
service: com.owncloud.web.ocdav
|
||||
- endpoint: /data
|
||||
service: com.owncloud.web.frontend
|
||||
unprotected: true
|
||||
- endpoint: /app/list
|
||||
service: com.owncloud.web.frontend
|
||||
unprotected: true
|
||||
- endpoint: /app/
|
||||
service: com.owncloud.web.frontend
|
||||
- endpoint: /graph/v1beta1/extensions/org.libregraph/activities
|
||||
service: com.owncloud.web.activitylog
|
||||
- endpoint: /graph/v1.0/invitations
|
||||
service: com.owncloud.web.invitations
|
||||
- endpoint: /graph/
|
||||
service: com.owncloud.web.graph
|
||||
- endpoint: /api/v0/settings
|
||||
service: com.owncloud.web.settings
|
||||
219
web/deployments/examples/ocis_web/docker-compose.yml
Normal file
219
web/deployments/examples/ocis_web/docker-compose.yml
Normal file
@@ -0,0 +1,219 @@
|
||||
---
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.0.3
|
||||
networks:
|
||||
ocis-net:
|
||||
aliases:
|
||||
- ${OCIS_DOMAIN:-ocis.owncloud.test}
|
||||
- ${WOPISERVER_DOMAIN:-wopiserver.owncloud.test}
|
||||
- ${COLLABORA_DOMAIN:-collabora.owncloud.test}
|
||||
command:
|
||||
- '--log.level=${TRAEFIK_LOG_LEVEL:-ERROR}'
|
||||
# letsencrypt configuration
|
||||
- '--certificatesResolvers.http.acme.email=${TRAEFIK_ACME_MAIL:-example@example.org}'
|
||||
- '--certificatesResolvers.http.acme.storage=/certs/acme.json'
|
||||
- '--certificatesResolvers.http.acme.httpChallenge.entryPoint=http'
|
||||
- "--certificatesresolvers.http.acme.caserver=${TRAEFIK_ACME_CASERVER:-https://acme-v02.api.letsencrypt.org/directory}"
|
||||
# enable dashboard
|
||||
- '--api.dashboard=true'
|
||||
# define entrypoints
|
||||
- '--entryPoints.http.address=:80'
|
||||
- '--entryPoints.http.http.redirections.entryPoint.to=https'
|
||||
- '--entryPoints.http.http.redirections.entryPoint.scheme=https'
|
||||
- '--entryPoints.https.address=:443'
|
||||
# docker provider (get configuration from container labels)
|
||||
- '--providers.docker.endpoint=unix:///var/run/docker.sock'
|
||||
- '--providers.docker.exposedByDefault=false'
|
||||
ports:
|
||||
- '80:80'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- '/var/run/docker.sock:/var/run/docker.sock:ro'
|
||||
- 'certs:/certs'
|
||||
labels:
|
||||
- 'traefik.enable=${TRAEFIK_DASHBOARD:-false}'
|
||||
- 'traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_BASIC_AUTH_USERS:-admin:$$apr1$$4vqie50r$$YQAmQdtmz5n9rEALhxJ4l.}' # defaults to admin:admin
|
||||
- 'traefik.http.routers.traefik.entrypoints=https'
|
||||
- 'traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DOMAIN:-traefik.owncloud.test}`)'
|
||||
- 'traefik.http.routers.traefik.middlewares=traefik-auth'
|
||||
- 'traefik.http.routers.traefik.tls.certresolver=http'
|
||||
- 'traefik.http.routers.traefik.service=api@internal'
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
ocis:
|
||||
image: ${OCIS_DOCKER_IMAGE:-owncloud/ocis-rolling}:${OCIS_DOCKER_TAG:-master}
|
||||
networks:
|
||||
ocis-net:
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
# run ocis init to initialize a configuration file with random secrets
|
||||
# it will fail on subsequent runs, because the config file already exists
|
||||
# therefore we ignore the error and then start the ocis server
|
||||
command: ['-c', 'ocis init || true; ocis server']
|
||||
environment:
|
||||
OCIS_URL: https://${OCIS_DOMAIN:-ocis.owncloud.test}
|
||||
OCIS_LOG_LEVEL: ${OCIS_LOG_LEVEL:-error} # make oCIS less verbose
|
||||
OCIS_LOG_COLOR: "${LOG_PRETTY:-false}"
|
||||
OCIS_LOG_PRETTY: "${LOG_PRETTY:-false}"
|
||||
PROXY_TLS: 'false' # do not use SSL between Traefik and oCIS
|
||||
GATEWAY_GRPC_ADDR: 0.0.0.0:9142 # make the REVA gateway accessible to the app drivers
|
||||
# INSECURE: needed if oCIS / Traefik is using self generated certificates
|
||||
OCIS_INSECURE: '${INSECURE:-false}'
|
||||
# basic auth (not recommended, but needed for eg. WebDAV clients that do not support OpenID Connect)
|
||||
PROXY_ENABLE_BASIC_AUTH: '${PROXY_ENABLE_BASIC_AUTH:-false}'
|
||||
# admin user password
|
||||
IDM_ADMIN_PASSWORD: '${ADMIN_PASSWORD:-admin}' # this overrides the admin password from the configuration file
|
||||
# demo users
|
||||
IDM_CREATE_DEMO_USERS: '${DEMO_USERS:-false}'
|
||||
# enable the notifications service
|
||||
OCIS_ADD_RUN_SERVICES: "notifications"
|
||||
NOTIFICATIONS_SMTP_HOST: inbucket
|
||||
NOTIFICATIONS_SMTP_PORT: 2500
|
||||
NOTIFICATIONS_SMTP_SENDER: oCIS notifications <notifications@${OCIS_DOMAIN:-ocis.owncloud.test}>
|
||||
NOTIFICATIONS_SMTP_USERNAME: notifications@${OCIS_DOMAIN:-ocis.owncloud.test}
|
||||
NOTIFICATIONS_SMTP_INSECURE: "true" # the mail catcher uses self signed certificates
|
||||
# fulltext search
|
||||
SEARCH_EXTRACTOR_TYPE: tika
|
||||
SEARCH_EXTRACTOR_TIKA_TIKA_URL: http://tika:9998
|
||||
# denial shares
|
||||
FRONTEND_OCS_ENABLE_DENIALS: '${SHARE_DENIALS:-false}'
|
||||
# make the registry available to the app provider containers
|
||||
NATS_NATS_HOST: 0.0.0.0
|
||||
# CSP configs
|
||||
PROXY_CSP_CONFIG_FILE_LOCATION: /etc/ocis/csp.yaml
|
||||
# these two vars are needed in the csp config file to include the web office apps and the importer
|
||||
COLLABORA_DOMAIN: ${COLLABORA_DOMAIN:-collabora.owncloud.test}
|
||||
COMPANION_DOMAIN: ${COMPANION_DOMAIN:-companion.owncloud.test}
|
||||
# enable to allow using the banned passwords list
|
||||
OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST: banned-password-list.txt
|
||||
# make collabora the secure view app
|
||||
FRONTEND_APP_HANDLER_SECURE_VIEW_APP_ADDR: com.owncloud.api.collaboration.Collabora
|
||||
volumes:
|
||||
- ./config/ocis/proxy.yaml:/etc/ocis/proxy.yaml
|
||||
- ./config/ocis/app-registry.yaml:/etc/ocis/app-registry.yaml
|
||||
- ./config/ocis/csp.yaml:/etc/ocis/csp.yaml
|
||||
- ./config/ocis/banned-password-list.txt:/etc/ocis/banned-password-list.txt
|
||||
- ocis-config:/etc/ocis
|
||||
- ocis-data:/var/lib/ocis
|
||||
labels:
|
||||
- 'traefik.enable=true'
|
||||
- 'traefik.http.routers.ocis.entrypoints=https'
|
||||
- 'traefik.http.routers.ocis.rule=Host(`${OCIS_DOMAIN:-ocis.owncloud.test}`)'
|
||||
- 'traefik.http.routers.ocis.tls.certresolver=http'
|
||||
- 'traefik.http.routers.ocis.service=ocis'
|
||||
- 'traefik.http.services.ocis.loadbalancer.server.port=9200'
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
web:
|
||||
image: owncloud/web:${WEB_DOCKER_TAG:-latest}
|
||||
networks:
|
||||
ocis-net:
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
collaboration:
|
||||
image: ${OCIS_DOCKER_IMAGE:-owncloud/ocis-rolling}:${OCIS_DOCKER_TAG:-master}
|
||||
networks:
|
||||
ocis-net:
|
||||
depends_on:
|
||||
ocis:
|
||||
condition: service_started
|
||||
collabora:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command: [ "-c", "ocis collaboration server" ]
|
||||
environment:
|
||||
COLLABORATION_GRPC_ADDR: 0.0.0.0:9301
|
||||
COLLABORATION_HTTP_ADDR: 0.0.0.0:9300
|
||||
COLLABORATION_WOPI_SRC: https://${WOPISERVER_DOMAIN:-wopiserver.owncloud.test}
|
||||
COLLABORATION_APP_NAME: "Collabora"
|
||||
COLLABORATION_APP_ADDR: https://${COLLABORA_DOMAIN:-collabora.owncloud.test}
|
||||
COLLABORATION_APP_ICON: https://${COLLABORA_DOMAIN:-collabora.owncloud.test}/favicon.ico
|
||||
COLLABORATION_APP_INSECURE: "${INSECURE:-true}"
|
||||
COLLABORATION_CS3API_DATAGATEWAY_INSECURE: "${INSECURE:-true}"
|
||||
COLLABORATION_LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
MICRO_REGISTRY_ADDRESS: "ocis:9233"
|
||||
OCIS_URL: https://${OCIS_DOMAIN:-ocis.owncloud.test}
|
||||
volumes:
|
||||
- ocis-config:/etc/ocis
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.collaboration.entrypoints=https"
|
||||
- "traefik.http.routers.collaboration.rule=Host(`${WOPISERVER_DOMAIN:-wopiserver.owncloud.test}`)"
|
||||
- "traefik.http.routers.collaboration.tls.certresolver=http"
|
||||
- "traefik.http.routers.collaboration.service=collaboration"
|
||||
- "traefik.http.services.collaboration.loadbalancer.server.port=9300"
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
collabora:
|
||||
image: collabora/code:24.04.5.1.1
|
||||
networks:
|
||||
ocis-net:
|
||||
environment:
|
||||
aliasgroup1: https://${WOPISERVER_DOMAIN:-wopiserver.owncloud.test}:443
|
||||
DONT_GEN_SSL_CERT: 'YES'
|
||||
extra_params: --o:ssl.enable=false --o:ssl.termination=true --o:welcome.enable=false --o:net.frame_ancestors=${OCIS_DOMAIN:-ocis.owncloud.test}
|
||||
username: ${COLLABORA_ADMIN_USER}
|
||||
password: ${COLLABORA_ADMIN_PASSWORD}
|
||||
cap_add:
|
||||
- MKNOD
|
||||
labels:
|
||||
- 'traefik.enable=true'
|
||||
- 'traefik.http.routers.collabora.entrypoints=https'
|
||||
- 'traefik.http.routers.collabora.rule=Host(`${COLLABORA_DOMAIN:-collabora.owncloud.test}`)'
|
||||
- 'traefik.http.routers.collabora.tls.certresolver=http'
|
||||
- 'traefik.http.routers.collabora.service=collabora'
|
||||
- 'traefik.http.services.collabora.loadbalancer.server.port=9980'
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-f", "http://localhost:9980/hosting/discovery" ]
|
||||
|
||||
|
||||
tika:
|
||||
image: ${TIKA_IMAGE:-apache/tika:latest-full}
|
||||
networks:
|
||||
ocis-net:
|
||||
restart: always
|
||||
|
||||
inbucket:
|
||||
image: inbucket/inbucket
|
||||
networks:
|
||||
- ocis-net
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command: [ "-c", "apk add openssl; openssl req -subj '/CN=inbucket.test' -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/server.key -out /tmp/server.crt; /start-inbucket.sh" ]
|
||||
environment:
|
||||
INBUCKET_SMTP_TLSENABLED: "true"
|
||||
INBUCKET_SMTP_TLSPRIVKEY: /tmp/server.key
|
||||
INBUCKET_SMTP_TLSCERT: /tmp/server.crt
|
||||
INBUCKET_STORAGE_MAILBOXMSGCAP: 1000
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.inbucket.entrypoints=https"
|
||||
- "traefik.http.routers.inbucket.rule=Host(`${INBUCKET_DOMAIN:-mail.owncloud.test}`)"
|
||||
- "traefik.http.routers.inbucket.tls.certresolver=http"
|
||||
- "traefik.http.routers.inbucket.service=inbucket"
|
||||
- "traefik.http.services.inbucket.loadbalancer.server.port=9000"
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
certs:
|
||||
ocis-config:
|
||||
ocis-data:
|
||||
|
||||
networks:
|
||||
ocis-net:
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
ocis:
|
||||
environment:
|
||||
# tracing
|
||||
OCIS_TRACING_ENABLED: "true"
|
||||
OCIS_TRACING_TYPE: "jaeger"
|
||||
OCIS_TRACING_ENDPOINT: jaeger-agent:6831
|
||||
# metrics
|
||||
PROXY_DEBUG_ADDR: 0.0.0.0:9205
|
||||
collaboration:
|
||||
environment:
|
||||
# tracing
|
||||
OCIS_TRACING_ENABLED: "true"
|
||||
OCIS_TRACING_TYPE: "jaeger"
|
||||
OCIS_TRACING_ENDPOINT: jaeger-agent:6831
|
||||
# metrics
|
||||
COLLABORATION_DEBUG_ADDR: 0.0.0.0:9304
|
||||
|
||||
networks:
|
||||
ocis-net:
|
||||
external: true
|
||||
20
web/dev/docker/ocis-appprovider-onlyoffice/entrypoint-override.sh
Executable file
20
web/dev/docker/ocis-appprovider-onlyoffice/entrypoint-override.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
apk add curl
|
||||
|
||||
#TODO: app driver itself should try again until OnlyOffice is up...
|
||||
|
||||
retries=10
|
||||
while [[ $retries -gt 0 ]]; do
|
||||
if curl --silent --show-error --fail http://onlyoffice/hosting/discovery > /dev/null; then
|
||||
echo "OnlyOffice is available !!"
|
||||
ocis app-provider server
|
||||
else
|
||||
echo "OnlyOffice is not yet available, trying again in 10 seconds"
|
||||
sleep 10
|
||||
retries=$((retries - 1))
|
||||
fi
|
||||
done
|
||||
echo 'OnlyOffice was not available after 100 seconds'
|
||||
exit 1
|
||||
33
web/dev/docker/ocis.idp.config.yaml
Normal file
33
web/dev/docker/ocis.idp.config.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
clients:
|
||||
- id: web
|
||||
name: ownCloud web app
|
||||
application_type: web
|
||||
insecure: true
|
||||
trusted: true
|
||||
redirect_uris:
|
||||
- https://host.docker.internal:9200/
|
||||
- https://host.docker.internal:9200/oidc-callback.html
|
||||
- https://host.docker.internal:9200/oidc-silent-redirect.html
|
||||
- https://host.docker.internal:9201/
|
||||
- https://host.docker.internal:9201/oidc-callback.html
|
||||
- https://host.docker.internal:9201/oidc-silent-redirect.html
|
||||
- https://host.docker.internal:10200/
|
||||
- https://host.docker.internal:10200/oidc-callback.html
|
||||
- https://host.docker.internal:10200/oidc-silent-redirect.html
|
||||
- https://host.docker.internal:10201/
|
||||
- https://host.docker.internal:10201/oidc-callback.html
|
||||
- https://host.docker.internal:10201/oidc-silent-redirect.html
|
||||
origins:
|
||||
- https://host.docker.internal:9200
|
||||
- https://host.docker.internal:9201
|
||||
- https://host.docker.internal:10200
|
||||
- https://host.docker.internal:10201
|
||||
|
||||
- id: xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69
|
||||
name: ownCloud desktop client
|
||||
application_type: native
|
||||
trusted: true
|
||||
secret: UBntmLjC2yYCeHwsyj73Uwo9TAaecAetRwMw0xYcvNL9yRdLSUi0hUAHfvCHFeFh
|
||||
redirect_uris:
|
||||
- http://localhost
|
||||
- http://127.0.0.1
|
||||
23
web/dev/docker/ocis.storage.ocmproviders.json
Normal file
23
web/dev/docker/ocis.storage.ocmproviders.json
Normal file
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"name": "ocis",
|
||||
"full_name": "ocis server",
|
||||
"organization": "ownCloud",
|
||||
"domain": "host.docker.internal:(9200|10200)",
|
||||
"homepage": "https://owncloud.com",
|
||||
"services": [
|
||||
{
|
||||
"endpoint": {
|
||||
"type": {
|
||||
"name": "OCM",
|
||||
"description": "ownCloud Open Cloud Mesh API"
|
||||
},
|
||||
"name": "ownCloud - OCM API",
|
||||
"path": "https://host.docker.internal:(9200|10200)/ocm/",
|
||||
"is_monitored": true
|
||||
},
|
||||
"host": "host.docker.internal:(9200|10200)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
26
web/dev/docker/ocis.web-federated.config.json
Normal file
26
web/dev/docker/ocis.web-federated.config.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"server": "https://host.docker.internal:10200",
|
||||
"theme": "https://host.docker.internal:10200/themes/owncloud/theme.json",
|
||||
"openIdConnect": {
|
||||
"metadata_url": "https://host.docker.internal:10200/.well-known/openid-configuration",
|
||||
"authority": "https://host.docker.internal:10200",
|
||||
"client_id": "web",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email"
|
||||
},
|
||||
"options": {
|
||||
"contextHelpersReadMore": true
|
||||
},
|
||||
"apps": [
|
||||
"files",
|
||||
"text-editor",
|
||||
"pdf-viewer",
|
||||
"search",
|
||||
"external",
|
||||
"admin-settings",
|
||||
"ocm",
|
||||
"webfinger",
|
||||
"epub-reader",
|
||||
"preview"
|
||||
]
|
||||
}
|
||||
29
web/dev/docker/ocis.web.config.json
Normal file
29
web/dev/docker/ocis.web.config.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"server": "https://host.docker.internal:9200",
|
||||
"theme": "https://host.docker.internal:9200/themes/owncloud/theme.json",
|
||||
"openIdConnect": {
|
||||
"metadata_url": "https://host.docker.internal:9200/.well-known/openid-configuration",
|
||||
"authority": "https://host.docker.internal:9200",
|
||||
"client_id": "web",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email acr"
|
||||
},
|
||||
"options": {
|
||||
"contextHelpersReadMore": true
|
||||
},
|
||||
"apps": [
|
||||
"files",
|
||||
"text-editor",
|
||||
"pdf-viewer",
|
||||
"search",
|
||||
"external",
|
||||
"admin-settings",
|
||||
"ocm",
|
||||
"webfinger",
|
||||
"epub-reader",
|
||||
"app-store",
|
||||
"activities",
|
||||
"preview",
|
||||
"password-protected-folders"
|
||||
]
|
||||
}
|
||||
58
web/dev/docker/ocis/app-registry.yaml
Normal file
58
web/dev/docker/ocis/app-registry.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
app_registry:
|
||||
mimetypes:
|
||||
- mime_type: application/pdf
|
||||
extension: pdf
|
||||
name: PDF
|
||||
description: PDF document
|
||||
icon: ""
|
||||
default_app: ""
|
||||
allow_creation: false
|
||||
- mime_type: application/vnd.oasis.opendocument.text
|
||||
extension: odt
|
||||
name: OpenDocument
|
||||
description: OpenDocument text document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.oasis.opendocument.spreadsheet
|
||||
extension: ods
|
||||
name: OpenSpreadsheet
|
||||
description: OpenDocument spreadsheet document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.oasis.opendocument.presentation
|
||||
extension: odp
|
||||
name: OpenPresentation
|
||||
description: OpenDocument presentation document
|
||||
icon: ""
|
||||
default_app: Collabora
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
extension: docx
|
||||
name: Microsoft Word
|
||||
description: Microsoft Word document
|
||||
icon: ""
|
||||
default_app: OnlyOffice
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
extension: xlsx
|
||||
name: Microsoft Excel
|
||||
description: Microsoft Excel document
|
||||
icon: ""
|
||||
default_app: OnlyOffice
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
extension: pptx
|
||||
name: Microsoft PowerPoint
|
||||
description: Microsoft PowerPoint document
|
||||
icon: ""
|
||||
default_app: OnlyOffice
|
||||
allow_creation: true
|
||||
- mime_type: application/vnd.jupyter
|
||||
extension: ipynb
|
||||
name: Jupyter Notebook
|
||||
description: Jupyter Notebook
|
||||
icon: ""
|
||||
default_app: ""
|
||||
allow_creation: true
|
||||
44
web/dev/docker/ocis/csp.yaml
Normal file
44
web/dev/docker/ocis/csp.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
directives:
|
||||
child-src:
|
||||
- '''self'''
|
||||
connect-src:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
|
||||
default-src:
|
||||
- '''none'''
|
||||
font-src:
|
||||
- '''self'''
|
||||
frame-ancestors:
|
||||
- '''self'''
|
||||
- 'https://host.docker.internal:9200'
|
||||
- 'https://host.docker.internal:9201'
|
||||
frame-src:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
- 'https://embed.diagrams.net/'
|
||||
# In contrast to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|host.docker.internal:9981}/'
|
||||
- 'https://${COLLABORA_DOMAIN|host.docker.internal:9980}/'
|
||||
img-src:
|
||||
- '''self'''
|
||||
- 'data:'
|
||||
- 'blob:'
|
||||
- 'https://raw.githubusercontent.com/owncloud/awesome-ocis/'
|
||||
# In contrast to bash and docker the default is given after the | character
|
||||
- 'https://${ONLYOFFICE_DOMAIN|host.docker.internal:9981}/'
|
||||
- 'https://${COLLABORA_DOMAIN|host.docker.internal:9980}/'
|
||||
manifest-src:
|
||||
- '''self'''
|
||||
media-src:
|
||||
- '''self'''
|
||||
object-src:
|
||||
- '''self'''
|
||||
- 'blob:'
|
||||
script-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
- 'https://www.gstatic.com/'
|
||||
style-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
3
web/dev/docker/ocis/password-policy-banned-passwords.txt
Normal file
3
web/dev/docker/ocis/password-policy-banned-passwords.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
password
|
||||
12345678
|
||||
ownCloud-1
|
||||
7
web/dev/docker/onlyoffice/entrypoint-override.sh
Executable file
7
web/dev/docker/onlyoffice/entrypoint-override.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# we can't mount it directly because the run-document-server.sh script wants to move it
|
||||
cp /etc/onlyoffice/documentserver/local.dist.json /etc/onlyoffice/documentserver/local.json
|
||||
|
||||
/app/ds/run-document-server.sh
|
||||
71
web/dev/docker/onlyoffice/local.json
Executable file
71
web/dev/docker/onlyoffice/local.json
Executable file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"services": {
|
||||
"CoAuthoring": {
|
||||
"sql": {
|
||||
"type": "postgres",
|
||||
"dbHost": "localhost",
|
||||
"dbPort": "5432",
|
||||
"dbName": "onlyoffice",
|
||||
"dbUser": "onlyoffice",
|
||||
"dbPass": "onlyoffice"
|
||||
},
|
||||
"token": {
|
||||
"enable": {
|
||||
"request": {
|
||||
"inbox": true,
|
||||
"outbox": true
|
||||
},
|
||||
"browser": true
|
||||
},
|
||||
"inbox": {
|
||||
"header": "Authorization"
|
||||
},
|
||||
"outbox": {
|
||||
"header": "Authorization"
|
||||
}
|
||||
},
|
||||
"secret": {
|
||||
"inbox": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
},
|
||||
"outbox": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
},
|
||||
"session": {
|
||||
"string": "B8LjkNqGxn6gf8bkuBUiMwyuCFwFddnu"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rabbitmq": {
|
||||
"url": "amqp://guest:guest@localhost"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
"inputLimits": [
|
||||
{
|
||||
"type": "docx;dotx;docm;dotm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "xlsx;xltx;xlsm;xltm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "pptx;ppsx;potx;pptm;ppsm;potm",
|
||||
"zip": {
|
||||
"uncompressed": "1GB",
|
||||
"template": "*.xml"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
6
web/dev/docker/traefik/configs/tls.yml
Normal file
6
web/dev/docker/traefik/configs/tls.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
tls:
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
certFile: /certificates/server.crt
|
||||
keyFile: /certificates/server.key
|
||||
13
web/dev/docker/wopiserver/entrypoint-override.sh
Executable file
13
web/dev/docker/wopiserver/entrypoint-override.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo "${WOPISECRET}" > /etc/wopi/wopisecret
|
||||
|
||||
cp /etc/wopi/wopiserver.conf.dist /etc/wopi/wopiserver.conf
|
||||
sed -i 's/wopiserver.owncloud.test/'${WOPISERVER_DOMAIN}'/g' /etc/wopi/wopiserver.conf
|
||||
|
||||
if [ "$WOPISERVER_INSECURE" == "true" ]; then
|
||||
sed -i 's/sslverify\s=\sTrue/sslverify = False/g' /etc/wopi/wopiserver.conf
|
||||
fi
|
||||
|
||||
/app/wopiserver.py
|
||||
128
web/dev/docker/wopiserver/wopiserver.conf.dist
Normal file
128
web/dev/docker/wopiserver/wopiserver.conf.dist
Normal file
@@ -0,0 +1,128 @@
|
||||
#
|
||||
# This config is based on https://github.com/cs3org/wopiserver/blob/master/wopiserver.conf
|
||||
#
|
||||
# wopiserver.conf
|
||||
#
|
||||
# Default configuration file for the WOPI server for oCIS
|
||||
#
|
||||
##############################################################
|
||||
|
||||
[general]
|
||||
# Storage access layer to be loaded in order to operate this WOPI server
|
||||
# only "cs3" is supported with oCIS
|
||||
storagetype = cs3
|
||||
|
||||
# Port where to listen for WOPI requests
|
||||
port = 8880
|
||||
|
||||
# Logging level. Debug enables the Flask debug mode as well.
|
||||
# Valid values are: Debug, Info, Warning, Error.
|
||||
loglevel = Error
|
||||
loghandler = stream
|
||||
logdest = stdout
|
||||
|
||||
# URL of your WOPI server or your HA proxy in front of it
|
||||
wopiurl = https://wopiserver.owncloud.test
|
||||
|
||||
# URL for direct download of files. The complete URL that is sent
|
||||
# to clients will include the access_token argument
|
||||
downloadurl = https://wopiserver.owncloud.test/wopi/iop/download
|
||||
|
||||
# The internal server engine to use (defaults to flask).
|
||||
# Set to waitress for production installations.
|
||||
internalserver = waitress
|
||||
|
||||
# List of file extensions deemed incompatible with LibreOffice:
|
||||
# interoperable locking will be disabled for such files
|
||||
nonofficetypes = .md .zmd .txt .epd
|
||||
|
||||
# List of file extensions to be supported by Collabora (deprecated)
|
||||
codeofficetypes = .odt .ott .ods .ots .odp .otp .odg .otg .doc .dot .xls .xlt .xlm .ppt .pot .pps .vsd .dxf .wmf .cdr .pages .number .key
|
||||
|
||||
# WOPI access token expiration time [seconds]
|
||||
tokenvalidity = 86400
|
||||
|
||||
# WOPI lock expiration time [seconds]
|
||||
wopilockexpiration = 3600
|
||||
|
||||
# WOPI lock strict check: if True (default), WOPI locks will be compared according to specs,
|
||||
# that is their representation must match. False allows for a more relaxed comparison,
|
||||
# which compensates incorrect lock requests from Microsoft Office Online 2016-2018
|
||||
# on-premise setups.
|
||||
wopilockstrictcheck = True
|
||||
|
||||
# Enable support of rename operations from WOPI apps. This is currently
|
||||
# disabled by default as it has been observed that both MS Office and Collabora
|
||||
# Online do not play well with this feature.
|
||||
# Not supported with oCIS, must always be set to "False"
|
||||
enablerename = False
|
||||
|
||||
# Detection of external Microsoft Office or LibreOffice locks. By default, lock files
|
||||
# compatible with Office for Desktop applications are detected, assuming that the
|
||||
# underlying storage can be mounted as a remote filesystem: in this case, WOPI GetLock
|
||||
# and SetLock operations return such locks and prevent online apps from entering edit mode.
|
||||
# This feature can be disabled in order to operate a pure WOPI server for online apps.
|
||||
# Not supported with oCIS, must always be set to "False"
|
||||
detectexternallocks = False
|
||||
|
||||
# Location of the webconflict files. By default, such files are stored in the same path
|
||||
# as the original file. If that fails (e.g. because of missing permissions),
|
||||
# an attempt is made to store such files in this path if specified, otherwise
|
||||
# the system falls back to the recovery space (cf. io|recoverypath).
|
||||
# The keywords <user_initial> and <username> are replaced with the actual username's
|
||||
# initial letter and the actual username, respectively, so you can use e.g.
|
||||
# /your_storage/home/user_initial/username
|
||||
#conflictpath = /
|
||||
|
||||
# ownCloud's WOPI proxy configuration. Disabled by default.
|
||||
#wopiproxy = https://external-wopi-proxy.com
|
||||
#wopiproxysecretfile = /path/to/your/shared-key-file
|
||||
#proxiedappname = Name of your proxied app
|
||||
|
||||
[security]
|
||||
# Location of the secret files. Requires a restart of the
|
||||
# WOPI server when either the files or their content change.
|
||||
wopisecretfile = /etc/wopi/wopisecret
|
||||
# iop secret is not used for cs3 storage type
|
||||
#iopsecretfile = /etc/wopi/iopsecret
|
||||
|
||||
# Use https as opposed to http (requires certificate)
|
||||
usehttps = no
|
||||
|
||||
# Certificate and key for https. Requires a restart
|
||||
# to apply a change.
|
||||
wopicert = /etc/grid-security/host.crt
|
||||
wopikey = /etc/grid-security/host.key
|
||||
|
||||
[bridge]
|
||||
# SSL certificate check for the connected apps
|
||||
sslverify = True
|
||||
|
||||
# Minimal time interval between two consecutive save operations [seconds]
|
||||
#saveinterval = 200
|
||||
|
||||
# Minimal time interval before a closed file is WOPI-unlocked [seconds]
|
||||
#unlockinterval = 90
|
||||
|
||||
# CodiMD: disable creating zipped bundles when files contain pictures
|
||||
#disablezip = False
|
||||
|
||||
[io]
|
||||
# Size used for buffered reads [bytes]
|
||||
chunksize = 4194304
|
||||
|
||||
# Path to a recovery space in case of I/O errors when reaching to the remote storage.
|
||||
# This is expected to be a local path, and it is provided in order to ease user support.
|
||||
# Defaults to the indicated spool folder.
|
||||
recoverypath = /var/spool/wopirecovery
|
||||
|
||||
[cs3]
|
||||
# Host and port of the Reva(-like) CS3-compliant GRPC gateway endpoint
|
||||
revagateway = ocis:9142
|
||||
|
||||
# Reva/gRPC authentication token expiration time [seconds]
|
||||
# The default value matches Reva's default
|
||||
authtokenvalidity = 3600
|
||||
|
||||
# SSL certificate check for Reva
|
||||
sslverify = True
|
||||
49
web/dev/scripts/bump_versions.sh
Executable file
49
web/dev/scripts/bump_versions.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script bumps the version in the package.json files of the main app
|
||||
# and all published packages to the provided version.
|
||||
#
|
||||
# NOTE: only run this if all packages are supposed to get the same version!
|
||||
|
||||
apps=("design-system" "eslint-config" "extension-sdk" "web-pkg" "web-client" "web-test-helpers")
|
||||
|
||||
NEW_VERSION="$1"
|
||||
|
||||
if [ -z "$NEW_VERSION" ]; then
|
||||
echo "Error: No new version provided."
|
||||
echo "Usage: $0 <new_version>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||||
sed -i '' "s/\"version\": \"${CURRENT_VERSION}\"/\"version\": \"${NEW_VERSION}\"/" package.json
|
||||
|
||||
for app in "${apps[@]}"; do
|
||||
cd "./packages/$app"
|
||||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||||
sed -i '' "s/\"version\": \"${CURRENT_VERSION}\"/\"version\": \"${NEW_VERSION}\"/" package.json
|
||||
cd "../.."
|
||||
done
|
||||
|
||||
echo "package.json files have been updated to version $NEW_VERSION"
|
||||
|
||||
SONAR_PROPERTIES_FILE="sonar-project.properties"
|
||||
|
||||
if [ ! -f "$SONAR_PROPERTIES_FILE" ]; then
|
||||
echo "Error: $SONAR_PROPERTIES_FILE file not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "s/sonar\.projectVersion=[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*/sonar.projectVersion=$NEW_VERSION/" "$SONAR_PROPERTIES_FILE"
|
||||
else
|
||||
sed -i "s/sonar\.projectVersion=[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*/sonar.projectVersion=$NEW_VERSION/" "$SONAR_PROPERTIES_FILE"
|
||||
fi
|
||||
|
||||
if grep -q "sonar.projectVersion=$NEW_VERSION" "$SONAR_PROPERTIES_FILE"; then
|
||||
echo "Sonar project version successfully updated to $NEW_VERSION"
|
||||
else
|
||||
echo "Failed to update Sonar project version. Please check the file format."
|
||||
exit 1
|
||||
fi
|
||||
26
web/dev/scripts/create_and_push_tags.sh
Executable file
26
web/dev/scripts/create_and_push_tags.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script creates and pushes tags for the main app and all published packages.
|
||||
|
||||
APPS=("design-system" "eslint-config" "extension-sdk" "web-pkg" "web-client" "web-test-helpers")
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
TAG="v${VERSION}"
|
||||
|
||||
git tag -s -a "$TAG" -m "$TAG"
|
||||
git push origin "$TAG"
|
||||
echo "v$VERSION has been created and pushed"
|
||||
|
||||
for app in "${APPS[@]}"; do
|
||||
cd "./packages/$app"
|
||||
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
TAG="${app}-v${VERSION}"
|
||||
|
||||
git tag -s -a "$TAG" -m "$TAG"
|
||||
git push origin "$TAG"
|
||||
|
||||
echo "$app-v$VERSION has been created and pushed"
|
||||
cd "../.."
|
||||
done
|
||||
365
web/docker-compose.yml
Normal file
365
web/docker-compose.yml
Normal file
@@ -0,0 +1,365 @@
|
||||
x-ocis-server: &ocis-service
|
||||
image: ${OCIS_IMAGE:-owncloud/ocis-rolling:master}
|
||||
entrypoint: /bin/sh
|
||||
command: ['-c', 'ocis init || true && ocis server']
|
||||
environment: &ocis-environment
|
||||
OCIS_INSECURE: '${OCIS_INSECURE:-true}'
|
||||
OCIS_LOG_LEVEL: '${OCIS_LOG_LEVEL:-error}'
|
||||
OCIS_LOG_PRETTY: '${OCIS_LOG_PRETTY:-true}'
|
||||
OCIS_LOG_COLOR: '${OCIS_LOG_COLOR:-true}'
|
||||
OCIS_PASSWORD_POLICY_MIN_CHARACTERS: '3'
|
||||
OCIS_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS: '0'
|
||||
OCIS_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS: '0'
|
||||
OCIS_PASSWORD_POLICY_MIN_DIGITS: '0'
|
||||
OCIS_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS: '0'
|
||||
OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST: '/etc/ocis/password-policy-banned-passwords.txt'
|
||||
|
||||
# WEB
|
||||
WEB_ASSET_CORE_PATH: ${WEB_ASSET_CORE_PATH:-/web/dist}
|
||||
WEB_ASSET_APPS_PATH: ${WEB_ASSET_APPS_PATH:-/web/apps}
|
||||
WEB_UI_CONFIG_FILE: ${WEB_UI_CONFIG_FILE:-/web/config.json}
|
||||
|
||||
#FRONTEND
|
||||
FRONTEND_SEARCH_MIN_LENGTH: '2'
|
||||
FRONTEND_OCS_ENABLE_DENIALS: 'true'
|
||||
FRONTEND_FULL_TEXT_SEARCH_ENABLED: 'true'
|
||||
GRAPH_INCLUDE_OCM_SHAREES: 'true'
|
||||
FRONTEND_CONFIGURABLE_NOTIFICATIONS: 'true'
|
||||
|
||||
# IDM
|
||||
IDM_CREATE_DEMO_USERS: '${DEMO_USERS:-true}'
|
||||
IDM_ADMIN_PASSWORD: '${ADMIN_PASSWORD:-admin}' # override the random admin password from `ocis init`
|
||||
IDM_SVC_PASSWORD: '${IDM_SVC_PASSWORD:-some-ldap-idm-password}'
|
||||
IDM_REVASVC_PASSWORD: '${IDM_REVASVC_PASSWORD:-some-ldap-reva-password}'
|
||||
IDM_IDPSVC_PASSWORD: '${IDM_IDPSVC_PASSWORD:-some-ldap-idp-password}'
|
||||
|
||||
# IDP
|
||||
IDP_LDAP_BIND_PASSWORD: '${IDP_LDAP_BIND_PASSWORD:-some-ldap-idp-password}'
|
||||
|
||||
# STORAGE
|
||||
STORAGE_HOME_DRIVER: '${STORAGE_HOME_DRIVER:-ocis}'
|
||||
STORAGE_USERS_DRIVER: '${STORAGE_USERS_DRIVER:-ocis}'
|
||||
STORAGE_TRANSFER_SECRET: '${STORAGE_TRANSFER_SECRET:-some-ocis-transfer-secret}'
|
||||
|
||||
# LDAP
|
||||
GROUPS_LDAP_BIND_PASSWORD: '${GROUPS_LDAP_BIND_PASSWORD:-some-ldap-reva-password}'
|
||||
USERS_LDAP_BIND_PASSWORD: '${USERS_LDAP_BIND_PASSWORD:-some-ldap-reva-password}'
|
||||
AUTH_BASIC_LDAP_BIND_PASSWORD: '${AUTH_BASIC_LDAP_BIND_PASSWORD:-some-ldap-reva-password}'
|
||||
GRAPH_APPLICATION_ID: '${GRAPH_APPLICATION_ID:-some-graph-app-id}'
|
||||
GRAPH_LDAP_BIND_PASSWORD: '${GRAPH_LDAP_BIND_PASSWORD:-some-ldap-idm-password}'
|
||||
LDAP_GROUP_SUBSTRING_FILTER_TYPE: 'any'
|
||||
LDAP_USER_SUBSTRING_FILTER_TYPE: 'any'
|
||||
|
||||
# PROXY
|
||||
PROXY_ENABLE_BASIC_AUTH: '${PROXY_ENABLE_BASIC_AUTH:-true}'
|
||||
PROXY_TLS: 'false'
|
||||
|
||||
# TIKA
|
||||
SEARCH_EXTRACTOR_TYPE: 'tika'
|
||||
SEARCH_EXTRACTOR_TIKA_TIKA_URL: 'http://host.docker.internal:9998'
|
||||
SEARCH_EXTRACTOR_CS3SOURCE_INSECURE: 'true'
|
||||
|
||||
# App Provider
|
||||
GATEWAY_GRPC_ADDR: 0.0.0.0:9142 # make the REVA gateway accessible to the app drivers
|
||||
NATS_NATS_HOST: 0.0.0.0
|
||||
NATS_NATS_PORT: 9233
|
||||
|
||||
# OCM
|
||||
OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE: '/etc/ocis/ocmproviders.json'
|
||||
OCM_OCM_INVITE_MANAGER_INSECURE: 'true'
|
||||
OCM_OCM_SHARE_PROVIDER_INSECURE: 'true'
|
||||
OCM_OCM_STORAGE_PROVIDER_INSECURE: 'true'
|
||||
|
||||
extra_hosts:
|
||||
- host.docker.internal:${DOCKER_HOST:-host-gateway}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- traefik
|
||||
- tika-service
|
||||
|
||||
services:
|
||||
ocis:
|
||||
<<: *ocis-service
|
||||
container_name: web_ocis
|
||||
environment:
|
||||
<<: *ocis-environment
|
||||
OCIS_URL: ${OCIS_URL:-https://host.docker.internal:9200}
|
||||
OCIS_CORS_ALLOW_ORIGINS: https://host.docker.internal:9200,https://host.docker.internal:9201
|
||||
OCM_WEBAPP_TEMPLATE: https://host.docker.internal:9201/o/{{.Token}}/{relative-path-to-shared-resource}
|
||||
# make the registry available to the app provider containers
|
||||
MICRO_REGISTRY: 'nats-js-kv'
|
||||
MICRO_REGISTRY_ADDRESS: 0.0.0.0:9233
|
||||
PROXY_CSP_CONFIG_FILE_LOCATION: /etc/ocis/csp.yaml
|
||||
ONLYOFFICE_DOMAIN: host.docker.internal:9981
|
||||
COLLABORA_DOMAIN: host.docker.internal:9980
|
||||
FRONTEND_APP_HANDLER_SECURE_VIEW_APP_ADDR: com.owncloud.api.collaboration.Collabora
|
||||
# Needed for enabling all roles
|
||||
GRAPH_AVAILABLE_ROLES: b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5,a8d5fe5e-96e3-418d-825b-534dbdf22b99,fb6c3e19-e378-47e5-b277-9732f9de6e21,58c63c02-1d89-4572-916a-870abc5a1b7d,2d00ce52-1fc2-4dbc-8b95-a73b73395f5a,1c996275-f1c9-4e71-abdf-a42f6495e960,312c0871-5ef7-4b3a-85b6-0e4074c64049,aa97fe03-7980-45ac-9e50-b325749fd7e6,63e64e19-8d43-42ec-a738-2b6af2610efa
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.ocis.tls: true
|
||||
traefik.http.routers.ocis.rule: Host(`host.docker.internal`) && PathPrefix(`/`)
|
||||
traefik.http.routers.ocis.entrypoints: ocis
|
||||
traefik.http.services.ocis.loadbalancer.server.port: 9200
|
||||
# workaround: https://github.com/owncloud/ocis/issues/5108
|
||||
traefik.http.routers.ocis.middlewares: cors
|
||||
volumes:
|
||||
- ./dev/docker/ocis/csp.yaml:/etc/ocis/csp.yaml
|
||||
- ./dev/docker/ocis/password-policy-banned-passwords.txt:/etc/ocis/password-policy-banned-passwords.txt
|
||||
- ./dev/docker/ocis.idp.config.yaml:/etc/ocis/idp.yaml
|
||||
- ./dev/docker/ocis-ca:/var/lib/ocis/proxy
|
||||
- ./dev/docker/ocis.storage.ocmproviders.json:/etc/ocis/ocmproviders.json
|
||||
- ./dev/docker/apps:/web/apps
|
||||
- ./dist:/web/dist
|
||||
- ./dev/docker/ocis/app-registry.yaml:/etc/ocis/app-registry.yaml
|
||||
- ocis-config:/etc/ocis
|
||||
- ${OCIS_WEB_CONFIG:-./dev/docker/ocis.web.config.json}:/web/config.json:ro
|
||||
|
||||
ocis-federated:
|
||||
<<: *ocis-service
|
||||
container_name: web_ocis_federated
|
||||
environment:
|
||||
<<: *ocis-environment
|
||||
OCIS_URL: https://host.docker.internal:10200
|
||||
OCIS_CORS_ALLOW_ORIGINS: https://host.docker.internal:10201
|
||||
OCM_WEBAPP_TEMPLATE: https://host.docker.internal:10201/o/{{.Token}}/{relative-path-to-shared-resource}
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.ocis-federated.tls: true
|
||||
traefik.http.routers.ocis-federated.rule: Host(`host.docker.internal`) && PathPrefix(`/`)
|
||||
traefik.http.routers.ocis-federated.entrypoints: ocis-federated
|
||||
traefik.http.services.ocis-federated.loadbalancer.server.port: 9200
|
||||
# workaround: https://github.com/owncloud/ocis/issues/5108
|
||||
traefik.http.routers.ocis-federated.middlewares: cors
|
||||
volumes:
|
||||
- ./dev/docker/ocis/password-policy-banned-passwords.txt:/etc/ocis/password-policy-banned-passwords.txt
|
||||
- ./dev/docker/ocis.idp.config.yaml:/etc/ocis/idp.yaml
|
||||
- ./dev/docker/ocis-ca:/var/lib/ocis/proxy
|
||||
- ./dev/docker/ocis.storage.ocmproviders.json:/etc/ocis/ocmproviders.json
|
||||
- ./dist:/web/dist
|
||||
- ./dev/docker/ocis/app-registry.yaml:/etc/ocis/app-registry.yaml
|
||||
- ocis-federated-config:/etc/ocis
|
||||
- ${OCIS_WEB_CONFIG:-./dev/docker/ocis.web-federated.config.json}:/web/config.json:ro
|
||||
|
||||
collaboration:
|
||||
image: ${OCIS_IMAGE:-owncloud/ocis-rolling:master}
|
||||
depends_on:
|
||||
ocis:
|
||||
condition: service_started
|
||||
collabora:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command: ['-c', 'ocis collaboration server']
|
||||
environment:
|
||||
COLLABORATION_GRPC_ADDR: 0.0.0.0:9301
|
||||
COLLABORATION_HTTP_ADDR: 0.0.0.0:9300
|
||||
MICRO_REGISTRY: nats-js-kv
|
||||
MICRO_REGISTRY_ADDRESS: ocis:9233
|
||||
COLLABORATION_WOPI_SRC: https://${WOPISERVER_DOMAIN:-host.docker.internal:9300}
|
||||
COLLABORATION_APP_NAME: Collabora
|
||||
COLLABORATION_APP_ADDR: https://${COLLABORA_DOMAIN:-host.docker.internal:9980}
|
||||
COLLABORATION_APP_ICON: https://${COLLABORA_DOMAIN:-host.docker.internal:9980}/favicon.ico
|
||||
COLLABORATION_APP_INSECURE: ${INSECURE:-true}
|
||||
COLLABORATION_CS3API_DATAGATEWAY_INSECURE: ${INSECURE:-true}
|
||||
COLLABORATION_LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
OCIS_URL: ${OCIS_URL:-https://host.docker.internal:9200}
|
||||
extra_hosts:
|
||||
- host.docker.internal:${DOCKER_HOST:-host-gateway}
|
||||
volumes:
|
||||
- ocis-config:/etc/ocis
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.collaboration.tls: true
|
||||
traefik.http.routers.collaboration.rule: PathPrefix(`/`)
|
||||
traefik.http.routers.collaboration.entrypoints: collaboration
|
||||
traefik.http.services.collaboration.loadbalancer.server.port: 9300
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
collabora:
|
||||
image: collabora/code:25.04.7.3.1
|
||||
entrypoint: /bin/sh
|
||||
command: ['-c', 'coolconfig generate-proof-key ; /start-collabora-online.sh']
|
||||
environment:
|
||||
DONT_GEN_SSL_CERT: YES
|
||||
extra_params: |
|
||||
--o:ssl.enable=false \
|
||||
--o:ssl.ssl_verification=false \
|
||||
--o:ssl.termination=true \
|
||||
--o:welcome.enable=false \
|
||||
--o:net.content_security_policy=frame-ancestors ${OCIS_URL:-https://host.docker.internal:9200}
|
||||
username: ${COLLABORA_ADMIN_USER:-admin}
|
||||
password: ${COLLABORA_ADMIN_PASSWORD:-admin}
|
||||
cap_add:
|
||||
- MKNOD
|
||||
- SYS_ADMIN
|
||||
extra_hosts:
|
||||
- host.docker.internal:${DOCKER_HOST:-host-gateway}
|
||||
healthcheck:
|
||||
test: [
|
||||
'CMD',
|
||||
'bash',
|
||||
'-c',
|
||||
"exec 3<>/dev/tcp/127.0.0.1/9980 && echo -e 'GET /hosting/discovery HTTP/1.1\r\nHost: localhost:9980\r\n\r\n' >&3 && head -n 1 <&3 | grep '200 OK'"
|
||||
]
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.collabora.tls: true
|
||||
traefik.http.routers.collabora.rule: PathPrefix(`/`)
|
||||
traefik.http.routers.collabora.entrypoints: collabora
|
||||
traefik.http.services.collabora.loadbalancer.server.port: 9980
|
||||
restart: always
|
||||
depends_on:
|
||||
- traefik
|
||||
|
||||
collaboration-oo:
|
||||
image: ${OCIS_IMAGE:-owncloud/ocis-rolling:master}
|
||||
depends_on:
|
||||
ocis:
|
||||
condition: service_started
|
||||
onlyoffice:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command: ['-c', 'ocis collaboration server']
|
||||
environment:
|
||||
COLLABORATION_GRPC_ADDR: 0.0.0.0:9303
|
||||
COLLABORATION_HTTP_ADDR: 0.0.0.0:9302
|
||||
MICRO_REGISTRY: nats-js-kv
|
||||
MICRO_REGISTRY_ADDRESS: ocis:9233
|
||||
COLLABORATION_WOPI_SRC: https://${WOPISERVER_ONLYOFFICE_DOMAIN:-host.docker.internal:9302}
|
||||
COLLABORATION_APP_NAME: OnlyOffice
|
||||
COLLABORATION_APP_PRODUCT: OnlyOffice
|
||||
COLLABORATION_APP_ADDR: https://${ONLYOFFICE_DOMAIN:-host.docker.internal:9981}
|
||||
COLLABORATION_APP_ICON: https://${ONLYOFFICE_DOMAIN:-host.docker.internal:9981}/web-apps/apps/documenteditor/main/resources/img/favicon.ico
|
||||
COLLABORATION_APP_INSECURE: ${INSECURE:-true}
|
||||
COLLABORATION_CS3API_DATAGATEWAY_INSECURE: ${INSECURE:-true}
|
||||
COLLABORATION_LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
OCIS_URL: ${OCIS_URL:-https://host.docker.internal:9200}
|
||||
extra_hosts:
|
||||
- host.docker.internal:${DOCKER_HOST:-host-gateway}
|
||||
volumes:
|
||||
- ocis-config:/etc/ocis
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.collaboration-oo.tls: true
|
||||
traefik.http.routers.collaboration-oo.rule: PathPrefix(`/`)
|
||||
traefik.http.routers.collaboration-oo.entrypoints: collaboration-oo
|
||||
traefik.http.services.collaboration-oo.loadbalancer.server.port: 9302
|
||||
logging:
|
||||
driver: ${LOG_DRIVER:-local}
|
||||
restart: always
|
||||
|
||||
onlyoffice:
|
||||
image: onlyoffice/documentserver:9.2.1
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- /entrypoint-override.sh
|
||||
environment:
|
||||
WOPI_ENABLED: true
|
||||
USE_UNAUTHORIZED_STORAGE: true # self signed certificates
|
||||
volumes:
|
||||
- ./dev/docker/onlyoffice/entrypoint-override.sh:/entrypoint-override.sh
|
||||
- ./dev/docker/onlyoffice/local.json:/etc/onlyoffice/documentserver/local.dist.json
|
||||
extra_hosts:
|
||||
- host.docker.internal:${DOCKER_HOST:-host-gateway}
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost/hosting/discovery']
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.onlyoffice.tls: true
|
||||
traefik.http.routers.onlyoffice.rule: PathPrefix(`/`)
|
||||
traefik.http.routers.onlyoffice.entrypoints: websecure
|
||||
traefik.http.services.onlyoffice.loadbalancer.server.port: 80
|
||||
# websockets can't be opened when this is ommitted
|
||||
traefik.http.middlewares.onlyoffice.headers.customrequestheaders.X-Forwarded-Proto: https
|
||||
traefik.http.routers.onlyoffice.middlewares: onlyoffice
|
||||
restart: always
|
||||
depends_on:
|
||||
- traefik
|
||||
|
||||
traefik:
|
||||
image: traefik:v3.7.1
|
||||
restart: unless-stopped
|
||||
entrypoint:
|
||||
[
|
||||
'/bin/sh',
|
||||
'-c',
|
||||
"[ -f /certificates/server.key ] && ./entrypoint.sh $$@ || (apk add openssl && openssl req -subj '/CN=ocis.test' -x509 -sha256 -nodes -days 3650 -newkey rsa:2048 -keyout /certificates/server.key -out /certificates/server.crt && chmod -R 777 /certificates && ./entrypoint.sh $$@)"
|
||||
]
|
||||
command:
|
||||
- '--pilot.dashboard=false'
|
||||
- '--log.level=DEBUG'
|
||||
- '--api.dashboard=true'
|
||||
- '--api.insecure=true'
|
||||
- '--providers.file.directory=/configs'
|
||||
- '--providers.docker=true'
|
||||
- '--providers.docker.exposedbydefault=false'
|
||||
- '--entrypoints.web.address=:80'
|
||||
- '--entrypoints.ocis.address=:9200'
|
||||
- '--entrypoints.ocis-federated.address=:10200'
|
||||
- '--entrypoints.collabora.address=:9980'
|
||||
# allow encoded characters which is required for collaboration/Collabora
|
||||
- '--entryPoints.collabora.http.encodedCharacters.allowEncodedSlash=true'
|
||||
- '--entryPoints.collabora.http.encodedCharacters.allowEncodedQuestionMark=true'
|
||||
- '--entryPoints.collabora.http.encodedCharacters.allowEncodedPercent=true'
|
||||
- '--entrypoints.wopi.address=:8880'
|
||||
- '--entrypoints.collaboration.address=:9300'
|
||||
- '--entrypoints.collaboration-oo.address=:9302'
|
||||
- '--entrypoints.websecure.address=:443'
|
||||
- '--entrypoints.websecure.http.middlewares=https_config@docker'
|
||||
- '--entrypoints.websecure.http.tls.options=default'
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.http_catchall.rule: HostRegexp(`{any:.+}`)
|
||||
traefik.http.routers.http_catchall.entrypoints: web
|
||||
traefik.http.routers.http_catchall.middlewares: https_config
|
||||
traefik.http.middlewares.https_config.headers.sslRedirect: true
|
||||
traefik.http.middlewares.https_config.headers.stsSeconds: 63072000
|
||||
traefik.http.middlewares.https_config.headers.stsIncludeSubdomains: true
|
||||
traefik.http.middlewares.cors.headers.accesscontrolallowmethods: '*'
|
||||
traefik.http.middlewares.cors.headers.accesscontrolallowheaders: '*'
|
||||
traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist: '*'
|
||||
traefik.http.middlewares.cors.headers.accesscontrolexposeheaders: '*'
|
||||
traefik.http.middlewares.cors.headers.accesscontrolmaxage: 100
|
||||
traefik.http.middlewares.cors.headers.addvaryheader: true
|
||||
ports:
|
||||
- '80:80'
|
||||
- '8090:8080'
|
||||
- '9200:9200'
|
||||
- '9300:9300'
|
||||
- '9302:9302'
|
||||
- '10200:10200'
|
||||
- '9980:9980'
|
||||
- '8880:8880'
|
||||
- '9981:443'
|
||||
volumes:
|
||||
- './dev/docker/traefik/certificates:/certificates'
|
||||
- './dev/docker/traefik/configs:/configs'
|
||||
- '/var/run/docker.sock:/var/run/docker.sock:ro'
|
||||
|
||||
tika-service:
|
||||
image: owncloudci/wait-for:latest
|
||||
container_name: web_tika_service
|
||||
depends_on:
|
||||
- tika
|
||||
command:
|
||||
- 'wait-for -it tika:9998 -t 300'
|
||||
|
||||
tika:
|
||||
image: apache/tika:3.2.3.0
|
||||
container_name: web_tika
|
||||
platform: linux/amd64
|
||||
ports:
|
||||
- 9998:9998
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
uploads:
|
||||
ocis-config:
|
||||
ocis-federated-config:
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
25
web/docker/Dockerfile
Normal file
25
web/docker/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
FROM owncloudops/nginx@sha256:8ca0c90c2f537fef6195ba8f5ebe6d6c00fe0a0c545f25ce8acd418a831a19a4
|
||||
|
||||
LABEL maintainer="ownCloud GmbH <devops@owncloud.com>" \
|
||||
org.opencontainers.image.title="ownCloud Web" \
|
||||
org.opencontainers.image.vendor="ownCloud GmbH" \
|
||||
org.opencontainers.image.authors="ownCloud GmbH" \
|
||||
org.opencontainers.image.description="ownCloud Web - User interface for ownCloud" \
|
||||
org.opencontainers.image.licenses="Apache-2.0" \
|
||||
org.opencontainers.image.documentation="https://github.com/owncloud/ocis" \
|
||||
org.opencontainers.image.url="https://hub.docker.com/r/owncloud/web" \
|
||||
org.opencontainers.image.source="https://github.com/owncloud/ocis"
|
||||
|
||||
RUN rm -f /var/lib/nginx/html/*
|
||||
|
||||
ADD docker/overlay /
|
||||
ADD dist/ /var/lib/nginx/html
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
USER nginx
|
||||
|
||||
STOPSIGNAL SIGTERM
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
WORKDIR /var/lib/nginx/html
|
||||
10
web/docker/overlay/usr/bin/healthcheck
Executable file
10
web/docker/overlay/usr/bin/healthcheck
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
URL=http://127.0.0.1:8080
|
||||
|
||||
wget --quiet --tries=1 --spider ${URL}
|
||||
[ $? -ne 0 ] && exit 1
|
||||
|
||||
exit 0
|
||||
95
web/docs/Makefile
Normal file
95
web/docs/Makefile
Normal file
@@ -0,0 +1,95 @@
|
||||
SHELL := bash
|
||||
NAME := web
|
||||
# we need an override so that this variable is cleanly set in this makefile
|
||||
# else it might come from somewhere else
|
||||
override HUGO := ${CURDIR}/hugo
|
||||
override HDIR := ${CURDIR}/hugo/.git
|
||||
|
||||
# print a hint when doing a local build because it may fail if you have not run pnpm commands at least once
|
||||
docs-first-time-message:
|
||||
@echo
|
||||
@echo 'Note, on a fresh web clone, you need to run `pnpm install` and `pnpm build` once to create required directories.'
|
||||
|
||||
# if the directory exists, print that we do not need to prepare
|
||||
hugo-exists:
|
||||
@if [ -d $(HDIR) ]; then \
|
||||
echo; \
|
||||
echo 'Build environment for hugo exists, nothing to setup, continuing.'; \
|
||||
fi
|
||||
|
||||
# if the directory does not extist, initialize the framework and create the theme
|
||||
$(HDIR):
|
||||
@echo 'Initialize the hugo framework and build the theme, no docs get built.'
|
||||
@mkdir -p $(HUGO)/content/
|
||||
@mkdir -p $(HUGO)/extensions/
|
||||
@mkdir -p $(HUGO)/public/
|
||||
@cd $(HUGO) && git init
|
||||
@cd $(HUGO) && git config advice.detachedHead false
|
||||
@cd $(HUGO) && git remote rm origin || true
|
||||
@cd $(HUGO) && git remote add origin https://github.com/owncloud/owncloud.github.io
|
||||
@cd $(HUGO) && git fetch --depth=1
|
||||
@cd $(HUGO) && git checkout origin/main -f
|
||||
@$(MAKE) -C $(HUGO) --no-print-directory theme
|
||||
|
||||
# print available make targets
|
||||
.PHONY: help
|
||||
.DEFAULT_GOAL := help
|
||||
help:
|
||||
@echo -e 'Available .PHONY targets: \n'
|
||||
@grep -P -o '(?<=^\.PHONY: )(.*)' Makefile | sort -u
|
||||
@echo
|
||||
|
||||
# alternative target because we also use it in the root's makefile
|
||||
.PHONY:list
|
||||
list: help
|
||||
|
||||
# for drone only. drone uses an image for hugo that needs the hugo folder in the root
|
||||
# CURDIR will work for make only but not when running manually in the shell
|
||||
.PHONY: docs-hugo-drone-prep
|
||||
docs-hugo-drone-prep:
|
||||
@echo
|
||||
@echo 'Linking directory hugo for drone.'
|
||||
@rm -f ../hugo
|
||||
@ln -s $(HUGO) ../hugo
|
||||
|
||||
# create the docs build environment
|
||||
.PHONY: docs-init
|
||||
docs-init: hugo-exists $(HDIR)
|
||||
# if there is nothing to do, stop printing that
|
||||
# another way would be https://stackoverflow.com/questions/58039810/makefiles-what-is-an-order-only-prerequisite
|
||||
@:
|
||||
|
||||
# the docs-build|serve commands require that docs-init was run first for the required data to exists
|
||||
# create a docs build
|
||||
.PHONY: docs-build
|
||||
docs-build:
|
||||
@echo
|
||||
@echo 'Building web for owncloud.dev'
|
||||
@$(MAKE) -C $(HUGO) --no-print-directory hugo-build
|
||||
@echo 'To view the rendered docs in the browser, run: make docs-serve'
|
||||
|
||||
# serve built docs with hugo
|
||||
.PHONY: docs-serve
|
||||
docs-serve:
|
||||
@$(MAKE) -C $(HUGO) --no-print-directory hugo-server
|
||||
|
||||
# copy required resources into hugo
|
||||
.PHONY: docs-copy
|
||||
docs-copy:
|
||||
@echo
|
||||
@echo 'Syncing required doc files and directories for the build process.'
|
||||
# brace expansion not with sh
|
||||
@rsync --delete -ax --exclude={hugo,Makefile,.gitignore,README.md} ./ $(HUGO)/content/$(NAME)
|
||||
|
||||
# clean up docs build artifacts (removing the hugo folder)
|
||||
.PHONY: docs-clean
|
||||
docs-clean:
|
||||
# NOTE: the whitespace at the beginning of the ifeq/else/endif statements is intentional.
|
||||
@echo
|
||||
ifneq ($(shell id -u), 0)
|
||||
@echo "You must run the clean command using sudo or as root because some doc files are created by root"
|
||||
else
|
||||
@echo 'Clean up docs build artifacts'
|
||||
@rm -rf $(HUGO)
|
||||
@echo "Removed folder: $(HUGO)"
|
||||
endif
|
||||
12
web/docs/_index.md
Normal file
12
web/docs/_index.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "ownCloud Web"
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: -15
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
This is the next generation ownCloud frontend.
|
||||
If you're new here, head over to the the [getting started guide]({{< ref "getting-started.md" >}}) for a quick introduction.
|
||||
74
web/docs/backend-oc10.md
Normal file
74
web/docs/backend-oc10.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: "Setup With ownCloud Classic"
|
||||
date: 2020-04-15T00:00:00+00:00
|
||||
weight: 40
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocFilePath: backend-oc10.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Compatibility
|
||||
|
||||
Please note that the usage of Web UI and ownCloud Classic as backend is not recommended starting with version 7.1.0 of the Web UI. Therefore, this section only applies to versions < 7.1.0.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Decide on which host and port Web will be served, for example `https://web-host:9100/web-path/`.
|
||||
In this document, we will refer to the following:
|
||||
- `<web-url>` as the full URL, for example `https://web-host:9100/web-path/`
|
||||
- `<web-domain>` as the protocol, domain and port, for example: `https://web-host:9100`
|
||||
|
||||
## Setting up ownCloud Classic
|
||||
|
||||
Make sure you have [ownCloud Classic](https://owncloud.org/download/#owncloud-server) already installed.
|
||||
|
||||
### Adjusting config.php
|
||||
|
||||
Add the following entries to config/config.php:
|
||||
|
||||
- tell ownCloud where Web is located:
|
||||
```
|
||||
'web.baseUrl' => '<web-url>',
|
||||
```
|
||||
|
||||
- add a CORS domain entry for Web in config.php:
|
||||
```
|
||||
'cors.allowed-domains' => ['<web-domain>'],
|
||||
```
|
||||
|
||||
### Setting up OAuth2
|
||||
|
||||
To connect to the ownCloud server, it is necessary to set it up with OAuth2.
|
||||
|
||||
Install and enable the [oauth2 app](https://marketplace.owncloud.com/apps/oauth2):
|
||||
```bash
|
||||
% occ market:install oauth2
|
||||
% occ app:enable oauth2
|
||||
```
|
||||
|
||||
Login as administrator in the ownCloud Classic web interface and go to the "User Authentication" section in the admin settings and add an entry for Web as follows:
|
||||
|
||||
- pick an arbitrary name for the client
|
||||
- set the redirection URI to `<web-url>/oidc-callback.html`
|
||||
- make sure to take note of the **client identifier** value as it will be needed in the Web configuration later on
|
||||
|
||||
### Setting up Web
|
||||
|
||||
In the local Web checkout, copy the `config/config.json.sample-oc10` file to `config/config.json` and adjust it accordingly:
|
||||
|
||||
- Set the "server" key to the URL of the ownCloud server including path. If the URL contains a path, please also add a **trailing slash** there.
|
||||
- Set the "clientId" key to the **client identifier** as copied from the "User Authentication" section before.
|
||||
- Adjust "url" and "authUrl" using the ownCloud server URL as prefix for both
|
||||
- Optionally adjust "apps" for the list of apps to be loaded. These match the app names inside the "apps" folder.
|
||||
|
||||
## Running Web
|
||||
|
||||
- if running from source, make sure to [build Web]({{< ref "./building.md" >}}) first
|
||||
- run by launching a rollup dev server `pnpm serve`
|
||||
- when working on the Web code, rollup will recompile the code automatically
|
||||
|
||||
## Running acceptance tests
|
||||
|
||||
For testing, please refer to the [testing docs]({{< ref "testing/_index.md" >}})
|
||||
36
web/docs/backend-ocis.md
Normal file
36
web/docs/backend-ocis.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Setup With oCIS"
|
||||
date: 2020-04-15T00:00:00+00:00
|
||||
weight: 50
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocFilePath: backend-ocis.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Setting up Web
|
||||
|
||||
- Clone the [repository](https://github.com/owncloud/web/)
|
||||
- Initally install all dependencies by running `pnpm install`
|
||||
- Copy `./config/config.json.sample-ocis` to `./config/config.json` and adjust values if required
|
||||
|
||||
## Running Web
|
||||
|
||||
- Start bundling web with a watcher by running `pnpm build:w`
|
||||
|
||||
## Setting up oCIS
|
||||
|
||||
- Setup oCIS by following the [setup instructions](https://owncloud.dev/ocis/getting-started/)
|
||||
- Start oCIS with local links to your bundled web frontend and config by running `WEB_ASSET_CORE_PATH=../../web/dist WEB_UI_CONFIG_FILE=../../web/dist/config.json OCIS_INSECURE=true IDM_CREATE_DEMO_USERS=true ./bin/ocis server` (and make sure to adjust paths as necessary)
|
||||
|
||||
## Start oCIS
|
||||
|
||||
- open [https://localhost:9200](https://localhost:9200) and accept the certificate
|
||||
- when signing in, use one of the [available demo users](https://owncloud.dev/ocis/getting-started/demo-users/)
|
||||
- whenever code changes are made, you need to manually reload the browser page (no hot reload)
|
||||
|
||||
## Running tests
|
||||
|
||||
For testing, please refer to the [testing docs]({{< ref "testing/_index.md" >}})
|
||||
|
||||
30
web/docs/building.md
Normal file
30
web/docs/building.md
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
---
|
||||
title: "Building From Source"
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: 20
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocFilePath: building.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Building ownCloud Web
|
||||
|
||||
- Run `pnpm install` to install dependencies
|
||||
- Run `pnpm build` to build Web and all apps included in the `packages` folder
|
||||
|
||||
### Updating Dependencies
|
||||
|
||||
- **Do not** update dependencies by yourself but use the provided ones by the repo. When rebasing your local clone, you can always run `pnpm install` to be in sync with the defined dependencies.
|
||||
|
||||
## Building the Documentation
|
||||
|
||||
Note that the documentation is located in the `docs/` folder.
|
||||
|
||||
Note that you should always rebase your working branch if it is based on an older master. This ensures that any relevant documentation build changes have been applied and will not affect the building process.
|
||||
|
||||
### Details
|
||||
|
||||
For details of the documentation such as notes, setup and how-to's, see the [Documentation](https://owncloud.dev/ocis/build-docs/) section in the developer docs.
|
||||
11
web/docs/deployments/_index.md
Normal file
11
web/docs/deployments/_index.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "Deployments"
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: 55
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/deployments
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
Showcases of different scenarios of deploying ownCloud Web.
|
||||
288
web/docs/deployments/oc10-app.md
Normal file
288
web/docs/deployments/oc10-app.md
Normal file
@@ -0,0 +1,288 @@
|
||||
---
|
||||
title: "Deploy as an app in ownCloud Classic"
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: 1
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/deployments
|
||||
geekdocFilePath: oc10-app.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
|
||||
## Compatibility
|
||||
|
||||
Please note that the usage of Web UI and ownCloud Classic as backend is not recommended starting with version 7.1.0 of the Web UI. Therefore, this section only applies to versions < 7.1.0.
|
||||
|
||||
## Introduction
|
||||
|
||||
ownCloud Web is being deployed as an app to [ownCloud marketplace](https://marketplace.owncloud.com/) to enable easy integration into existing ownCloud Classic instances.
|
||||
After completing this setup, ownCloud Web will be available on `https://<your-owncloud-server>/index.php/apps/web`.
|
||||
|
||||
## Prerequisites
|
||||
- Running [ownCloud Classic server](https://owncloud.com/download-server/) with version 10.8
|
||||
- Installed [oauth2 app](https://marketplace.owncloud.com/apps/oauth2)
|
||||
- Command line access to your server
|
||||
|
||||
## Deploying ownCloud Web
|
||||
Download the [ownCloud Web app](https://marketplace.owncloud.com/apps/web) from the marketplace and enable it:
|
||||
```console
|
||||
occ market:install web
|
||||
```
|
||||
|
||||
## Configure oauth2
|
||||
Within the `Admin` page of ownCloud Classic, head into `User Authentication` and add a new client with arbitrary name (e.g. `ownCloud Web`) and redirection URL `https://<your-owncloud-server>/index.php/apps/web/oidc-callback.html`.
|
||||
|
||||
{{< figure src="/clients/web/static/oauth2.png" alt="Example OAuth2 entry" >}}
|
||||
|
||||
{{< hint >}}
|
||||
You can mark the ownCloud web client as `trusted` by clicking the respective checkbox so authorization after authentication gets omitted.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< hint >}}
|
||||
If you use OpenID Connect you need to add a new client for ownCloud Web to your identity provider instead.
|
||||
{{< /hint >}}
|
||||
|
||||
## Configure ownCloud Classic
|
||||
### Set ownCloud Web address
|
||||
To set the ownCloud Web address and to display ownCloud Web in the app switcher, add the following line into `config/config.php`:
|
||||
|
||||
```php
|
||||
'web.baseUrl' => 'https://<your-owncloud-server>/index.php/apps/web',
|
||||
```
|
||||
|
||||
### Configure link routing
|
||||
Administrators can optionally decide whether ownCloud Links (public and private links) should be provided by the Classic web interface or by ownCloud Web using the `web.rewriteLinks` option in `config/config.php`. The option defaults to `false` so that the links open in the Classic web interface. Setting it to `true` will redirect all links to ownCloud Web. To redirect all private and public links to ownCloud Web, add the following line into `config/config.php`:
|
||||
|
||||
```php
|
||||
'web.rewriteLinks' => true,
|
||||
```
|
||||
|
||||
### Make ownCloud Web the default web interface
|
||||
Administrators can optionally decide to make ownCloud Web the default web interface that users see after they log in to ownCloud. By default, the Classic web interface will be presented to users. To present ownCloud Web to users by default, add the following line into `config/config.php`:
|
||||
|
||||
```php
|
||||
'defaultapp' => 'web',
|
||||
```
|
||||
|
||||
{{< hint info >}}
|
||||
While it is possible to make ownCloud Web the default web interface, the decision should be carefully evaluated. Features are still being added to ownCloud Web and users might need to use the Classic web interface to do certain actions.
|
||||
{{< /hint >}}
|
||||
|
||||
## Configure ownCloud Web
|
||||
There are a few config values which need to be set in order for ownCloud Web to work correctly. Please copy the example config below into `config/config.json` and adjust it for your environment:
|
||||
|
||||
```json
|
||||
{
|
||||
"server" : "https://<your-owncloud-server>",
|
||||
"theme": "https://<your-owncloud-server>/index.php/apps/web/themes/owncloud/theme.json",
|
||||
"auth": {
|
||||
"clientId": "<client-id-from-oauth2>",
|
||||
"url": "https://<your-owncloud-server>/index.php/apps/oauth2/api/v1/token",
|
||||
"authUrl": "https://<your-owncloud-server>/index.php/apps/oauth2/authorize",
|
||||
"logoutUrl": "https://<your-owncloud-server>/index.php/logout"
|
||||
},
|
||||
"apps" : [
|
||||
"files",
|
||||
"preview",
|
||||
"search"
|
||||
],
|
||||
"applications" : [
|
||||
{
|
||||
"title": {
|
||||
"en": "Classic Design",
|
||||
"de": "Klassisches Design",
|
||||
"fr": "Design classique",
|
||||
"zh": "文件"
|
||||
},
|
||||
"icon": "swap-box",
|
||||
"url": "https://<your-owncloud-server>/index.php/apps/files"
|
||||
},
|
||||
{
|
||||
"icon": "settings-4",
|
||||
"menu": "user",
|
||||
"target": "_self",
|
||||
"title": {
|
||||
"de": "Einstellungen",
|
||||
"en": "Settings"
|
||||
},
|
||||
"url": "https://<your-owncloud-server>/index.php/settings/personal"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
{{< hint info >}}
|
||||
If any issues arise when trying to access the new design, a good start for debugging it is to run your `config.json` file through a json validator of your choice.
|
||||
{{< /hint >}}
|
||||
|
||||
|config parameter|explanation|
|
||||
|---|---|
|
||||
|server|ownCloud Classic server address|
|
||||
|theme|Theme to be used in ownCloud Web pointing to a json file inside of `themes` folder|
|
||||
|auth.clientId|Client ID received when adding ownCloud Web in the `User Authentication` section in `Admin`|
|
||||
|apps|List of internal extensions to be loaded|
|
||||
|applications|Additional apps and links to be displayed in the application switcher or in the user menu|
|
||||
|applications[0].title|Visible title in the application switcher or user menu, localizable|
|
||||
|applications[1].menu|Use `user` to move the menu item into the user menu. Defaults to app switcher|
|
||||
|
||||
{{< hint info >}}
|
||||
It is important that you don't edit or place the `config.json` within the app folder. If you do, the integrity check of the app will fail and raise warnings.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< hint >}}
|
||||
If you use OpenID Connect you need to replace the `"auth"` part with following configuration:
|
||||
|
||||
```json
|
||||
"openIdConnect": {
|
||||
"metadata_url": "<fqdn-of-the-identity-provider>/.well-known/openid-configuration",
|
||||
"authority": "<fqdn-of-the-identity-provider>",
|
||||
"client_id": "<client-id-from-the-identity-provider>",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile email"
|
||||
}
|
||||
```
|
||||
{{< /hint >}}
|
||||
|
||||
## Integrate ownCloud Classic features in ownCloud Web
|
||||
### Add links to the app switcher
|
||||
ownCloud Classic features that are not deeply integrated with the Classic UI (e.g., full screen apps) can be added to the ownCloud Web app switcher so that users can easily access them from ownCloud Web. You can use the following example and customize it according to your needs.
|
||||
|
||||
{{< hint info >}}
|
||||
All apps that are listed in the ownCloud Classic app switcher will be added as links to the app switcher of the new ownCloud Web automatically. All of those links will open in a new browser tab on click.
|
||||
{{< /hint >}}
|
||||
|
||||
To add new elements in the app switcher, paste the following into the `applications` section of `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": {
|
||||
"en": "Custom Groups",
|
||||
"de": "Benutzerdefinierte Gruppen"
|
||||
},
|
||||
"icon": "settings-4",
|
||||
"url": "https://<your-owncloud-server>/settings/personal?sectionid=customgroups"
|
||||
}
|
||||
```
|
||||
|
||||
{{< hint info >}}
|
||||
The URL in the example might need adaptations depending on the configuration of your ownCloud Classic. App switcher elements added this way will open the respective page in a new tab. This method can also be used to link external sites like Help pages or similar.
|
||||
{{< /hint >}}
|
||||
|
||||
### Add links to the user menu
|
||||
Just like adding links to the app switcher, you can also add links to the user menu.
|
||||
|
||||
```json
|
||||
{
|
||||
"icon": "settings-4",
|
||||
"menu": "user",
|
||||
"target": "_self",
|
||||
"title": {
|
||||
"de": "Hilfe",
|
||||
"en": "Help"
|
||||
},
|
||||
"url": "https://help-link.example"
|
||||
}
|
||||
```
|
||||
|
||||
This will add a link to the specified URL in the user menu. This way, the link will open in the same tab. If you instead want to open it in a new tab, just remove the line `"target": "_self",`.
|
||||
|
||||
### ONLYOFFICE
|
||||
For ONLYOFFICE there is a [native integration](https://github.com/ONLYOFFICE/onlyoffice-owncloud-web) available for ownCloud Web when it is used with ownCloud Classic. It fully integrates the ONLYOFFICE Document Editors and allows users to create and open documents right from ownCloud Web.
|
||||
|
||||
To be able to use ONLYOFFICE in ownCloud Web, it is required to run
|
||||
- ownCloud Classic >= 10.8
|
||||
- ownCloud Web >= 4.0.0
|
||||
- [ONLYOFFICE Connector for ownCloud Classic](https://marketplace.owncloud.com/apps/onlyoffice) >= 7.1.1
|
||||
|
||||
Make sure that ONLYOFFICE works as expected in the Classic UI and add the following to `config.json` to make it available in ownCloud Web:
|
||||
|
||||
```json
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "onlyoffice",
|
||||
"path": "https://<your-owncloud-server>/apps-external/onlyoffice/js/web/onlyoffice.js"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
{{< hint info >}}
|
||||
The URL in the example might need adaptations depending on the configuration of your ownCloud Classic.
|
||||
{{< /hint >}}
|
||||
|
||||
### Collabora Online
|
||||
For Collabora Online there is a native integration available for ownCloud Web when it is used with ownCloud Classic. It fully integrates the Collabora Online Document Editors and allows users to create and open documents right from ownCloud Web.
|
||||
|
||||
To be able to use Collabora Online in ownCloud Web, it is required to run
|
||||
- ownCloud Classic >= 10.8
|
||||
- ownCloud Web >= 4.0.0
|
||||
- [Collabora Online Connector for ownCloud Classic](https://marketplace.owncloud.com/apps/richdocuments) >= 2.7.0
|
||||
|
||||
Make sure that Collabora Online works as expected in the Classic UI and add the following to `config.json` to make it available in ownCloud Web:
|
||||
|
||||
```json
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "richdocuments",
|
||||
"path": "https://<your-owncloud-server>/apps/richdocuments/js/richdocuments.js"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
{{< hint info >}}
|
||||
The URL in the example might need adaptations depending on the configuration of your ownCloud Classic.
|
||||
{{< /hint >}}
|
||||
|
||||
## Additional configuration for certain core apps
|
||||
There is additional configuration available for certain core apps. You can find them listed below.
|
||||
|
||||
### Preview app
|
||||
In case the backend has additional preview providers configured there is no mechanism, yet, to announce those to the `Preview` app in ownCloud Web. As an intermediate solution you can add the additional supported mimeTypes to the `Preview` app by following these steps:
|
||||
1. Remove the `"preview"` string from the `"apps"` section in your `config.json` file
|
||||
2. Add the following config to your `config.json` file:
|
||||
```json
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "preview",
|
||||
"path": "web-app-preview",
|
||||
"config": {
|
||||
"mimeTypes": ["image/tiff", "image/webp"]
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
If you already have an `"external_apps"` section, just add the preview app to the list. Please adjust the `"mimeTypes"` list according to your additional preview providers. See https://github.com/owncloud/files_mediaviewer#supporting-more-media-types for advise on how to add preview providers to the backend.
|
||||
|
||||
### Text-Editor app
|
||||
The `text-editor` app provides a list of file extensions that the app is associated with, both for opening files and for creating new files.
|
||||
By default, only `.txt` and `.md` files appear in the file creation menu and offer the text-editor as default app on a left mouse click
|
||||
in the file list. For other file types the text-editor app only appears in the right mouse click context menu. In case you want to change this
|
||||
default set of primary file extensions for the text-editor you can overwrite it as follows:
|
||||
1. Remove the `"text-editor"` string from the `"apps"` section in your `config.json` file
|
||||
2. Add the following config to your `config.json` file:
|
||||
```json
|
||||
"external_apps": [
|
||||
{
|
||||
"id": "text-editor",
|
||||
"path": "web-app-text-editor",
|
||||
"config": {
|
||||
"primaryExtensions": ["txt", "yaml"]
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
With the above example config the text editor will offer creation of new files for `.txt` and `.yaml` files instead of `.txt` and `.md` files.
|
||||
Also, a left mouse click on any `.txt` or `.yaml` file will open the respective file in the text-editor app. In this example, `.md` files would
|
||||
not be opened in the text-editor by default anymore, but the text-editor will would appear in the context menu for the file as alternative app.
|
||||
|
||||
If you already have an `"external_apps"` section, just add the preview app to the list. Please adjust the `"mimeTypes"` list according to your additional preview providers. See https://github.com/owncloud/files_mediaviewer#supporting-more-media-types for advise on how to add preview providers to the backend.
|
||||
|
||||
{{< hint info >}}
|
||||
The reason why the app needs to be ported from the `apps` section to the `external_apps` section is that only the `external_apps` support additional configuration. There are plans to change the configuration of apps to give you a coherent admin experience in that regard.
|
||||
{{< /hint >}}
|
||||
|
||||
## Accessing ownCloud Web
|
||||
After following all the steps, you should see a new entry in the application switcher called `New Design` which points to the ownCloud web.
|
||||
|
||||
{{< figure src="/clients/web/static/application-switcher-oc10.jpg" alt="ownCloud Classic application switcher" >}}
|
||||
16
web/docs/development/_index.md
Normal file
16
web/docs/development/_index.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: 'Development'
|
||||
date: 2022-01-28T00:00:00+00:00
|
||||
weight: 50
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
This section is a guide about the development of ownCloud Web **core**, **apps** and **extensions**.
|
||||
This includes **tooling**, **conventions** and the **repo structure**.
|
||||
|
||||
It is of interest for you if you want to contribute to ownCloud Web or develop your own apps and extensions.
|
||||
63
web/docs/development/conventions.md
Normal file
63
web/docs/development/conventions.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "Conventions"
|
||||
date: 2022-01-28T00:00:00+00:00
|
||||
weight: 20
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocFilePath: conventions.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
This is a collection of tips and conventions to follow when working on the [ownCloud web frontend](https://github.com/owncloud/web).
|
||||
Since it is a living document, please open a PR if you find something missing.
|
||||
|
||||
## Contributing to ownCloud Web
|
||||
|
||||
Everyone is invited to contribute. Simply fork the [codebase](https://github.com/owncloud/web/),
|
||||
check the [issues](https://github.com/owncloud/web/issues?q=is%3Aopen+is%3Aissue+label%3ATopic%3Agood-first-issue)
|
||||
for a suitable one and open a pull request!
|
||||
|
||||
### Linting and Tests
|
||||
|
||||
To make sure your pull request can be efficiently reviewed and won't need a lot of changes down the road, please run the linter and
|
||||
the unit tests via `pnpm lint --fix` and `pnpm test:unit` locally. Our [CI](https://drone.owncloud.com/owncloud/web) will run on
|
||||
pull requests and report back any problems after that. For a further introduction on how we handle testing, please head to
|
||||
the [testing docs]({{< ref "../testing/_index.md" >}}).
|
||||
|
||||
### Changelog Items
|
||||
|
||||
In our project, we follow [SemVer](https://semver.org/) and keep a changelog for every change that influences the user experience (where
|
||||
"users" can be admins, end-users and developers).
|
||||
Some changes, like refactoring, updating dependencies, writing documentation or adding tests don't require a changelog item.
|
||||
|
||||
Please add a changelog item to the `changelog/unreleased/` folder, referencing the issue and pull request numbers, following
|
||||
the [changelog item template](https://github.com/owncloud/web/blob/master/changelog/TEMPLATE).
|
||||
|
||||
## Code Conventions
|
||||
|
||||
### Early Returns
|
||||
|
||||
We're trying to stick with early returns in our code to make it more performant and simpler to reason about it.
|
||||
|
||||
### Translations
|
||||
|
||||
Use the `v-text` directive in combination with `$gettext` (or a variation of it) inside HTML tags (instead of
|
||||
a `<translate tag="h1">` or similar) in order to make reasoning about the DOM tree easier.
|
||||
|
||||
### TypeScript
|
||||
|
||||
We're using TypeScript, which allows us to catch bugs at transpile time. Clean types make sure our IDEs can support us
|
||||
in reasoning about our (ever growing, complex) codebase.
|
||||
|
||||
### Vue 3 and Composition API
|
||||
|
||||
We've migrated from Vue 2 to Vue 3 late in 2022 and since then have been investing continuous efforts to move away from the Vue options API
|
||||
in favor of the Vue composition API. The `web-pkg` helper package provides quite some composables which will help you in
|
||||
app & extension development, so we encourage you to make use of the Vue composition API as well, even outside of the
|
||||
ownCloud Web repository.
|
||||
|
||||
### Dependencies
|
||||
|
||||
To keep the bundle size small and reduce the risk of introducing security problems for our users, we try to limit
|
||||
the amount of dependencies in our code base and keep them as up-to-date as possible.
|
||||
132
web/docs/development/repo-structure.md
Normal file
132
web/docs/development/repo-structure.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
title: 'Repo Structure and (Published) Packages'
|
||||
date: 2022-01-28T00:00:00+00:00
|
||||
weight: 30
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocFilePath: repo-structure.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Repository Structure
|
||||
|
||||
From a developer's perspective, the most important parts of the [ownCloud Web repo](https://github.com/owncloud/web) are the following files and folders:
|
||||
|
||||
### dev Folder and docker-compose.yml File
|
||||
|
||||
The `/dev` folder contains all the configuration files that are needed in the `docker-compose.yml` file. This docker compose stack
|
||||
contains all the backend and testing related infrastructure that is needed for an out-of-the-box usable localhost development setup,
|
||||
as described in the [tooling section]({{< ref "tooling.md" >}}).
|
||||
|
||||
### docs Folder
|
||||
|
||||
Within the `/docs` folder you will find all the documentation source documents that get published to the [dev docs](https://owncloud.dev/clients/web/).
|
||||
|
||||
### packages Folder
|
||||
|
||||
We're using the [ownCloud Web repo](https://github.com/owncloud/web) as a mono repo. It contains a variety of packages. Some of them get
|
||||
published to [npmjs.com](https://npmjs.com), others define the core packages, apps and extensions that are the foundation of
|
||||
the `ownCloud Web` release artifact.
|
||||
|
||||
Having these packages side by side within the `/packages` folder of the repo is possible because of a `pnpm` feature called `Workspaces`. You can learn more about that by visiting the [pnpm docs](https://pnpm.io/workspaces).
|
||||
|
||||
### tests Folder
|
||||
|
||||
We're using the [Playwright](https://playwright.dev) for UI testing. The UI tests are located in the `/tests/e2e`
|
||||
|
||||
You're more than welcome to make a pull request and adjust this section of the docs accordingly. :-)
|
||||
You can read more about testing in our [testing section]({{< ref "../testing/_index.md" >}})
|
||||
|
||||
### package.json File
|
||||
|
||||
This is probably no surprise: the root level `package.json` file defines the project information, build scripts, dependencies and some more details.
|
||||
Each package in `/packages` can and most likely will contain another `package.json` which does the same for the respective package.
|
||||
|
||||
### vite.config.ts
|
||||
|
||||
We're working with [Vite](https://vitejs.dev) as a local development server and build tool. `vite.config.ts` is the main configuration file for that.
|
||||
You can read more about the usage in our [tooling section]({{< ref "tooling.md" >}}).
|
||||
|
||||
## (Published) Packages
|
||||
|
||||
Each package in the `/packages` folder can - not exclusively, but most commonly - consist of
|
||||
|
||||
- source code (`/src`),
|
||||
- unit tests (`/tests`),
|
||||
- translations (`/l10n`) and
|
||||
- a `package.json` file for package specific details and dependencies.
|
||||
|
||||
### Code Style and Build Config
|
||||
|
||||
Some of our packages in `/packages` are pure helper packages which ensure a common code style and build configuration for all our
|
||||
internal (mono repo) and external packages. We encourage you to make use of the very same packages. This helps the community
|
||||
understand code more easily, even when coming from different developers or vendors in the ownCloud Web ecosystem.
|
||||
|
||||
Namely those packages are
|
||||
|
||||
- `/packages/babel-preset`
|
||||
- `/packages/eslint-config`
|
||||
- `/packages/extension-sdk`
|
||||
- `/packages/prettier-config`
|
||||
- `/packages/tsconfig/`
|
||||
|
||||
### ownCloud Design System
|
||||
|
||||
The ownCloud Design System (`/packages/design-system`) is a collection of components, design tokens and styles which ensure a
|
||||
unique and consistent look and feel and branding throughout the ownCloud Web ecosystem. We hope that you use it, too, so that your
|
||||
very own apps and extensions will blend in with all the others. Documentation and code examples can be found in
|
||||
the [design system documentation](https://owncloud.design).
|
||||
|
||||
The ownCloud Design System is a standalone project, but to make development easier we have the code in our mono repo.
|
||||
We're planning to publish it on npmjs.com as [@ownclouders/design-system](https://www.npmjs.com/package/@ownclouders/design-system)
|
||||
as soon as possible. Since it's bundled with ownCloud Web, you should not bundle it with your app or extension.
|
||||
|
||||
### web-client
|
||||
|
||||
The client package (`/packages/web-client`) serves as an abstraction layer for the various ownCloud APIs, like
|
||||
[LibreGraph](https://owncloud.dev/apis/http/graph/), [WebDAV](https://doc.owncloud.com/server/next/developer_manual/webdav_api/) and
|
||||
[OCS](https://doc.owncloud.com/server/next/developer_manual/core/apis/ocs-capabilities.html). The package provides TypeScript
|
||||
interfaces for various entities (like files, folders, shares and spaces) and makes sure that raw API responses are properly
|
||||
transformed so that you can deal with more useful objects. The web-client package gets published
|
||||
on npmjs.com as [@ownclouders/web-client](https://www.npmjs.com/package/@ownclouders/web-client).
|
||||
|
||||
Dedicated documentation for the `web-client` package is not available, yet, since our extension system is still work in progress. However, the package's [README.md](https://github.com/owncloud/web/blob/master/packages/web-client/README.md) gives you a few examples on how to use it.
|
||||
|
||||
### web-pkg
|
||||
|
||||
The web-pkg package (`/packages/web-pkg`) is a collection of opinionated components, composables, types and other helpers that aim
|
||||
at making your app and extension developer experience as easy and seamless as possible. The web-pkg package gets published on
|
||||
npmjs.com as [@ownclouders/web-pkg](https://www.npmjs.com/package/@ownclouders/web-pkg).
|
||||
|
||||
Dedicated documentation for the `web-pkg` package is not available, yet, since our extension system is still work in progress.
|
||||
|
||||
### web-runtime
|
||||
|
||||
At the very heart of ownCloud Web, the `web-runtime` is responsible for dependency injection, app bootstrapping, configuration,
|
||||
authentication, data preloading and much more.
|
||||
It is very likely that you will never get in touch with it as most of the developer-facing features are exposed via `web-pkg`. If you
|
||||
have more questions about this package, please join our [public chat](https://matrix.to/#/#ocis:matrix.org) and simply ask
|
||||
or write an issue in our [issue tracker](https://github.com/owncloud/web/issues).
|
||||
|
||||
### Standalone Core Apps
|
||||
|
||||
Both `web-app-admin-settings` and `web-app-files` are standalone apps which are bundled with the default ownCloud Web release artifact.
|
||||
|
||||
### Viewer and Editor Apps
|
||||
|
||||
Apps which fall into the categories `viewer` or `editor` can be opened from the context of a file or folder. This mostly happens from
|
||||
within the `files` app. We currently bundle the following apps with the default ownCloud Web release artifact:
|
||||
|
||||
- `web-app-epub-reader` a simple reader for `.epub` files
|
||||
- `web-app-external` an iframe integration of all the apps coming from the [app provider](https://owncloud.dev/services/app-provider/)
|
||||
(e.g. OnlyOffice, Collabora Online and others)
|
||||
- `web-app-pdf-viewer` a viewer for `.pdf` files, which relies on native PDF rendering support from the browser
|
||||
- `web-app-preview` a viewer for various media files (audio / video / image formats)
|
||||
- `web-app-text-editor` a simple editor for `.txt`, `.md` and other plain text files
|
||||
|
||||
If you're interested in writing your own viewer or editor app for certain file types, please get in touch with us for more info.
|
||||
|
||||
### Testing
|
||||
|
||||
Additional unit testing code lives in `test-helpers`.
|
||||
52
web/docs/development/tooling.md
Normal file
52
web/docs/development/tooling.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: 'Tooling'
|
||||
date: 2022-01-28T00:00:00+00:00
|
||||
weight: 40
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/development
|
||||
geekdocFilePath: tooling.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Packaging
|
||||
|
||||
Web is using [pnpm](https://pnpm.io/) as package manager and [vite](https://vitejs.dev/) as build tool. The latter is built on top of [rollup](https://rollupjs.org/) and brings some additional features such as instant hot-reloading.
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- docker
|
||||
- docker-compose (if not already included in your docker installation)
|
||||
- pnpm
|
||||
- node
|
||||
|
||||
If you’re not using Docker Desktop, you might have to modify your `/etc/hosts` and add `127.0.0.1 host.docker.internal` to make `host.docker.internal` links work.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
After cloning the source code, install the dependencies via `pnpm install`.
|
||||
|
||||
### Starting the Server
|
||||
|
||||
You can start the server by running `docker-compose up ocis`.
|
||||
|
||||
Note that the container needs a short while to start because it is waiting for `tika` to be initialized. This is the case as soon as the `tika-service` container has stopped running.
|
||||
|
||||
### Building and Accessing Web
|
||||
|
||||
After the docker containers are running (and `tika` is being initialized), run `pnpm build:w` to build Web. This also includes hot-reloading after changes you make, although it will take a while to rebuild the project. See down below for some details on how to enable instant hot-reloading.
|
||||
|
||||
Now you can access Web via https://host.docker.internal:9200.
|
||||
|
||||
### Using Instant Hot-Reload via Vite
|
||||
|
||||
To work with instant hot-reloading, you can also build Web by running `pnpm vite`. The port to access Web is slightly different then: https://host.docker.internal:9201. Also note that the initial page load may take a bit longer than usual. This is normal and to be expected.
|
||||
|
||||
### Running Web with oC10
|
||||
|
||||
Older versions of Web (< 7.1.0) also support running oC10 as server. The development setup is nearly the same as mentioned above, the only differences are:
|
||||
|
||||
* The server can be started via `docker-compose up oc10`
|
||||
* The server port is `8080` (`8081` when running Web via `pnpm vite:oc10`)
|
||||
165
web/docs/embed-mode/_index.md
Normal file
165
web/docs/embed-mode/_index.md
Normal file
@@ -0,0 +1,165 @@
|
||||
---
|
||||
title: 'Embed Mode'
|
||||
date: 2023-10-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/embed-mode
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
The ownCloud Web can be consumed by another application in a stripped down version called "Embed mode". This mode is supposed to be used in the context of selecting or sharing resources. If you're looking for even more minimalistic approach, you can take a look at the [File picker](https://owncloud.dev/integration/file_picker/).
|
||||
|
||||
## Getting started
|
||||
|
||||
To integrate ownCloud Web into your application, add an iframe element pointing to your ownCloud Web deployed instance with additional query parameter `embed=true`.
|
||||
|
||||
```html
|
||||
<iframe src="<web-url>?embed=true"></iframe>
|
||||
```
|
||||
|
||||
## Communication
|
||||
|
||||
To establish seamless cross-origin communication between the embedded instance and the parent application, our approach involves emitting events using the `postMessage` method. These events can be conveniently captured by utilizing the standard `window.addEventListener('message', listener)` pattern.
|
||||
|
||||
### Target origin
|
||||
|
||||
By default, the `postMessage` method does not specify the `targetOrigin` parameter. However, it is recommended best practice to explicitly pass in the URI of the iframe origin (not the parent application). To enhance security, you can specify this value by modifying the config option `options.embed.messagesOrigin`.
|
||||
|
||||
### Events
|
||||
|
||||
To maintain uniformity and ease of handling, each event encapsulates the same structure within its payload: `{ name: string, data: any }`.
|
||||
|
||||
| Name | Data | Description |
|
||||
| --- | --- | --- |
|
||||
| **owncloud-embed:select** | Resource[] | Gets emitted when user selects resources or location via the select action |
|
||||
| **owncloud-embed:share** | string[] | **DEPRECATED**: Gets emitted when user selects resources and shares them via the "Share links" action. Use `owncloud-embed:share-links` instead. |
|
||||
| **owncloud-embed:share-links** | Array<{ url: string; password?: string }> | Gets emitted when user selects resources and shares them via the "Share link(s)" or "Share link(s) and password(s)" action. Each object contains the link URL and optionally the password (when shared with password). |
|
||||
| **owncloud-embed:cancel** | null | Gets emitted when user attempts to close the embedded instance via "Cancel" action |
|
||||
|
||||
### Example
|
||||
|
||||
#### Selecting resources
|
||||
|
||||
```html
|
||||
<iframe src="https://my-owncloud-web-instance?embed=true"></iframe>
|
||||
|
||||
<script>
|
||||
function selectEventHandler(event) {
|
||||
if (event.data?.name !== 'owncloud-embed:select') {
|
||||
return
|
||||
}
|
||||
|
||||
const resources = event.data.data
|
||||
|
||||
doSomethingWithSelectedResources(resources)
|
||||
}
|
||||
|
||||
window.addEventListener('message', selectEventHandler)
|
||||
</script>
|
||||
```
|
||||
|
||||
#### Sharing links with password
|
||||
|
||||
```html
|
||||
<iframe src="https://my-owncloud-web-instance?embed=true"></iframe>
|
||||
|
||||
<script>
|
||||
function shareLinksEventHandler(event) {
|
||||
if (event.data?.name !== 'owncloud-embed:share-links') {
|
||||
return
|
||||
}
|
||||
|
||||
const links = event.data.data // Array<{ url: string; password?: string }>
|
||||
|
||||
links.forEach(link => console.log("Link", link.url, "Password", link.password))
|
||||
|
||||
doSomethingWithSharedLinks(links)
|
||||
}
|
||||
|
||||
window.addEventListener('message', shareLinksEventHandler)
|
||||
</script>
|
||||
```
|
||||
|
||||
## Location picker
|
||||
|
||||
By default, the Embed mode allows users to select resources. In certain cases (e.g. uploading a file), this needs to be changed to allow selecting a location. This can be achieved by running the embed mode with additional parameter `embed-target=location`. With this parameter, resource selection is disabled and the selected resources array always includes the current folder as the only item.
|
||||
In special scenarios you also want the user to set a file name, this can be achieved by adding the `embed-choose-file-name=true` parameter, or if you also want to set a default file name, you can use `embed-choose-file-name-suggestion=my file.text`.
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
```html
|
||||
<iframe src="https://my-owncloud-web-instance?embed=true&embed-target=location"></iframe>
|
||||
|
||||
<script>
|
||||
function selectEventHandler(event) {
|
||||
if (event.data?.name !== 'owncloud-embed:select') {
|
||||
return
|
||||
}
|
||||
|
||||
const resources = event.data.data[0]
|
||||
|
||||
doSomethingWithSelectedResources(resources)
|
||||
}
|
||||
|
||||
window.addEventListener('message', selectEventHandler)
|
||||
</script>
|
||||
```
|
||||
|
||||
## File picker
|
||||
|
||||
The File Picker mode in ownCloud Web is designed for embedding an interface that allows users to pick a single file.
|
||||
This mode can be configured to restrict the file types that users can select. To enable the File Picker mode, you need
|
||||
to include the embed-target=file query parameter in the iframe URL. Furthermore, you can specify allowed file types
|
||||
using the embed-file-types parameter. The file types can be specified using file extensions, MIME types, or a
|
||||
combination of both. If the embed-file-types parameter is not provided, all file types will be selectable by default.
|
||||
|
||||
### Example
|
||||
|
||||
```html
|
||||
|
||||
<iframe src="https://my-owncloud-web-instance?embed=true&embed-target=file&embed-file-types=txt,image/png"></iframe>
|
||||
|
||||
<script>
|
||||
function selectEventHandler(event) {
|
||||
if (event.data?.name !== 'owncloud-embed:file-pick') {
|
||||
return
|
||||
}
|
||||
|
||||
const file = event.data.data
|
||||
|
||||
doSomethingWithPickedFile(file)
|
||||
}
|
||||
|
||||
window.addEventListener('message', selectEventHandler)
|
||||
</script>
|
||||
```
|
||||
|
||||
## Delegate authentication
|
||||
|
||||
If you already have a valid `access_token` that can be used to call the API from within the Embed mode and do not want to force the user to authenticate again, you can delegate the authentication. Delegating authentication will disable internal login form in ownCloud Web and will instead use events to obtain the token and update it.
|
||||
|
||||
### Configuration
|
||||
|
||||
To allow authentication delegation, you need to set the config option `options.embed.delegateAuthentication` to `true`. This can be achieved via query parameter `embed-delegate-authentication=true`. Because we are using the `postMessage` method to communicate across different origins, it is best practice to verify that the event originated from a known origin and not from some malicious site. We highly recommend to allow this check in production environments. You can enable it by setting the config option `options.embed.delegateAuthenticationOrigin` via query parameter `embed-delegate-authentication-origin=my-origin`. The value of this parameter will be compared against the `MessageEvent.origin` value and if they do not match, the token will be rejected.
|
||||
|
||||
### Events
|
||||
|
||||
#### Opening Embed mode
|
||||
|
||||
As already mentioned, we're using the `postMessage` method to allow communication between the Embed mode and the parent application. When the Embed mode is opened for the first time, the user gets redirected to the `/web-oidc-callback` page where a message with payload `{ name: 'owncloud-embed:request-token', data: undefined }` is sent to request the `access_token` from the parent application. The parent application should set an event listener before opening the Embed mode and once received, it should send a message with payload `{ name: 'owncloud-embed:update-token', data: { access_token: '<bearer-token>' } }`. Once the Embed mode receives this message, it will save the token in the application state and will automatically authenticate the user.
|
||||
|
||||
{{< hint info >}}
|
||||
When passing the token in the message payload, use only the token itself without `Bearer ` string as that will be added automatically in the Embed mode.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< hint info >}}
|
||||
To save unnecessary duplication of messages with only different names, the name in the message payload above is exactly the same for both the initial authentication and subsequent token updates after renewal.
|
||||
{{< /hint >}}
|
||||
|
||||
#### Updating the token
|
||||
|
||||
When authentication is delegated, the automatic renewal of the token inside of ownCloud Web is disabled. In order to update the token, a listener is created which awaits a message with payload `{ name: 'owncloud-embed:update-token', data: { access_token: '<bearer-token>' } }`. The token will then be replaced inside of the Embed mode automatically.
|
||||
172
web/docs/extension-system/_index.md
Normal file
172
web/docs/extension-system/_index.md
Normal file
@@ -0,0 +1,172 @@
|
||||
---
|
||||
title: 'Extension System'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Concepts and Building Blocks
|
||||
|
||||
ownCloud Web can be extended through various entry points with custom **apps** and **extensions**.
|
||||
|
||||
### Distinction between Apps and Extensions
|
||||
|
||||
An Application in the context of ownCloud Web is an artifact which can be installed in an ownCloud Infinite Scale instance.
|
||||
It serves two main purposes:
|
||||
1. It makes the full app viewport (everything below the top bar) available to the application developer for any custom
|
||||
application code. This includes the ability to define views with routes, navigation items for the left sidebar, and more.
|
||||
2. Through the `extensions` key in the application interface you can register extensions of any extension type. Those extensions
|
||||
are then available in standardized extension points. Additionally, they can be queried from the extension registry for
|
||||
your own purposes.
|
||||
|
||||
Both parts are optional. This means that an application can be a file editor without any custom extensions, or even contain
|
||||
no custom application code at all and only host extensions to be registered in the extension registry, or a combination of both.
|
||||
|
||||
### Examples
|
||||
|
||||
You can find open source examples for apps and extensions in our [curated list of ownCloud apps and extensions](https://github.com/owncloud/awesome-ocis).
|
||||
Feel free to contribute or just be inspired for your own apps or extensions.
|
||||
|
||||
### Apps
|
||||
|
||||
To get started, define a `src/index.ts`. Below is the most basic example of its content:
|
||||
|
||||
```typescript
|
||||
// Install '@ownclouders/web-pkg' as a devDependency first (only relevant for types and autocompletion, dependency is already provided by ownCloud Web at runtime).
|
||||
import {
|
||||
AppWrapperRoute,
|
||||
ApplicationFileExtension,
|
||||
defineWebApplication
|
||||
} from '@ownclouders/web-pkg'
|
||||
|
||||
|
||||
export default defineWebApplication({
|
||||
setup({ applicationConfig }) {
|
||||
// Here, you have access to the full injection context, meaning you can use all composables that we provide via web-pkg
|
||||
|
||||
// Needs to be unique within all installed applications in any ownCloud web instance
|
||||
// Should be short, unique and expressive as it is used as prefix on all routes within your application
|
||||
const appId = 'your-extension'
|
||||
|
||||
// See extensions section below
|
||||
const extensions = [
|
||||
...
|
||||
]
|
||||
|
||||
// See details below
|
||||
const navItems = [
|
||||
...
|
||||
]
|
||||
|
||||
// See details below
|
||||
const routes = [
|
||||
...
|
||||
]
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Your application name'),
|
||||
id: appId,
|
||||
icon: 'aliens', // See https://owncloud.design/#/Design%20Tokens/IconList for available options
|
||||
},
|
||||
extensions,
|
||||
navItems,
|
||||
routes
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
By defining an application via `defineWebApplication` you can provide the following:
|
||||
- `appInfo` - the application metadata, which is used to make the application available via the app switcher and the app registry.
|
||||
- `navItems` - the statically defined navigation items for the left sidebar. Only gets rendered when more than 1 navigation item exists at runtime.
|
||||
Additional dynamic navigation items can be registered via the extension registry.
|
||||
- `routes` - the routes to the different views of your application. May be referenced within the `navItems`. Authentication requirements can be defined per item.
|
||||
- `extensions` - the extensions to be registered in the extension registry. For more details see the `Extensions` section below.
|
||||
|
||||
If you want to learn how to implement an app for viewing and editing specific file types, please consult the [relevant documentation]({{< ref "viewer-editor-apps.md" >}}) for detailed instructions and guidance.
|
||||
|
||||
To learn how to integrate an app into ownCloud Web, please refer to the "Web Apps" section of the Web service docs ("Services" > "Web").
|
||||
|
||||
### Extensions
|
||||
|
||||
In contrast to applications, extensions usually have a rather small scope and dedicated functionality.
|
||||
|
||||
#### Extension Registry
|
||||
|
||||
The globally available extension registry provided by the ownCloud Web runtime can be used to both register and query extensions. All extensions
|
||||
which are being made available via an `app` get registered in the extension registry automatically. In your custom application code you can
|
||||
then query any of the available extensions by providing an `extensionPoint` entity. Throughout the ownCloud Web platform
|
||||
and most prominently also in the `files` app we have defined some extension points which automatically use certain extensions, see the
|
||||
`Extension Points` section below.
|
||||
|
||||
#### Extension Types
|
||||
|
||||
For building an extension you can choose from the types predefined by the ownCloud Web extension system. See the full list of available extension types below.
|
||||
|
||||
1. `ActionExtension` (type `action`) - An extension that can register `Action` items which then get shown in various places (e.g. context menus, batch actions), depending on the
|
||||
extension points referenced in the extension respectively. Most commonly used for file and folder actions (e.g. copy, rename, delete, etc.). For details, please refer to the [action docs]({{< ref "extension-types/actions.md" >}}).
|
||||
2. `SearchExtension` (type `search`) - An extension that can register additional search providers. For details, please refer to the [search docs]({{< ref "extension-types/search.md" >}}).
|
||||
3. `SidebarNavExtension` (type `sidebarNav`) - An extension that can register additional navigation items for the left sidebar. These can be scoped to specific apps, and programmatically enabled/disabled.
|
||||
For details, please refer to the [sidebar nav docs]({{< ref "extension-types/left-sidebar-menu-item.md" >}}).
|
||||
4. `SidebarPanelExtension`, (type `sidebarPanel`) - An extension that can register panels for the right sidebar. For details, please refer to the [sidebar panel docs]({{< ref "extension-types/right-sidebar-panels.md" >}}).
|
||||
5. `FolderViewExtension` (type `folderView`) - An extension that can register additional ways of displaying the content of a folder (resources like spaces, folders or files) to the user.
|
||||
For details, please refer to the [folder view docs]({{< ref "extension-types/folder-view.md" >}}).
|
||||
6. `CustomComponentExtension` (type `customComponent`) - An extension that can register a custom component for a render target. For details, please refer to the
|
||||
[custom component docs]({{< ref "extension-types/custom-components.md" >}})
|
||||
|
||||
You're free to introduce your own extension types within your application code and use the extension registry to query the available ones. However, if you have the impression
|
||||
that an important extension type is missing and would be beneficial for the platform, please reach out to us by opening a [GitHub issue](https://github.com/owncloud/web/issues/new/choose).
|
||||
|
||||
#### Extension Base Configuration
|
||||
|
||||
Any extension is required to define at least an `id` and a `type` in order to fulfill the generic `Extension` interface.
|
||||
|
||||
The `id` is supposed to be unique throughout the ownCloud Web ecosystem. In order to keep `id`s readable for humans we didn't want to enforce uniqueness through e.g. uuids.
|
||||
Instead, we chose to use dot-formatted namespaces like e.g. `com.github.owncloud.web.files.search`. We'd like to encourage you to follow the same format for your own extensions.
|
||||
|
||||
For the `type` you can choose from the ones listed above or define a custom one.
|
||||
|
||||
In addition, you can also pass optional `extensionPointIds` to further limit the usage of an extension. With the right click context menu and the batch actions being
|
||||
two different extension points, this could mean that a file action extension is only allowed in the context menu, but not in the batch actions.
|
||||
You can find predefined extension point ids in the extension points section below.
|
||||
|
||||
#### Extension Points
|
||||
|
||||
There are standardized components and places where extensions are being used automatically. The following ones are currently provided by the ownCloud Web runtime or
|
||||
the `files` app. If you decide to develop an extension which fulfills the type and registers itself for the extensionPointId of the respective extension point,
|
||||
your extension will be used automatically.
|
||||
|
||||
1. Left Sidebar for Navigation. ExtensionPointId `app.${appName}.navItems` (dynamically created for each app). Mounts extensions of type `sidebarNav`.
|
||||
2. Global top bar
|
||||
1. Center area. ExtensionPointId `app.runtime.header.center`. Mounts extensions of type `customComponent`.
|
||||
2. Progress bar for the global loading state. ExtensionPointId `app.runtime.global-progress-bar`. Mounts a single extensions of type `customComponent`. If multiple exist, the user can choose via the account page.
|
||||
3. Files app
|
||||
1. Right sidebar. ExtensionPointId `app.files.sidebar`. Mounts extensions of type `sidebarPanel`. Used in any file(s) context (files app, file viewer apps, file editor apps).
|
||||
2. Folder views for regular folders. ExtensionPointId `app.files.folder-views.folder`. Mounts extensions of type `folderView`.
|
||||
3. Folder views for the project spaces overview. ExtensionPointId `app.files.folder-views.project-spaces`. Mounts extensions of type `folderView`.
|
||||
4. Folder views for the favorites page. ExtensionPointId `app.files.folder-views.favorites`. Mounts extensions of type `folderView`.
|
||||
5. Right click context menu. ExtensionPointId `global.files.context-actions`. Mounts extensions of type `action`.
|
||||
6. Batch actions in the app bar above file lists. ExtensionPointId `global.files.batch-actions`. Mounts extensions of type `action`.
|
||||
7. Default actions (left click) on a file. ExtensionPointId `global.files.default-actions`. Mounts extensions of type `action`.
|
||||
8. Upload menu. ExtensionPointId `app.files.upload-menu`. Mounts extensions of type `action`.
|
||||
9. Quick actions. ExtensionPointId `app.files.quick-actions`. Mounts extensions of type `action`.
|
||||
4. Global search providers. ExtensionPointId `app.search.providers`. Utilizes extensions of type `search` as search engines for the search input in the global top bar.
|
||||
|
||||
#### User Preferences for Extensions
|
||||
|
||||
To allow users to configure extensions, extension points can define user preferences. User preferences are defined as an object on the extension point configuration.
|
||||
Whenever an extension point declares to accept user preferences, it will get listed with a dropdown on the Preferences page (reachable via top right user menu).
|
||||
The user can then select one out of all the extensions which have been registered for this extension point.
|
||||
|
||||
### Helpful packages
|
||||
|
||||
We currently offer the following packages that can be integrated into your app, providing useful utilities and types.
|
||||
|
||||
- `web-client` - This package serves as an abstraction layer between the server APIs and an app or extension. It converts raw API data into objects with helpful types and utilities. For details, please refer to the package's [README.md](https://github.com/owncloud/web/blob/master/packages/web-client/README.md).
|
||||
- `web-pkg` - This package provides utilities, most importantly a variety of components and composables, that can be useful when developing apps and extensions. For details, please refer to the package's [README.md](https://github.com/owncloud/web/blob/master/packages/web-pkg/README.md).
|
||||
12
web/docs/extension-system/extension-types/_index.md
Normal file
12
web/docs/extension-system/extension-types/_index.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "Extension Types"
|
||||
date: 2024-01-25T00:00:00+00:00
|
||||
weight: 50
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
This section is a guide about the different predefined extension types of ownCloud Web. Please refer to the respective
|
||||
subpages to learn more about the individual extension types.
|
||||
96
web/docs/extension-system/extension-types/actions.md
Normal file
96
web/docs/extension-system/extension-types/actions.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: 'Action Extensions'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: actions.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Action extension type
|
||||
|
||||
Actions are one of the possible extension types. Registered actions get rendered in various places across the UI, depending on their scope and targets.
|
||||
|
||||
### Configuration
|
||||
|
||||
This is what the `ActionExtension` interface looks like:
|
||||
|
||||
```typescript
|
||||
interface ActionExtension {
|
||||
id: string
|
||||
type: 'action'
|
||||
extensionPointIds?: string[]
|
||||
action: Action // Please check the Action section below
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.
|
||||
|
||||
#### Action
|
||||
|
||||
The most important configuration options are:
|
||||
|
||||
- `icon` - The icon to be displayed, can be picked from https://owncloud.design/#/Design%20Tokens/IconList
|
||||
- `name` - The name of the action (not displayed in the UI)
|
||||
- `label` - The text to be displayed
|
||||
- `route` - The string/route to navigate to. The nav item will be a `<router-link>` tag.
|
||||
- `href` - The URL to navigate to. The nav item will be a `<a>`tag.
|
||||
- `handler` - The action to perform upon click. The nav item will be a `<button>` tag.
|
||||
- `isVisible` - Determines whether the action is displayed to the user
|
||||
|
||||
Please check the [`Action` type](https://github.com/owncloud/web/blob/236c185540fc6758dc7bd84985c8834fa4145530/packages/web-pkg/src/composables/actions/types.ts#L6) for a full list of configuration options.
|
||||
|
||||
### Example
|
||||
|
||||
The following example shows how an action extension for downloading files could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.
|
||||
|
||||
```typescript
|
||||
export const useDownloadFilesExtension = () => {
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const extension = computed<ActionExtension>(() => ({
|
||||
id: 'com.github.owncloud.web.files.download-action',
|
||||
scopes: ['resource'],
|
||||
type: 'action',
|
||||
action: {
|
||||
name: 'download-files',
|
||||
icon: 'download',
|
||||
class: 'oc-files-actions-download-files',
|
||||
label: () => $gettext('Download'),
|
||||
isVisible: ({ space, resources }) => {
|
||||
if (resources.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
handler: ({ space, resources }) => {
|
||||
console.log('Triggering download...')
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
return { extension }
|
||||
}
|
||||
```
|
||||
|
||||
The extension could then be registered in any app like so:
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { extension } = useFileActionDownloadFiles()
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Download app'),
|
||||
id: 'download-app'
|
||||
},
|
||||
extensions: computed(() => [unref(extension)])
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
79
web/docs/extension-system/extension-types/app-menu-items.md
Normal file
79
web/docs/extension-system/extension-types/app-menu-items.md
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
title: 'Application Menu Item Extensions'
|
||||
date: 2024-07-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: app-menu-items.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Extension Type AppMenuItem
|
||||
|
||||
This extension type allows apps to register links to internal or external pages within the application switcher menu on the top left.
|
||||
|
||||
### Configuration
|
||||
|
||||
The Interface for an `AppMenuItemExtension` looks like so:
|
||||
|
||||
```typescript
|
||||
interface AppMenuItemExtension {
|
||||
id: string
|
||||
type: 'appMenuItem'
|
||||
extensionPointIds?: string[]
|
||||
label: () => string
|
||||
color?: string
|
||||
handler?: () => void
|
||||
icon?: string
|
||||
path?: string
|
||||
priority?: number
|
||||
url?: string
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in the top level docs.
|
||||
|
||||
A `handler` will result in a `<button>` element. This is necessary when an action should be performed when clicking the menu item (e.g. opening a file editor).
|
||||
|
||||
A `path` will result in an `<a>` element that links to an internal page via the vue router. That means the given path needs to exist within the application.
|
||||
|
||||
A `url` will result in an `<a>` element that links to an external page. External pages always open in a new tab or window.
|
||||
|
||||
At least one of these properties has to be provided when registering an extension. If you define more than one, the priority order is `handler` > `path` > `url`.
|
||||
|
||||
`priority` specifies the order of the menu items. 50 is a good number to start with, then go up/down based on where the item should be placed. Defaults to the highest possible number, so the item will most likely end up at the bottom of the list if you don't specify a `priority`. Leave it empty if unsure what to pick.
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how an app creates an extension that registers an app menu item, linking to an internal page. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { $gettext } = useGettext()
|
||||
const appId = 'my-cool-app'
|
||||
|
||||
const menuItems = computed<AppMenuItemExtension[]>(() => [
|
||||
{
|
||||
id: 'com.github.owncloud.web.my-cool-app.menu-item',
|
||||
type: 'appMenuItem',
|
||||
label: () => $gettext('My cool app'),
|
||||
path: urlJoin(appId),
|
||||
icon: 'star',
|
||||
color: '#0D856F',
|
||||
priority: 60
|
||||
}
|
||||
])
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('My cool app'),
|
||||
id: appId
|
||||
},
|
||||
extensions: menuItems
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: 'Custom Component Extensions'
|
||||
date: 2024-02-14T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: custom-components.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Extension Type CustomComponent
|
||||
|
||||
CustomComponent extensions need to define one or multiple `extensionPointId`s as render target. A `CustomComponentTarget` component for this very
|
||||
extension point needs to be mounted in the current view.
|
||||
|
||||
### Configuration
|
||||
|
||||
To define a custom component extension, you implement the `CustomComponentExtension` interface.
|
||||
Here's what it looks like:
|
||||
|
||||
```typescript
|
||||
interface CustomComponentExtension {
|
||||
id: string
|
||||
type: 'customComponent'
|
||||
extensionPointIds?: string[]
|
||||
content: Slot | Component
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in the top level docs.
|
||||
|
||||
The `content` property specifies a render function or a Component for the target extension point.
|
||||
|
||||
### Example
|
||||
|
||||
A simple example for a custom component extension could be a `NyanCat` progress bar component, being
|
||||
targeted at the `global-progress-bar` extension point as render target.
|
||||
|
||||
```typescript
|
||||
const extension = {
|
||||
id: 'com.github.owncloud.web.app.progress-bars.nyan-cat',
|
||||
type: 'customComponent',
|
||||
extensionPointIds: ['app.runtime.global-progress-bar'],
|
||||
content: (slots) => [h(NyanCat, slots)],
|
||||
userPreference: {
|
||||
optionLabel: $gettext('Nyan Cat progress bar')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `content` property in this example can also be defined as `content: NyanCat`.
|
||||
84
web/docs/extension-system/extension-types/folder-view.md
Normal file
84
web/docs/extension-system/extension-types/folder-view.md
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
title: 'Folder View Extensions'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: folder-view.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
## Folder view extension type
|
||||
|
||||
The folder view is one of the possible extension types. Registered folder view can be used to render multiple resources (folders, files, spaces) in the UI.
|
||||
|
||||
### Configuration
|
||||
|
||||
This is what the FolderViewExtension interface looks like:
|
||||
|
||||
```typescript
|
||||
interface FolderViewExtension {
|
||||
id: string
|
||||
type: 'folderView'
|
||||
extensionPointIds?: string[]
|
||||
folderView: FolderView // See FolderView section below
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.
|
||||
|
||||
#### FolderView
|
||||
|
||||
For the folderView object, you have the following configuration options:
|
||||
|
||||
- `name` - The name of the action (not displayed in the UI)
|
||||
- `label` - The text to be displayed to the user when switching between different FolderView options
|
||||
- `icon` - Object, expecting an icon `name` and a corresponding `IconFillType`, see https://owncloud.design/#/Design%20Tokens/IconList for available options
|
||||
- `isScrollable` - Optional boolean, determines whether the user can scroll inside the component or it statically fills the viewport
|
||||
- `component` - The Vue component to render the resources. It should expect a prop of type `Resource[]`
|
||||
- `componentAttrs` - Optional additional configuration for the component mentioned above
|
||||
|
||||
### Example
|
||||
|
||||
The following example shows how an extension for a custom folder view could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.
|
||||
|
||||
```typescript
|
||||
export const useCustomFolderViewExtension = () => {
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const extension = computed<FolderViewExtension>(() => ({
|
||||
id: 'com.github.owncloud.web.files.folder-view.custom',
|
||||
type: 'folderView',
|
||||
scopes: ['resource', 'space', 'favorite'],
|
||||
folderView: {
|
||||
name: 'custom-table',
|
||||
label: $gettext('Switch to custom folder view'),
|
||||
icon: {
|
||||
name: 'menu-line',
|
||||
fillType: 'none'
|
||||
},
|
||||
component: YourCustomFolderViewComponent
|
||||
}
|
||||
}))
|
||||
|
||||
return { extension }
|
||||
}
|
||||
```
|
||||
|
||||
The extension could then be registered in any app like so:
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { extension } = useCustomFolderViewExtension()
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Custom folder view app'),
|
||||
id: 'custom-folder-view-app'
|
||||
},
|
||||
extensions: computed(() => [unref(extension)])
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: 'Left Sidebar Menu Item Extensions'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: left-sidebar-menu-item.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Left sidebar menu item extension type
|
||||
|
||||
One possible extension type is left sidebar menu items. Registered left sidebar menu items get rendered in the left sidebar, as long as there is more than one available.
|
||||
|
||||
### Configuration
|
||||
|
||||
To define a left sidebar menu item, you implement the SidebarNavExtension interface.
|
||||
It looks like this:
|
||||
|
||||
```typescript
|
||||
interface SidebarNavExtension {
|
||||
id: string
|
||||
type: 'sidebarNav'
|
||||
extensionPointIds?: string[]
|
||||
navItem: AppNavigationItem // Please check the AppNavigationItem section below
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.
|
||||
|
||||
#### AppNavigationItem
|
||||
|
||||
The most important configuration options are:
|
||||
|
||||
- `icon` - The icon to be displayed, can be picked from https://owncloud.design/#/Design%20Tokens/IconList
|
||||
- `name` - The text to be displayed
|
||||
- `route` - The string/route to navigate to, if the nav item should be a `<router-link>` (Mutually exclusive with `handler`)
|
||||
- `handler` - The action to perform upon click, if the nav item should be a `<button>` (Mutually exclusive with `route`)
|
||||
|
||||
Please check the [`AppNavigationItem` type](https://github.com/owncloud/web/blob/f069ce44919cde5d112c68a519d433e015a4a011/packages/web-pkg/src/apps/types.ts#L14) for a full list of configuration options.
|
||||
|
||||
### Example
|
||||
|
||||
The following example shows an extension that adds a left sidebar nav item inside the files app, linking to a custom page. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.
|
||||
|
||||
```typescript
|
||||
export const useCustomPageExtension = () => {
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const extension = computed<SidebarNavExtension>(() => ({
|
||||
id: 'com.github.owncloud.web.files.left-nav.custom-page',
|
||||
scopes: ['app.files'],
|
||||
type: 'sidebarNav',
|
||||
action: {
|
||||
name: $gettext('Custom page'),
|
||||
icon: 'world',
|
||||
priority: 100,
|
||||
isActive: () => true,
|
||||
isVisible: () => true,
|
||||
route: {
|
||||
path: '/files/custom-page'
|
||||
},
|
||||
activeFor: [{ path: '/files/custom-page' }]
|
||||
}
|
||||
}))
|
||||
|
||||
return { extension }
|
||||
}
|
||||
```
|
||||
|
||||
The extension could then be registered in any app like so:
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { extension } = useCustomPageExtension()
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Custom page app'),
|
||||
id: 'custom-page-app'
|
||||
},
|
||||
routes: {
|
||||
path: '/files/custom-page',
|
||||
name: 'files-custom-page',
|
||||
component: CustomPageComponent,
|
||||
meta: {
|
||||
title: $gettext('Custom Page')
|
||||
}
|
||||
},
|
||||
extensions: computed(() => [unref(extension)])
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: 'Right Sidebar Panel Extensions'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: right-sidebar-panels.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Extension Type SideBarPanel
|
||||
|
||||
The right sidebar is supposed to show information and make context specific actions available for single or multiple selected items.
|
||||
|
||||
It is structured in a hierarchical way:
|
||||
|
||||
- Panels which are defined as `root` panels get rendered as immediate members of the right sidebar.
|
||||
- Panels which are defined as non-`root` panels receive a navigation item below the `root` panels so that users can navigate into the respective
|
||||
sub panel.
|
||||
|
||||
### Configuration
|
||||
|
||||
To define a right sidebar panel extension, you implement the `SidebarPanelExtension` interface.
|
||||
It can be found below:
|
||||
|
||||
```typescript
|
||||
interface SidebarPanelExtension<R extends Item, P extends Item, T extends Item> {
|
||||
id: string
|
||||
type: 'sidebarPanel'
|
||||
extensionPointIds?: string[]
|
||||
panel: SideBarPanel<R, P, T> // Please check the SideBarPanel section below
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in the top level docs.
|
||||
|
||||
The `panel` object configures the actual sidebar panel. It consists of different properties and functions, where all the functions get called with a
|
||||
`SideBarPanelContext` entity from the integrating extension points.
|
||||
|
||||
#### SideBarPanelContext
|
||||
|
||||
```typescript
|
||||
interface SideBarPanelContext<R extends Item, P extends Item, T extends Item> {
|
||||
root?: R
|
||||
parent?: P
|
||||
items?: T[]
|
||||
}
|
||||
```
|
||||
|
||||
- `items` - The most important member of the panel context, which denotes all selected items. That can mean all selected files in a files listing,
|
||||
all selected users in a user listing, the individual current file in a file editor.
|
||||
- `parent` - The immediate parent of the selected items. For example, if the user selects a file in a file listing, the parent is the parent folder,
|
||||
or if being in a root of a space, the space itself. Can be `null` for non-hierarchical contexts, e.g. a user listing.
|
||||
- `root` - The uppermost parent of the selected items. For example, if the user selects a file in a file listing, the root is always the space in which
|
||||
the selected files reside. Can be `null` for non-hierarchical contexts, e.g. a user listing.
|
||||
|
||||
#### SideBarPanel
|
||||
|
||||
```typescript
|
||||
interface SideBarPanel<R extends Item, P extends Item, T extends Item> {
|
||||
name: string
|
||||
icon: string
|
||||
iconFillType?: IconFillType
|
||||
title(context: SideBarPanelContext<R, P, T>): string
|
||||
isVisible(context: SideBarPanelContext<R, P, T>): boolean
|
||||
component: Component
|
||||
componentAttrs?(context: SideBarPanelContext<R, P, T>): any
|
||||
isRoot?(context: SideBarPanelContext<R, P, T>): boolean
|
||||
}
|
||||
```
|
||||
|
||||
- `name` - A human readable id for the panel.
|
||||
- `icon`, `iconFillType` and `title` - Properties which are used to render the panel itself or right sidebar navigation items for navigating into that panel.
|
||||
- `isVisible` - Determines if the panel is available for the given panel context.
|
||||
- `component` - Provides a component that renders the actual sidebar panel.
|
||||
- `componentAttrs` - Defines additional props for the component with the given panel context.
|
||||
- `isRoot` - Determines if the panel is a root panel for the given panel context.
|
||||
|
||||
## Extension Point FileSideBar
|
||||
|
||||
In the context of files (e.g. file listing, text editor for a single file, etc.) we have a dedicated component `FileSideBar` which can be
|
||||
toggled (shown/hidden) with a button in the top bar. The component queries all extensions of the type `sideBarPanel` from the extension
|
||||
registry that also fulfill the scope `resource`. By registering an custom extension of type `sideBarPanel` and scope `resource`, your extension
|
||||
will automatically become available in all environments that display the `FileSideBar` (i.e. any file viewer, file editor, file listing).
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how a sidebar panel for displaying exif data for a resource could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) and the [web-client](https://github.com/owncloud/web/tree/master/packages/web-client) packages.
|
||||
|
||||
```typescript
|
||||
export const useExifDataPanelExtension = () => {
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const extension = computed<SidebarPanelExtension<SpaceResource, Resource, Resource>>(() => ({
|
||||
id: 'com.github.owncloud.web.files.sidebar-panel.exif-data',
|
||||
type: 'sidebarPanel',
|
||||
scopes: ['resource'],
|
||||
panel: {
|
||||
name: 'exif-data',
|
||||
icon: 'image',
|
||||
title: () => $gettext('EXIF data'),
|
||||
component: ExifDataPanelComponent,
|
||||
isRoot: () => true,
|
||||
isVisible: ({ items }) => {
|
||||
if (items?.length !== 1) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
return { extension }
|
||||
}
|
||||
```
|
||||
|
||||
The extension can then be registered in any app like so:
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { extension } = useExifDataPanelExtension()
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Exif panel app'),
|
||||
id: 'exif-panel-app'
|
||||
},
|
||||
extensions: computed(() => [unref(extension)])
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
141
web/docs/extension-system/extension-types/search.md
Normal file
141
web/docs/extension-system/extension-types/search.md
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: 'Search Extensions'
|
||||
date: 2024-01-23T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system/extension-types
|
||||
geekdocFilePath: search.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Search extensions
|
||||
|
||||
One possible extension type is search. Registered search extensions are available when using the search field in the topbar. A search extension can consist of a
|
||||
`list` and a `preview` search. The result of a `preview` search is shown below the search input field while the `list` search result is
|
||||
|
||||
### Configuration
|
||||
|
||||
An example of a search extension configuration can be found below:
|
||||
|
||||
```typescript
|
||||
interface SearchExtension {
|
||||
id: string
|
||||
type: 'search'
|
||||
extensionPointIds?: string[]
|
||||
searchProvider: {
|
||||
id: string
|
||||
available: boolean
|
||||
displayName?: string
|
||||
previewSearch?: SearchPreview // See SearchPreview section below
|
||||
listSearch?: SearchList // See SearchList section below
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.
|
||||
|
||||
The `searchProvider` object configures the actual provider. It consist of the following:
|
||||
|
||||
- `id` - Since your extension has an `id` and can only have one searchProvider, you can reuse the same value
|
||||
- `available` - Can be used to programmatically disable/enable any searchProvider, e.g. by dynamically checking backend capabilities
|
||||
- `displayName` - Optional, used to add a small hint to indicate the connection between search providers and their corresponding results
|
||||
- `previewSearch` - See below
|
||||
- `listSearch` - See below
|
||||
|
||||
#### ListSearch
|
||||
|
||||
The listSearch object consists of:
|
||||
|
||||
- `component` - Vue component that can render the values from the SearchResult below
|
||||
- `search(term: string)` - Function that exectues the search, based on a given term. The term is formatted in [KQL](https://owncloud.dev/services/search/#query-language). Please note that the returned values needs to be formatted to fit either `SearchResource` or `GenericSearchResultItem` type
|
||||
|
||||
#### PreviewSearch
|
||||
|
||||
The previewSearch object extends the listSearch with one additional attribute:
|
||||
|
||||
- `available` - Indicates whether a preview underneath the search bar is available for this search provider
|
||||
|
||||
## Example
|
||||
|
||||
The following example shows how a search extension that queries a Solr search engine could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) and the [web-client](https://github.com/owncloud/web/tree/master/packages/web-client) packages.
|
||||
|
||||
```typescript
|
||||
export const useSolrSearchExtension = () => {
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const previewSearch: SearchPreview = {
|
||||
component: SolarSearchComponent, // see the next example snippet
|
||||
available: () => true,
|
||||
search: (term) => {
|
||||
// actual search implementation
|
||||
console.log('Querying solr search engine...')
|
||||
}
|
||||
}
|
||||
|
||||
const searchProvider: SearchProvider = {
|
||||
id: 'solr-search',
|
||||
available: true,
|
||||
displayName: 'Solr Search',
|
||||
previewSearch
|
||||
}
|
||||
|
||||
const extension = computed<SearchExtension>(() => ({
|
||||
id: 'com.github.owncloud.web.solr-search',
|
||||
type: 'search',
|
||||
searchProvider
|
||||
}))
|
||||
|
||||
return { extension }
|
||||
}
|
||||
```
|
||||
|
||||
The search component for the preview search container may look like this:
|
||||
|
||||
```Vue
|
||||
<template>
|
||||
<resource-list-item :resource="resource" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType } from 'vue'
|
||||
import { Resource } from '@ownclouders/web-client'
|
||||
import { SearchResultValue, ResourceListItem } from '@ownclouders/web-pkg'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SolarSearchComponent',
|
||||
components: { ResourceListItem },
|
||||
props: {
|
||||
searchResult: {
|
||||
type: Object as PropType<SearchResultValue>,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const resource = computed<Resource>(() => props.searchResult.data)
|
||||
|
||||
return { resource }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
```
|
||||
|
||||
The extension can then be registered in any app like so:
|
||||
|
||||
```typescript
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
const { extension } = useSolrSearchExtension()
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: $gettext('Solr search app'),
|
||||
id: 'solrs-search-app'
|
||||
},
|
||||
extensions: computed(() => [unref(extension)])
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
128
web/docs/extension-system/viewer-editor-apps.md
Normal file
128
web/docs/extension-system/viewer-editor-apps.md
Normal file
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: 'Viewer and Editor Apps'
|
||||
date: 2024-03-12T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/extension-system
|
||||
geekdocFilePath: viewer-editor-apps.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Viewer and editor apps
|
||||
|
||||
ownCloud Web allows developers to implement apps for viewing and editing specific file types. For instance, the built-in preview app serves as the default application for opening media files like images, videos, or audio.
|
||||
|
||||
This section will guide you through the process of implementing such an app within ownCloud Web.
|
||||
|
||||
### Basic app structure
|
||||
|
||||
An app is essentially a distinct package that must be specified as an external application in the Web configuration.
|
||||
|
||||
The structure of an app is quite simple and straightforward. Consider, for example, the [pdf-viewer app](https://github.com/owncloud/web/tree/master/packages/web-app-pdf-viewer). It consists of a `package.json` file, a `src` directory containing all the source code, and a `l10n` directory for translations. Optionally, you may also include a `tests` directory if your application requires testing.
|
||||
|
||||
To learn more about apps in general, please refer to the [Web app docs]({{< ref "_index.md#apps" >}}).
|
||||
|
||||
### App setup
|
||||
|
||||
Inside the `src` folder you will need an `index.ts` file that sets up the app so it can be registered by the Web runtime. It follows the basic structure as described in [the apps section]({{< ref "_index.md#apps" >}}), so it may look like this:
|
||||
|
||||
```typescript
|
||||
import { AppWrapperRoute, defineWebApplication, AppMenuItemExtension } from '@ownclouders/web-pkg'
|
||||
import translations from '../l10n/translations.json'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
import { computed } from 'vue'
|
||||
|
||||
// This is the base component of your app.
|
||||
import App from './App.vue'
|
||||
|
||||
export default defineWebApplication({
|
||||
setup() {
|
||||
// The ID of your app.
|
||||
const appId = 'advanced-pdf-viewer'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
// This creates a route under which your app can be opened.
|
||||
// Later, this route will be bound to one or more file extensions.
|
||||
const routes = [
|
||||
{
|
||||
name: 'advanced-pdf-viewer',
|
||||
path: '/:driveAliasAndItem(.*)?',
|
||||
component: AppWrapperRoute(App, {
|
||||
applicationId: appId
|
||||
}),
|
||||
meta: {
|
||||
authContext: 'hybrid',
|
||||
title: $gettext('Advanced PDF Viewer'),
|
||||
patchCleanPath: true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// if you want your app to be present in the app menu on the top left.
|
||||
const menuItems = computed<AppMenuItemExtension[]>(() => [
|
||||
{
|
||||
label: () => $gettext('Advanced PDF Viewer'),
|
||||
type: 'appMenuItem',
|
||||
handler: () => {
|
||||
// do stuff...
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
return {
|
||||
appInfo: {
|
||||
name: 'Advanced PDF Viewer',
|
||||
id: appId,
|
||||
defaultExtension: 'pdf',
|
||||
extensions: [
|
||||
// This makes sure all files with the "pdf" extension will be routed to your app when being opened.
|
||||
// See the `ApplicationFileExtension` interface down below for a list of all possible properties.
|
||||
{
|
||||
extension: 'pdf',
|
||||
routeName: 'advanced-pdf-viewer',
|
||||
|
||||
// Add this if you want your app to be present in the "New" file menu.
|
||||
newFileMenu: {
|
||||
menuTitle() {
|
||||
return $gettext('PDF document')
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
routes,
|
||||
translations,
|
||||
extensions: menuItems
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Here is the interface defining the `extensions` property of the `appInfo` object.
|
||||
|
||||
```typescript
|
||||
interface ApplicationFileExtension {
|
||||
app?: string
|
||||
extension?: string
|
||||
createFileHandler?: (arg: {
|
||||
fileName: string
|
||||
space: SpaceResource
|
||||
currentFolder: Resource
|
||||
}) => Promise<Resource>
|
||||
hasPriority?: boolean
|
||||
label?: string
|
||||
name?: string
|
||||
icon?: string
|
||||
mimeType?: string
|
||||
newFileMenu?: { menuTitle: () => string }
|
||||
routeName?: string
|
||||
customHandler? (
|
||||
fileActionOptions: FileActionOptions,
|
||||
extension: string,
|
||||
appFileExtension: ApplicationFileExtension
|
||||
) => Promise<void> | void
|
||||
}
|
||||
```
|
||||
110
web/docs/getting-started.md
Normal file
110
web/docs/getting-started.md
Normal file
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: 'Getting Started'
|
||||
date: 2018-05-02T00:00:00+00:00
|
||||
weight: 10
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs
|
||||
geekdocFilePath: getting-started.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Source Code
|
||||
|
||||
The source code is hosted at [https://github.com/owncloud/web](https://github.com/owncloud/web).
|
||||
Please refer to the [build documentation for Web]({{< ref "./building.md" >}}).
|
||||
|
||||
## Installation
|
||||
|
||||
Make sure to have Docker, Docker-Compose, [Node.js](https://nodejs.org/en/download) and [pnpm](https://pnpm.io/installation) installed.
|
||||
If you plan to work with translations, you also need to install the [Transifex Client](https://developers.transifex.com/docs/cli). Note when installing the Transifex Client, change to your `~/.local/bin` directory first because it installs at the current location.
|
||||
|
||||
{{< hint info >}}
|
||||
This setup currently doesn't work on Windows out of the box.
|
||||
|
||||
<details>
|
||||
<summary>Workaround</summary>
|
||||
One of our contributors has opened a PR to a dependency that prevents us from successfully bundling the frontend.
|
||||
Feel free to check out [his changes](https://github.com/egoist/rollup-plugin-postcss/pull/384) and build them locally if you absolutely want to work on Windows.
|
||||
</details>
|
||||
{{< /hint >}}
|
||||
|
||||
After cloning the [source code](https://github.com/owncloud/web), install the dependencies via `pnpm install` and bundle the frontend code by running `pnpm build:w`.
|
||||
|
||||
### Docker
|
||||
|
||||
Then, you can start the server by running `docker-compose up ocis` and access it via [https://host.docker.internal:9200](https://host.docker.internal:9200). If you're not using Docker Desktop, you might have to modify your `/etc/hosts` and add `127.0.0.1 host.docker.internal` to make the `host.docker.internal` links work.
|
||||
|
||||
The bundled frontend code automatically gets mounted into the Docker containers, recompiles on changes and you can log in using the demo user (admin/admin) and take a look around!
|
||||
|
||||
For more details on how to set up Web for development, please see [tooling]({{< ref "tooling.md#development-setup" >}}).
|
||||
|
||||
## Configuration
|
||||
|
||||
Depending on the backend you are using, there are sample config files provided in the [config folder](https://github.com/owncloud/web/tree/master/config) of the ownCloud Web git repository. See below for available backends. Also, find some of the configuration details below.
|
||||
|
||||
- `customTranslations` You can specify one or multiple files to overwrite existing translations. For example set this option to `[{url: "https://localhost:9200/customTranslations.json"}]`.
|
||||
|
||||
#### Options
|
||||
|
||||
- `options.accountEditLink` This accepts an object with the following optional fields to have a link on the account page:
|
||||
- `options.accountEditLink.href` Set a different target URL for the edit link. Make sure to prepend it with `http(s)://`.
|
||||
- `options.disableFeedbackLink` Set this option to `true` to disable the feedback link in the topbar. Keeping it enabled (value `false` or absence of the option)
|
||||
allows ownCloud to get feedback from your user base through a dedicated survey website.
|
||||
- `options.feedbackLink` This accepts an object with the following optional fields to customize the feedback link in the topbar:
|
||||
- `options.feedbackLink.href` Set a different target URL for the feedback link. Make sure to prepend it with `http(s)://`. Defaults to `https://owncloud.com/web-design-feedback`.
|
||||
- `options.feedbackLink.ariaLabel` Since the link only has an icon, you can set an e.g. screen reader accessible label. Defaults to `ownCloud feedback survey`.
|
||||
- `options.feedbackLink.description` Provide any description you want to see as tooltip and as accessible description. Defaults to `Provide your feedback: We'd like to improve the web design and would be happy to hear your feedback. Thank you! Your ownCloud team.`
|
||||
- `options.sharingRecipientsPerPage` Sets the amount of users shown as recipients in the dropdown when sharing resources. Default amount is 200.
|
||||
- `options.runningOnEos` Set this option to `true` if running on an [EOS storage backend](https://eos-web.web.cern.ch/eos-web/) to enable its specific features. Defaults to `false`, and we recommend reaching out to [the ownCloud web team](https://matrix.to/#/#ocis:matrix.org) if you're not CERN and thinking about enabling this feature flag.
|
||||
- `options.cernFeatures` Enabling this will activate CERN-specific features. Defaults to `false`.
|
||||
- `options.editor.autosaveEnabled` Specifies if the autosave for the editor apps is enabled.
|
||||
- `options.editor.autosaveInterval` Specifies the time interval for the autosave of editor apps in seconds.
|
||||
- `options.editor.openAsPreview` Specifies if non-personal files i.e. files in shares, spaces or public links are being opened in read only mode so the user needs to manually switch to edit mode. Can be set to `true`, `false` or an array of web app/editor names.
|
||||
- `options.contextHelpersReadMore` Specifies whether the "Read more" link should be displayed or not.
|
||||
- `options.tokenStorageLocal` Specifies whether the access token will be stored in the local storage when set to `true` or in the session storage when set to `false`. If stored in the local storage, login state will be persisted across multiple browser tabs, means no additional logins are required. Defaults to `true`.
|
||||
- `options.loginUrl` Specifies the target URL to the login page. This is helpful when an external IdP is used. This option is disabled by default. Example URL like: 'https://www.myidp.com/login'.
|
||||
- `options.logoutUrl` Adds a link to the user's profile page to point him to an external page, where he can manage his session and devices. This is helpful when an external IdP is used. This option is disabled by default.
|
||||
- `options.userListRequiresFilter` Defines whether one or more filters must be set in order to list users in the Web admin settings. Set this option to 'true' if running in an environment with a lot of users and listing all users could slow down performance. Defaults to `false`.
|
||||
- `options.concurrentRequests` This accepts an object with the following optional fields to customize the maximum number of concurrent requests in code paths where we limit concurrent requests
|
||||
- `resourceBatchActions` Concurrent number of file/folder/space batch actions like e.g. accepting shares. Defaults to 4.
|
||||
- `sse` Concurrent number of SSE event handlers. Defaults to 4.
|
||||
- `shares` Accepts an object regarding the following sharing related options:
|
||||
- `create` Concurrent number of share invites. Defaults to 4.
|
||||
- `list` Concurrent number of individually loaded shares. Defaults to 2.
|
||||
|
||||
#### Scripts and Styles
|
||||
|
||||
Web supports adding additional CSS and JavaScript files to further customize the user experience and adapt it to your specific needs. Please consider opening a feature request if you feel like your customization could be a benefit to the upstream project, and keep an eye open for future major releases of `web` since this API may change.
|
||||
|
||||
- `styles` expects an array of objects that specify a `href` attribute, pointing to the path/URL of your stylesheet, like `[{ "href": "css/custom.css" }]`.
|
||||
- `scripts` expects an array of objects that specify a `src` attribute, pointing to the path/URL of your script, and an optional `async` attribute (defaults to false), like `[{ "src": "js/custom.js", "async": true }]`.
|
||||
|
||||
### Sentry
|
||||
|
||||
Web supports [Sentry](https://sentry.io/welcome/) to provide monitoring and error tracking.
|
||||
To enable sending data to a Sentry instance, you can use the following configuration keys:
|
||||
|
||||
- `sentry.dsn` Should contain the DSN for your sentry project.
|
||||
- `sentry.environment`: Lets you specify the environment to use in Sentry. Defaults to `production`.
|
||||
|
||||
Any other key under `sentry` will be forwarded to the Sentry initialization. You can find out more
|
||||
settings in the [Sentry docs](https://docs.sentry.io/platforms/javascript/configuration/).
|
||||
|
||||
{{< hint info >}}
|
||||
If you are using an old version of Sentry (9 and before), you might want to add the setting `sentry.autoSessionTracking: false` to avoid errors related to breaking changes introduced in the
|
||||
integration libraries.
|
||||
{{< /hint >}}
|
||||
|
||||
## Setting up backend and running
|
||||
|
||||
Newer versions of Web (> 7.0.2) can only run against [oCIS](https://github.com/owncloud/ocis), whereas older versions (< 7.1.0) can run against [ownCloud Classic](https://github.com/owncloud/core/) as well.
|
||||
Depending which one you chose, please check the matching section:
|
||||
|
||||
- [Setting up with oCIS as backend]({{< ref "backend-ocis.md" >}})
|
||||
- [Setting up with ownCloud as backend]({{< ref "backend-oc10.md" >}})
|
||||
|
||||
## Running
|
||||
|
||||
- [Running with oCIS as backend]({{< ref "backend-ocis.md#running-web" >}})
|
||||
- [Running with ownCloud as backend]({{< ref "backend-oc10.md#running-web" >}})
|
||||
13
web/docs/releasing/_index.md
Normal file
13
web/docs/releasing/_index.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: 'Releasing'
|
||||
date: 2025-06-16T00:00:00+00:00
|
||||
weight: 50
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/releasing
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
This section serves as a guide for releasing ownCloud Web and managing important deprecations for a release.
|
||||
46
web/docs/releasing/deprecations.md
Normal file
46
web/docs/releasing/deprecations.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: 'Deprecations and Migrations'
|
||||
date: 2025-06-11T00:00:00+00:00
|
||||
weight: 70
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/deprecations
|
||||
geekdocFilePath: deprecations.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
This guide tracks deprecations, planned removals, and migration paths for ownCloud Web. Developers should reference this guide when upgrading between major versions to ensure compatibility and adopt recommended practices.
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Upcoming Deprecations
|
||||
|
||||
The following features are deprecated and **will be removed** in the next major version.
|
||||
|
||||
| Component/Feature | Deprecated | Migration | Reference | Reasoning |
|
||||
|---|---|---|---|---|---|
|
||||
| `owncloud-embed:share` event | November 12, 2025 | Use `owncloud-embed:share-links` event instead | [PR #13296](https://github.com/owncloud/web/pull/13296) | New event provides structured data with both URL and optional password |
|
||||
|
||||
## Migration History
|
||||
|
||||
The following features **are already removed**.
|
||||
|
||||
| Component/Feature | Removed in Version | Deprecated | Migration | Reference | Reasoning |
|
||||
|---|---|---|---|---|---|
|
||||
| `CollapsibleOcTable` component | v12 | May 16, 2025 | Use `OcTable` instead | [PR #12567](https://github.com/owncloud/web/pull/12567) | No longer needed by original implementers |
|
||||
| `ocsUserContext` and `ocsPublicLinkContext` of `ClientService` | v12 | September 26, 2024 | Use `ocs` instead | [PR #11656](https://github.com/owncloud/web/pull/11656) | These methods were only a wrapper around the `ocs` |
|
||||
| Web Client initialisation | v12 | September 26, 2024 | Use `graph()`, `ocs()` and `webdav()` to initialize and use clients | [PR #11656](https://github.com/owncloud/web/pull/11656) | More transparency to developers |
|
||||
| `type` prop of `ApplicationInformation` | v12 | July 26, 2024 | N/A | [Commit 5e8ac91](https://github.com/owncloud/web/commit/5e8ac918de780f0b03ad79a85b8c25e4ba1fe4df) | The `type` prop is not used anymore |
|
||||
| `isFileEditor` prop of `ApplicationInformation` | v12 | July 26, 2024 | N/A | [Commit 67ce21c](https://github.com/owncloud/web/commit/67ce21ce1bcc449d18f53e4930d180198a19faa0) | The `isFileEditor` prop is not used anymore |
|
||||
| `ApplicationMenuItem` and `applicationMenu` prop of `ApplicationInformation` | v12 | July 24, 2024 | Register app menu items via the `appMenuExtensionPoint` instead | [PR #11258](https://github.com/owncloud/web/pull/11258) | Transitioning to the new extension points system |
|
||||
| `ApplicationQuickAction` | v12 | December 1, 2023 | Register quick actions as extension instead | [PR #10102](https://github.com/owncloud/web/pull/10102) | Transitioning to the new extension points system |
|
||||
| Vuex Store | v9 | January 22, 2024 | Migrate to Pinia stores | [PR #10372](https://github.com/owncloud/web/pull/10372) | Better TypeScript support and Composition API integration |
|
||||
| Home Folder Option | v9 | January 5, 2024 | Use spaces functionality | [PR #10122](https://github.com/owncloud/web/pull/10122) | No longer needed by original implementers |
|
||||
| OCS User API | v9 | January 3, 2024 | Use Graph user from `@ownclouders/web-client/src/helpers` and `useUserStore` | [PR #10240](https://github.com/owncloud/web/pull/10240) | The OCS API is deprecated and we're slowly transitioning to the Graph API and we want to get rid of the vuex store |
|
||||
| Vuex Modal Implementation | v9 | December 22, 2023 | Use `useModals()` composable | [PR #10212](https://github.com/owncloud/web/pull/10212) | Remove Vuex store dependency |
|
||||
| App: `user-management` | v8 | January 4, 2023 | Use the name `admin-settings` when referencing the app (in your configs for example) | [PR #8175](https://github.com/owncloud/web/pull/8175) | The app is supposed to hold a variety of general settings in the future, not just user-related settings |
|
||||
| `mediaSource` helper & `v-image-source` directive | v6 | July 27, 2022 | Use `loadPreview` from web-pkg | N/A | `loadPreview` is the new default mechanism. We want to get rid of magical everywhere-available helpers |
|
||||
| `getToken` getter | v6 | July 7, 2022 | Use `runtime/auth/accessToken` getter | N/A | `user` state is not supposed to deal with authentication details. We introduced the namespaced `auth` module for `user` and `public-link` related authentication contexts |
|
||||
|
||||
## Getting Help
|
||||
|
||||
For questions about specific migrations, refer to the linked pull requests and commits for detailed implementation examples and discussion.
|
||||
19
web/docs/releasing/releasing.md
Normal file
19
web/docs/releasing/releasing.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: 'Releasing'
|
||||
weight: 25
|
||||
geekdocRepo: https://github.com/owncloud/ocis
|
||||
geekdocEditPath: edit/master/web/docs
|
||||
geekdocFilePath: releasing.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Releasing
|
||||
|
||||
ownCloud Web no longer has a standalone release process. Its source lives in-tree under
|
||||
`web/` in the [ocis repository](https://github.com/owncloud/ocis) and is built and released
|
||||
as part of oCIS itself. See [oCIS Web service / Releasing](/services/web/releasing) for the
|
||||
current process.
|
||||
|
||||
The final standalone release of ownCloud Web was `v12.5.0` (also tagged `last-agpl-release`),
|
||||
after which the [owncloud/web](https://github.com/owncloud/web) repository was archived.
|
||||
BIN
web/docs/static/application-switcher-oc10.jpg
vendored
Normal file
BIN
web/docs/static/application-switcher-oc10.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
web/docs/static/oauth2.png
vendored
Normal file
BIN
web/docs/static/oauth2.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
11
web/docs/testing/_index.md
Normal file
11
web/docs/testing/_index.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "Tests"
|
||||
date: 2022-01-28T00:00:00+00:00
|
||||
weight: 55
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/testing
|
||||
geekdocFilePath: _index.md
|
||||
geekdocCollapseSection: true
|
||||
---
|
||||
|
||||
Guides on running different kinds of tests in ownCloud Web.
|
||||
48
web/docs/testing/accesibility.md
Normal file
48
web/docs/testing/accesibility.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: 'Accessibility'
|
||||
date: 2025-11-10T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/testing
|
||||
geekdocFilePath: accessibility.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Introduction
|
||||
|
||||
Accessibility is a crucial aspect of web development. It ensures that web applications are usable by everyone, including people with disabilities.
|
||||
|
||||
## What Tools We Use
|
||||
|
||||
### eslint-plugin-vuejs-accessibility
|
||||
|
||||
We use [eslint-plugin-vuejs-accessibility](https://github.com/vue-a11y/eslint-plugin-vuejs-accessibility) to quickly catch accessibility issues in the codebase. This plugin is used in the [@ownclouders/eslint-config](https://www.npmjs.com/package/@ownclouders/eslint-config).
|
||||
|
||||
### @axe-core/playwright
|
||||
|
||||
We use [@axe-core/playwright](https://github.com/dequelabs/axe-core-npm) to automatically test the accessibility of the ownCloud Web client. All tests are run automatically on every PR and on commits to the `master` branch. We are not running dedicated accessibility tests and instead make them part of the E2E tests. This way we do not have to maintain duplicate tests and we can granularly add accessibility tests to the specific steps of the tests. The tests are considered failed if any `serious` or `critical` accessibility violations are found.
|
||||
|
||||
#### Running Accessibility Tests
|
||||
|
||||
To run the accessibility tests, you can simply run our existing E2E tests using the following command:
|
||||
|
||||
```bash
|
||||
pnpm test:e2e:playwright
|
||||
```
|
||||
|
||||
#### Skipping Accessibility Tests Locally
|
||||
|
||||
If you want to skip the accessibility tests, you can add the `SKIP_A11Y_TESTS` environment variable to your command.
|
||||
|
||||
```bash
|
||||
SKIP_A11Y_TESTS=true pnpm test:e2e:playwright
|
||||
```
|
||||
|
||||
#### Skipping Accessibility Tests in CI
|
||||
|
||||
If you want to skip the accessibility tests in CI, you can add the `[skip-a11y]` flag into the title of the PR.
|
||||
|
||||
#### Accessibility Report
|
||||
|
||||
After the tests are run, a JSON accessibility report is generated in the `reports/e2e/a11y-report.json` file. This report contains detailed information about the accessibility violations found in the tests.
|
||||
266
web/docs/testing/e2e-testing-standards.md
Normal file
266
web/docs/testing/e2e-testing-standards.md
Normal file
@@ -0,0 +1,266 @@
|
||||
---
|
||||
title: 'End-to-End (E2E) Test Standards'
|
||||
date: 2024-09-11T00:00:00+00:00
|
||||
weight: 60
|
||||
geekdocRepo: https://github.com/owncloud/web
|
||||
geekdocEditPath: edit/master/docs/testing
|
||||
geekdocFilePath: e2e-testing-standards.md
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Introduction
|
||||
|
||||
In ownCloud, we use Playwright for webUI test automation. We benefit from lower barriers to entry, readability, and usability when test standards are consistent across repositories. For example:
|
||||
|
||||
- **Reusability:** Enhances reusability by making it easier to reuse functions, locators, shared steps, and other test code. Finding the necessary components and functionalities will be simple for someone working on a test resulting in reduced duplication and the requirement for rework after the initiation of a code review.
|
||||
|
||||
- **Facilitates reviews:** Code can be examined more quickly. Since you can quickly determine what the test code is doing, it eases the mental strain of code review.
|
||||
|
||||
- **Faster onboarding:** By following naming conventions, new contributors are onboarded more rapidly and feel comfortable enough to contribute to the codebase.
|
||||
|
||||
Here are the test standards and guidelines we adhere to when creating Playwright tests at ownCloud.
|
||||
|
||||
## Folder Structure:
|
||||
- `tests/:`
|
||||
|
||||
- `e2e/`: Main folder containing all (end-to-end) E2E test-related files.
|
||||
|
||||
- `specs/`: Main folder containing all test-related files.
|
||||
|
||||
- `<test-suite-folder>/`: Collection house for "**related"** spec files.
|
||||
|
||||
- `<aSpecFile>.spec.ts`: A spec file.
|
||||
|
||||
- `steps/`: Holds the files that defines actions of user.
|
||||
|
||||
- `hooks/`: Test hooks for setting up and tearing down test environments.
|
||||
- `hooks.ts`: Contains `Before`, `After`, and other lifecycle hooks.
|
||||
|
||||
- `support/`: Playwright (Test implementation)
|
||||
|
||||
- `api/`: Contains API-related test files and configurations.
|
||||
|
||||
- `<api-folder>/ `: Specific API tests for a particular service.
|
||||
|
||||
- `objects/`: Contains the Page Object classes.
|
||||
|
||||
- `<specific-page-object-folder>/`: Collection house for related page objects for each webpage or component.
|
||||
|
||||
- `<individualPageObject>.ts`: Page Object for each webpage or component.
|
||||
|
||||
- `utils/`: Utility functions and common helpers.
|
||||
|
||||
- `helpers.ts`: Common utility functions (e.g., date formatting, data generation).
|
||||
|
||||
- `test-data/`: Static test data files or folders for upload.
|
||||
|
||||
- `filesForUpload/`: Static test data files for upload.
|
||||
|
||||
- `config/`: Configuration files for Playwright and other tools.
|
||||
|
||||
- `playwright.config.ts`: Playwright configuration.
|
||||
|
||||
- `reports/`: Generated test reports (e.g., HTML, JSON).
|
||||
|
||||
- `screenshots/`: Captured screenshots during test execution.
|
||||
|
||||
- `videos/`: Recorded videos of test runs.
|
||||
|
||||
## Test Structure - Arrange, Act, Assert:
|
||||
|
||||
We can follow the AAA (Arrange, Act, Assert) pattern when structuring the tests. In most cases, the Arrange step can be included in a Before block(hook).
|
||||
Consider including comments defining each section to ease readability.
|
||||
|
||||
```typescript
|
||||
// arrange, set up the initial conditions for the test
|
||||
// create a property
|
||||
await createProperty()
|
||||
|
||||
// act, perform the action that you want to test
|
||||
// raise a charge
|
||||
// this could involve calling methods or functions defined in your page objects
|
||||
await raiseCharge()
|
||||
|
||||
// assert, verify that the action had the expected outcome
|
||||
// confirm charge has been raised
|
||||
expect(charge).toBe('raised')
|
||||
```
|
||||
|
||||
## Page Object Model (POM)
|
||||
|
||||
Every page should possess one POM file to enhance maintainability and scalability of our tests. It should include all the selectors and functions which are needed to interact with the UI page or component(s).
|
||||
|
||||
All interactions should be done using the page objects, no selectors in your tests.
|
||||
|
||||
All assertions should be in your test, no assertion in the POM
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
// POM file './pageOobjects/foo/'
|
||||
// add all locators and functions related to the page.
|
||||
// allowing all tests to reuse
|
||||
|
||||
import {expect, Locator, Page} from '@playwright/test';
|
||||
|
||||
export class FooPage {
|
||||
readonly errorMessage: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.errorMessage = page.locator('.error-message');
|
||||
}
|
||||
}
|
||||
|
||||
// test file './steps/foo.ts'
|
||||
import {FooPage} from './pageObjects/foo';
|
||||
|
||||
let fooPage: FooPage;
|
||||
|
||||
await errorMessageShouldBeVisible({page}) {
|
||||
const fooPage = new FooPage({page});
|
||||
await expect(fooPage.errorMessage).toBeVisible();
|
||||
}
|
||||
```
|
||||
|
||||
DO NOT ⚔️
|
||||
```typescript
|
||||
// test file './steps/foo.ts'
|
||||
// include locators directly in test
|
||||
import { Locator, Page } from '@playwright/test';
|
||||
|
||||
await errorMessageShouldBeVisible({page}) {
|
||||
await expect(page.locator('.error-message')).toBeVisible();
|
||||
}
|
||||
```
|
||||
|
||||
## Waiting:
|
||||
|
||||
Playwright uses auto-waiting, so we avoid artificial waiting, the exception being if it is really necessary.
|
||||
|
||||
DO NOT ⚔️
|
||||
|
||||
```typescript
|
||||
await page.waitForTimeout(5000)
|
||||
```
|
||||
|
||||
This can cause flaky tests as we can rarely be certain the amount of wait time is enough. It can also unnecessarily increase the test run time. Instead, we can try:
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
await page.goto(fooBarURL, {
|
||||
waitUntil: 'domcontentloaded'
|
||||
});
|
||||
```
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
const element = page.locator("some-locator-path");
|
||||
element.waitFor({ visible: true });
|
||||
```
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
await fooPage.buttonFoo.click();
|
||||
await expect(fooPage.titlePage).toBeVisible();
|
||||
```
|
||||
|
||||
## Selectors
|
||||
|
||||
Avoid selectors tied to implementation and page structure.
|
||||
|
||||
Instead, we can prioritize the below, based on [testing-library guiding principles](https://testing-library.com/docs/queries/about/#priority)
|
||||
|
||||
- `getByRole` (this aids accessibility, reflects how users and assistive technology perceive the page)
|
||||
|
||||
- `getByText`
|
||||
|
||||
- `getByTestId` (add them when needed)
|
||||
|
||||
DO NOT ⚔️
|
||||
|
||||
```javascript
|
||||
page.locator('.opt-u > div > .summary > div:nth-child(4) > div')
|
||||
```
|
||||
|
||||
DO 👍
|
||||
|
||||
```javascript
|
||||
page.locator('#foo-button');
|
||||
page.getByText('OK');
|
||||
```
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### Files and folders
|
||||
- **Files**: Declare in **_camelCase_**
|
||||
- **Folders**: Declare in **_kebab-case_**
|
||||
|
||||
### Variables
|
||||
|
||||
Declare in **_camelCase_**.
|
||||
|
||||
### Booleans
|
||||
|
||||
Start with ‘is’, ‘has’, ‘are’, ‘have’. This helps spot that this is a boolean while skimming the code. Still declared in ***camelCase***.
|
||||
|
||||
```typescript
|
||||
let isTurnedOn = false
|
||||
```
|
||||
### Page Objects / Classes
|
||||
|
||||
Declare in **_PascalCase_**.
|
||||
|
||||
Use descriptive naming, which can help the reader quickly identify what page or page component this is covering. Use as much context as needed from your product to make the name meaningful.
|
||||
|
||||
DO NOT ⚔️
|
||||
|
||||
```typescript
|
||||
export class newModal
|
||||
```
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
export class AddWorksOrderModal
|
||||
```
|
||||
|
||||
### Locators
|
||||
|
||||
Use descriptive naming, which can help the reader quickly identify what element the locator is targeting.
|
||||
|
||||
As an example, you can use a naming structure that contains ***“action / name of element” + “type of element”***.
|
||||
|
||||
***Defining type of element*** - These are your basic HTML element types, they’ll be defined and named in the design system, or as a team you can align on a consistent naming of the elements. Example: checkbox, tickbox, button, tooltip
|
||||
|
||||
***Defining action / name -*** Think about what action this element will perform when interacted with. Or any existing name/text of the element
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
// This element is a submit button for the user registration form
|
||||
const submitButton = await page.locator("<locator-path>");
|
||||
```
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
// This element is a button for uploading a profile picture
|
||||
const uploadProfilePictureButton = await page.locator("<locator-path>");
|
||||
```
|
||||
|
||||
### Function names
|
||||
|
||||
Always start function names with a ***“verb”***, followed by the ***“component context”*** that the function is interacting with i.e. what entity it is having an effect on.
|
||||
|
||||
DO 👍
|
||||
|
||||
```typescript
|
||||
getWorksOrder()
|
||||
printTransactions()
|
||||
deleteProperty()
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user