mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-22 16:04:28 +00:00
Compare commits
110
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b042fec29d | ||
|
|
a653fc3627 | ||
|
|
db31fcad98 | ||
|
|
b82c73f789 | ||
|
|
70d3507e5d | ||
|
|
518b45d149 | ||
|
|
65f2eea6c9 | ||
|
|
12a4a8218a | ||
|
|
76dd4f079c | ||
|
|
b35fb011e0 | ||
|
|
fa1e9c7ca7 | ||
|
|
75bb64b333 | ||
|
|
1f40045b41 | ||
|
|
1951e5e82c | ||
|
|
0be39c5b7d | ||
|
|
6886188ff4 | ||
|
|
3a2de81369 | ||
|
|
4de3ea2892 | ||
|
|
0beb2e3334 | ||
|
|
537d79f3c2 | ||
|
|
10d5f4f530 | ||
|
|
ab0e7e1ea9 | ||
|
|
967a3aa10b | ||
|
|
821649c821 | ||
|
|
7cf75e9dba | ||
|
|
dfe126f827 | ||
|
|
80ce98991c | ||
|
|
579d42ec74 | ||
|
|
047108683f | ||
|
|
830c9196e7 | ||
|
|
7208f23da1 | ||
|
|
b0a4a0bcfa | ||
|
|
f7b13dd121 | ||
|
|
a5ccfa01d2 | ||
|
|
62bf4c5b45 | ||
|
|
7168d7e31d | ||
|
|
3c633f8a34 | ||
|
|
b606a4ee8e | ||
|
|
1af094692f | ||
|
|
c86d8ac6b8 | ||
|
|
b06d65ab43 | ||
|
|
390bdc33e0 | ||
|
|
2284d1fcee | ||
|
|
62a439e10e | ||
|
|
ddad663489 | ||
|
|
f08e7d9b92 | ||
|
|
6c2865a09d | ||
|
|
5a0d15c937 | ||
|
|
53757dab93 | ||
|
|
e1d4d3e85b | ||
|
|
859fe238b8 | ||
|
|
23df40796b | ||
|
|
b98b1326b2 | ||
|
|
2f8831b561 | ||
|
|
4948b9b586 | ||
|
|
838018e72e | ||
|
|
d5433e7a3f | ||
|
|
194e19bf5e | ||
|
|
1358e7098d | ||
|
|
4be327608a | ||
|
|
929ef37ded | ||
|
|
6fce1807f0 | ||
|
|
c1d72650cc | ||
|
|
dab368e44b | ||
|
|
7548174e4f | ||
|
|
b513060744 | ||
|
|
311a9ef70b | ||
|
|
7331144f9d | ||
|
|
d576b36f7b | ||
|
|
7a6340aac6 | ||
|
|
6b82abcd80 | ||
|
|
97bde05422 | ||
|
|
3bc50eee47 | ||
|
|
b95a220de7 | ||
|
|
2896e18429 | ||
|
|
29db91f976 | ||
|
|
1e3dfe3de1 | ||
|
|
dcb1f5e80f | ||
|
|
5c75eeab27 | ||
|
|
8e4bff8c19 | ||
|
|
e066f155b2 | ||
|
|
c3c7a23ccd | ||
|
|
c816411644 | ||
|
|
f752490624 | ||
|
|
d196b66b4e | ||
|
|
d803a1d71e | ||
|
|
c75430cde2 | ||
|
|
f44c3531c7 | ||
|
|
596829bc77 | ||
|
|
096aeb0c54 | ||
|
|
1a12684557 | ||
|
|
998664acc3 | ||
|
|
c52b3fc4ad | ||
|
|
1fde3650ca | ||
|
|
57614f59e4 | ||
|
|
a95883f98b | ||
|
|
6cf18c33a1 | ||
|
|
232e6fbf71 | ||
|
|
d15731d5a4 | ||
|
|
45d7421e4f | ||
|
|
4d0aabfe6e | ||
|
|
db0e266fde | ||
|
|
6281561ab4 | ||
|
|
b981f0dc19 | ||
|
|
bc41429982 | ||
|
|
a31621cfde | ||
|
|
aa68224d63 | ||
|
|
b8413a21a3 | ||
|
|
af59196f19 | ||
|
|
84a966993f |
@@ -3,6 +3,8 @@ name: Build AppImage
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 23 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -47,10 +49,12 @@ jobs:
|
|||||||
arch: x86_64
|
arch: x86_64
|
||||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
|
||||||
openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
|
openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
|
||||||
|
appimagetool-sha: 'ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0'
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
|
||||||
openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
|
openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
|
||||||
|
appimagetool-sha: 'f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
@@ -142,6 +146,7 @@ jobs:
|
|||||||
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
|
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
|
||||||
--java-options "-Dcryptomator.buildNumber=\"appimage-${REV_NUM}\""
|
--java-options "-Dcryptomator.buildNumber=\"appimage-${REV_NUM}\""
|
||||||
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
|
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
|
||||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
||||||
--resource-dir dist/linux/resources
|
--resource-dir dist/linux/resources
|
||||||
- name: Patch Cryptomator.AppDir
|
- name: Patch Cryptomator.AppDir
|
||||||
@@ -165,7 +170,8 @@ jobs:
|
|||||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||||
- name: Download AppImageKit
|
- name: Download AppImageKit
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage
|
curl --silent --fail-with-body --proto "=https" -L "https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage
|
||||||
|
echo "${{ matrix.appimagetool-sha }} appimagetool.AppImage" | shasum -a256 --check
|
||||||
chmod +x appimagetool.AppImage
|
chmod +x appimagetool.AppImage
|
||||||
./appimagetool.AppImage --appimage-extract
|
./appimagetool.AppImage --appimage-extract
|
||||||
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
|
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
name: Build Debian Package
|
name: Build Debian Package
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 22 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
semver:
|
semver:
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
name: Create PR for flathub
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tag:
|
|
||||||
description: 'Release tag'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
get-version:
|
|
||||||
uses: ./.github/workflows/get-version.yml
|
|
||||||
with:
|
|
||||||
version: ${{ inputs.tag }}
|
|
||||||
tarball:
|
|
||||||
name: Determines tarball url and compute checksum
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [get-version]
|
|
||||||
if: github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
|
|
||||||
outputs:
|
|
||||||
url: ${{ steps.url.outputs.url}}
|
|
||||||
sha512: ${{ steps.sha512.outputs.sha512}}
|
|
||||||
steps:
|
|
||||||
- name: Determine tarball url
|
|
||||||
id: url
|
|
||||||
run: |
|
|
||||||
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz"
|
|
||||||
echo "url=${URL}" >> "$GITHUB_OUTPUT"
|
|
||||||
env:
|
|
||||||
TAG: ${{ inputs.tag || github.event.release.tag_name}}
|
|
||||||
- name: Download source tarball and compute checksum
|
|
||||||
id: sha512
|
|
||||||
run: |
|
|
||||||
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
|
|
||||||
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
|
|
||||||
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
|
|
||||||
flathub:
|
|
||||||
name: Create PR for flathub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [tarball, get-version]
|
|
||||||
env:
|
|
||||||
FLATHUB_PR_URL: tbd
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
repository: 'flathub/org.cryptomator.Cryptomator'
|
|
||||||
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
|
||||||
- name: Checkout release branch
|
|
||||||
run: |
|
|
||||||
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
|
|
||||||
- name: Update build file
|
|
||||||
run: |
|
|
||||||
sed -i -e 's/VERSION: [0-9]\+\.[0-9]\+\.[0-9]\+.*/VERSION: ${{ needs.get-version.outputs.semVerStr }}/g' org.cryptomator.Cryptomator.yaml
|
|
||||||
sed -i -e 's/sha512: [0-9A-Za-z_\+-]\{128\} #CRYPTOMATOR/sha512: ${{ needs.tarball.outputs.sha512 }} #CRYPTOMATOR/g' org.cryptomator.Cryptomator.yaml
|
|
||||||
sed -i -e 's;url: https://github.com/cryptomator/cryptomator/archive/refs/tags/[^[:blank:]]\+;url: ${{ needs.tarball.outputs.url }};g' org.cryptomator.Cryptomator.yaml
|
|
||||||
- name: Commit and push
|
|
||||||
run: |
|
|
||||||
git config user.name "${{ github.actor }}"
|
|
||||||
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
|
|
||||||
git config push.autoSetupRemote true
|
|
||||||
git stage .
|
|
||||||
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
|
|
||||||
git push
|
|
||||||
- name: Create pull request
|
|
||||||
run: |
|
|
||||||
printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update maven dependencies\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
|
|
||||||
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
|
|
||||||
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
|
||||||
- name: Slack Notification
|
|
||||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
||||||
SLACK_USERNAME: 'Cryptobot'
|
|
||||||
SLACK_ICON: false
|
|
||||||
SLACK_ICON_EMOJI: ':bot:'
|
|
||||||
SLACK_CHANNEL: 'cryptomator-desktop'
|
|
||||||
SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
|
|
||||||
SLACK_MESSAGE: "See <${{ env.FLATHUB_PR_URL }}|PR> on how to proceed.>."
|
|
||||||
SLACK_FOOTER: false
|
|
||||||
MSG_MINIMAL: true
|
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
name: Build flatpak
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
src-tag:
|
||||||
|
description: 'Source or Release tag'
|
||||||
|
required: false
|
||||||
|
create-pr:
|
||||||
|
description: 'Create Flathub PR'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'dependabot/**'
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/get-version.yml'
|
||||||
|
- '.github/workflows/linux-flatpak.yml'
|
||||||
|
- 'dist/linux/flatpak/**'
|
||||||
|
- 'dist/linux/common/**'
|
||||||
|
- 'dist/linux/resources/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
get-version:
|
||||||
|
uses: ./.github/workflows/get-version.yml
|
||||||
|
with:
|
||||||
|
version: ${{ inputs.src-tag }}
|
||||||
|
|
||||||
|
build-flatpak:
|
||||||
|
name: "Build flatpak"
|
||||||
|
needs: [get-version]
|
||||||
|
container:
|
||||||
|
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08
|
||||||
|
options: --privileged
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
variant:
|
||||||
|
- arch: x86_64
|
||||||
|
runner: ubuntu-24.04
|
||||||
|
- arch: aarch64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
runs-on: ${{ matrix.variant.runner }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
env:
|
||||||
|
SRC_GIT_SHA: ${{ inputs.src-tag || github.sha}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
repository: flathub/org.cryptomator.Cryptomator
|
||||||
|
submodules: true
|
||||||
|
- name: Checkout build script
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
path: build-scripts
|
||||||
|
- name: Checkout app source
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
path: cryptomator
|
||||||
|
ref: ${{ env.SRC_GIT_SHA }}
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Prepare build files
|
||||||
|
# using envsubst instead of yq to keep linebreaks
|
||||||
|
run: |
|
||||||
|
cp -r -f build-scripts/dist/linux/flatpak/* .
|
||||||
|
envsubst '$FLATPAK_VERSION $FLATPAK_REVISION $CRYPTOMATOR_SOURCE' < org.cryptomator.Cryptomator.TEMPLATE.yaml > org.cryptomator.Cryptomator.yaml
|
||||||
|
env:
|
||||||
|
FLATPAK_VERSION: ${{ needs.get-version.outputs.semVerNum }}
|
||||||
|
FLATPAK_REVISION: 1
|
||||||
|
CRYPTOMATOR_SOURCE: |-
|
||||||
|
type: git
|
||||||
|
path: cryptomator
|
||||||
|
commit: ${{ env.SRC_GIT_SHA }}
|
||||||
|
- name: Copy build script for upload
|
||||||
|
run: cp org.cryptomator.Cryptomator.yaml org.cryptomator.Cryptomator.${{matrix.variant.arch}}.yaml
|
||||||
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||||
|
with:
|
||||||
|
archive: false
|
||||||
|
if-no-files-found: error
|
||||||
|
path: |
|
||||||
|
org.cryptomator.Cryptomator.${{matrix.variant.arch}}.yaml
|
||||||
|
- uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb # SNAPSHOT due to using keep-build-dirs
|
||||||
|
with:
|
||||||
|
bundle: cryptomator.flatpak
|
||||||
|
manifest-path: org.cryptomator.Cryptomator.yaml
|
||||||
|
cache-key: flatpak-builder-${{ env.SRC_GIT_SHA }}
|
||||||
|
arch: ${{ matrix.variant.arch }}
|
||||||
|
keep-build-dirs: true
|
||||||
|
- name: Collect maven dependencies
|
||||||
|
working-directory: .flatpak-builder/build/cryptomator-1/.m2/repository/
|
||||||
|
run: |
|
||||||
|
find * -type f \( -iname '*.jar' -o -iname '*.pom' \) | sort -V > /tmp/maven-dependency-files.txt
|
||||||
|
grep -v '^org/openjfx/javafx-' /tmp/maven-dependency-files.txt > maven-dependency-files-common.txt
|
||||||
|
grep '^org/openjfx/javafx-' /tmp/maven-dependency-files.txt > maven-dependency-files-javafx.txt
|
||||||
|
- name: Update arch independent maven dependencies
|
||||||
|
run: |
|
||||||
|
(
|
||||||
|
cd .flatpak-builder/build/cryptomator-1/.m2/repository/
|
||||||
|
|
||||||
|
while IFS= read -r dependencyPath; do
|
||||||
|
dependencyName=$(dirname "$dependencyPath")
|
||||||
|
dependencySha=$(sha256sum "$dependencyPath" | cut -c 1-64)
|
||||||
|
cat <<EOF
|
||||||
|
- type: file
|
||||||
|
dest: .m2/repository/${dependencyName}
|
||||||
|
url: https://repo.maven.apache.org/maven2/${dependencyPath}
|
||||||
|
sha256: ${dependencySha}
|
||||||
|
EOF
|
||||||
|
done < maven-dependency-files-common.txt
|
||||||
|
) > maven-dependencies.yaml
|
||||||
|
- name: Update arch specific maven dependencies
|
||||||
|
run: |
|
||||||
|
(
|
||||||
|
cd .flatpak-builder/build/cryptomator-1/.m2/repository/
|
||||||
|
|
||||||
|
while IFS= read -r dependencyPath; do
|
||||||
|
dependencyName=$(dirname "$dependencyPath")
|
||||||
|
dependencySha=$(sha256sum "$dependencyPath" | cut -c 1-64)
|
||||||
|
cat <<EOF
|
||||||
|
- type: file
|
||||||
|
dest: .m2/repository/${dependencyName}
|
||||||
|
url: https://repo.maven.apache.org/maven2/${dependencyPath}
|
||||||
|
sha256: ${dependencySha}
|
||||||
|
only-arches: [${{ matrix.variant.arch }}]
|
||||||
|
EOF
|
||||||
|
done < maven-dependency-files-javafx.txt
|
||||||
|
) > javafx-maven-dependencies-${{ matrix.variant.arch }}.yaml
|
||||||
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||||
|
with:
|
||||||
|
name: maven-sources-${{ matrix.variant.arch }}
|
||||||
|
if-no-files-found: error
|
||||||
|
path: |
|
||||||
|
maven-dependencies.yaml
|
||||||
|
javafx-maven-dependencies-${{ matrix.variant.arch }}.yaml
|
||||||
|
|
||||||
|
verify-maven-sources:
|
||||||
|
name: Verify maven sources
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build-flatpak]
|
||||||
|
permissions:
|
||||||
|
contents: none
|
||||||
|
steps:
|
||||||
|
- name: Download updated maven aarch64 dependencies
|
||||||
|
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||||
|
with:
|
||||||
|
name: maven-sources-aarch64
|
||||||
|
path: mvn-src-aarch64
|
||||||
|
- name: Download updated maven x86_64 dependencies
|
||||||
|
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||||
|
with:
|
||||||
|
name: maven-sources-x86_64
|
||||||
|
path: mvn-src-x64
|
||||||
|
- name: Verify arch independent maven dependencies
|
||||||
|
run: cmp --silent mvn-src-aarch64/maven-dependencies.yaml mvn-src-x64/maven-dependencies.yaml
|
||||||
|
|
||||||
|
create-pr:
|
||||||
|
name: Create PR for flathub
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [get-version, verify-maven-sources]
|
||||||
|
if: (github.event_name == 'workflow_dispatch' && inputs.create-pr ) || (github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable')
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
env:
|
||||||
|
TARBALL_URL: 'https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name || inputs.src-tag }}.tar.gz'
|
||||||
|
steps:
|
||||||
|
- name: Check that input "src-tag" is actually a tag
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
run: |
|
||||||
|
if [ -z "$SRC_TAG" ]; then
|
||||||
|
echo '::error::Input "src-tag" must be set to create a Flathub PR'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
SRC_TAG: ${{ inputs.src-tag }}
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
repository: flathub/org.cryptomator.Cryptomator
|
||||||
|
submodules: true #TODO: Update submodule!
|
||||||
|
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
||||||
|
- name: Checkout release branch
|
||||||
|
run: |
|
||||||
|
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
path: cryptomator
|
||||||
|
- name: Download source tarball and compute checksum
|
||||||
|
id: sha512
|
||||||
|
run: |
|
||||||
|
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${TARBALL_URL} --output cryptomator.tar.gz
|
||||||
|
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
|
||||||
|
echo "value=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: Download updated maven aarch64 dependencies
|
||||||
|
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||||
|
with:
|
||||||
|
name: maven-sources-aarch64
|
||||||
|
path: mvn-src-aarch64
|
||||||
|
- name: Download updated maven x86_64 dependencies
|
||||||
|
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||||
|
with:
|
||||||
|
name: maven-sources-x86_64
|
||||||
|
path: mvn-src-x64
|
||||||
|
- name: Determine revision
|
||||||
|
id: revision
|
||||||
|
run: |
|
||||||
|
CURRENT_VERSION="$(yq '(.modules[] | select(.name == "cryptomator") | .build-options.env.VERSION)' org.cryptomator.Cryptomator.yaml)"
|
||||||
|
CURRENT_REVISION="$(yq '(.modules[] | select(.name == "cryptomator") | .build-options.env.REVISION_NO)' org.cryptomator.Cryptomator.yaml)"
|
||||||
|
|
||||||
|
if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REVISION" =~ ^[0-9]+$ ]]; then
|
||||||
|
NEXT_REVISION=$((CURRENT_REVISION + 1))
|
||||||
|
else
|
||||||
|
NEXT_REVISION=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "value=${NEXT_REVISION}" >> "$GITHUB_OUTPUT"
|
||||||
|
env:
|
||||||
|
TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }}
|
||||||
|
- name: Update build files
|
||||||
|
run: |
|
||||||
|
cp -r -f cryptomator/dist/linux/flatpak/* .
|
||||||
|
cp -r -f mvn-src-x64/* .
|
||||||
|
cp -r -f mvn-src-aarch64/* .
|
||||||
|
envsubst '$FLATPAK_VERSION $FLATPAK_REVISION $CRYPTOMATOR_SOURCE' < org.cryptomator.Cryptomator.TEMPLATE.yaml > org.cryptomator.Cryptomator.yaml
|
||||||
|
yq -i 'del(.modules[] | select(.name == "cryptomator") | .build-options.build-args)' org.cryptomator.Cryptomator.yaml
|
||||||
|
yq -i '(.modules[] | select(.name == "cryptomator") | .sources) += ["maven-dependencies.yaml", "javafx-maven-dependencies-x86_64.yaml", "javafx-maven-dependencies-aarch64.yaml"]' org.cryptomator.Cryptomator.yaml
|
||||||
|
env:
|
||||||
|
FLATPAK_VERSION: ${{ needs.get-version.outputs.semVerNum }}
|
||||||
|
FLATPAK_REVISION: ${{ steps.revision.outputs.value}}
|
||||||
|
CRYPTOMATOR_SOURCE: |-
|
||||||
|
type: archive
|
||||||
|
sha512: ${{steps.sha512.outputs.value}}
|
||||||
|
url: ${{ env.TARBALL_URL }}
|
||||||
|
- name: Commit and push
|
||||||
|
run: |
|
||||||
|
git config user.name "cryptobot"
|
||||||
|
git config user.email "cryptobot@users.noreply.github.com"
|
||||||
|
git config push.autoSetupRemote true
|
||||||
|
git stage org.cryptomator.Cryptomator.yaml maven-dependencies.yaml javafx-maven-dependencies-aarch64.yaml javafx-maven-dependencies-x86_64.yaml
|
||||||
|
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
|
||||||
|
git push
|
||||||
|
- name: Create pull request
|
||||||
|
id: create-pr
|
||||||
|
run: |
|
||||||
|
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
|
||||||
|
PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
|
||||||
|
echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_OUTPUT"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
||||||
|
- name: Slack Notification
|
||||||
|
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
||||||
|
SLACK_USERNAME: 'Cryptobot'
|
||||||
|
SLACK_ICON: false
|
||||||
|
SLACK_ICON_EMOJI: ':bot:'
|
||||||
|
SLACK_CHANNEL: 'cryptomator-desktop'
|
||||||
|
SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
|
||||||
|
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.FLATHUB_PR_URL }}|PR> on how to proceed."
|
||||||
|
SLACK_FOOTER: false
|
||||||
|
MSG_MINIMAL: true
|
||||||
@@ -3,6 +3,8 @@ name: Build Arch package
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 21 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ name: Build macOS .dmg for x64
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 20 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -125,7 +127,6 @@ jobs:
|
|||||||
--java-options "-Xmx256m"
|
--java-options "-Xmx256m"
|
||||||
--java-options "-Dfile.encoding=\"utf-8\""
|
--java-options "-Dfile.encoding=\"utf-8\""
|
||||||
--java-options "-Djava.net.useSystemProxies=true"
|
--java-options "-Djava.net.useSystemProxies=true"
|
||||||
--java-options "-Dapple.awt.enableTemplateImages=true"
|
|
||||||
--java-options "-Dsun.java2d.metal=true"
|
--java-options "-Dsun.java2d.metal=true"
|
||||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
||||||
@@ -138,6 +139,7 @@ jobs:
|
|||||||
--java-options "-Dcryptomator.showTrayIcon=true"
|
--java-options "-Dcryptomator.showTrayIcon=true"
|
||||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
||||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
|
||||||
--mac-package-identifier org.cryptomator
|
--mac-package-identifier org.cryptomator
|
||||||
--resource-dir dist/mac/resources
|
--resource-dir dist/mac/resources
|
||||||
- name: Patch Cryptomator.app
|
- name: Patch Cryptomator.app
|
||||||
@@ -248,7 +250,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
||||||
- name: Notarize .dmg
|
- name: Notarize .dmg
|
||||||
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
|
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize || github.event_name == 'schedule'
|
||||||
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
|
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
|
||||||
with:
|
with:
|
||||||
app-path: 'Cryptomator-*.dmg'
|
app-path: 'Cryptomator-*.dmg'
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ name: Build macOS .dmg for arm64
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 20 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -123,7 +125,6 @@ jobs:
|
|||||||
--java-options "-Xmx256m"
|
--java-options "-Xmx256m"
|
||||||
--java-options "-Dfile.encoding=\"utf-8\""
|
--java-options "-Dfile.encoding=\"utf-8\""
|
||||||
--java-options "-Djava.net.useSystemProxies=true"
|
--java-options "-Djava.net.useSystemProxies=true"
|
||||||
--java-options "-Dapple.awt.enableTemplateImages=true"
|
|
||||||
--java-options "-Dsun.java2d.metal=true"
|
--java-options "-Dsun.java2d.metal=true"
|
||||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
||||||
@@ -137,6 +138,7 @@ jobs:
|
|||||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
||||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
||||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
|
||||||
--mac-package-identifier org.cryptomator
|
--mac-package-identifier org.cryptomator
|
||||||
--resource-dir dist/mac/resources
|
--resource-dir dist/mac/resources
|
||||||
- name: Patch Cryptomator.app
|
- name: Patch Cryptomator.app
|
||||||
@@ -247,7 +249,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
|
||||||
- name: Notarize .dmg
|
- name: Notarize .dmg
|
||||||
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize
|
if: startsWith(github.ref, 'refs/tags/') || inputs.notarize || github.event_name == 'schedule'
|
||||||
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
|
uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3
|
||||||
with:
|
with:
|
||||||
app-path: 'Cryptomator-*.dmg'
|
app-path: 'Cryptomator-*.dmg'
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ name: Build Windows Installer
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 19 20 * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -157,6 +159,7 @@ jobs:
|
|||||||
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
|
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
|
||||||
--java-options "-Dcryptomator.disableUpdateCheck=false"
|
--java-options "-Dcryptomator.disableUpdateCheck=false"
|
||||||
--java-options "-XX:ErrorFile=C:/cryptomator/cryptomator_crash.log"
|
--java-options "-XX:ErrorFile=C:/cryptomator/cryptomator_crash.log"
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true"
|
||||||
--resource-dir dist/win/resources
|
--resource-dir dist/win/resources
|
||||||
--icon dist/win/resources/Cryptomator.ico
|
--icon dist/win/resources/Cryptomator.ico
|
||||||
--add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties"
|
--add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties"
|
||||||
@@ -192,7 +195,7 @@ jobs:
|
|||||||
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
|
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
|
||||||
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
|
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
|
||||||
- name: Sign DLLs with Azure Trusted Signing
|
- name: Sign DLLs with Azure Trusted Signing
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule'
|
||||||
uses: ./.github/actions/win-sign-action
|
uses: ./.github/actions/win-sign-action
|
||||||
with:
|
with:
|
||||||
base-dir: ${{ github.workspace }}\appdir
|
base-dir: ${{ github.workspace }}\appdir
|
||||||
@@ -201,17 +204,6 @@ jobs:
|
|||||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign DLLs with Actalis CodeSigner
|
|
||||||
if: inputs.sign || github.event_name == 'release'
|
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
|
||||||
with:
|
|
||||||
base-dir: 'appdir'
|
|
||||||
file-extensions: 'dll,exe,ps1'
|
|
||||||
recursive: true
|
|
||||||
sign-description: 'Cryptomator'
|
|
||||||
sign-url: 'https://cryptomator.org'
|
|
||||||
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
|
|
||||||
password: ${{ secrets.WIN_CODESIGN_PW }}
|
|
||||||
- name: Replace DLLs inside jars with signed ones
|
- name: Replace DLLs inside jars with signed ones
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
@@ -261,7 +253,7 @@ jobs:
|
|||||||
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
|
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
|
||||||
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
|
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
|
||||||
- name: Sign MSI with Azure Trusted Signing
|
- name: Sign MSI with Azure Trusted Signing
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule'
|
||||||
uses: ./.github/actions/win-sign-action
|
uses: ./.github/actions/win-sign-action
|
||||||
with:
|
with:
|
||||||
base-dir: ${{ github.workspace }}\installer
|
base-dir: ${{ github.workspace }}\installer
|
||||||
@@ -369,7 +361,7 @@ jobs:
|
|||||||
run: >
|
run: >
|
||||||
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
|
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
|
||||||
- name: Sign WiX burn engine with Azure Trusted Signing
|
- name: Sign WiX burn engine with Azure Trusted Signing
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule'
|
||||||
uses: ./.github/actions/win-sign-action
|
uses: ./.github/actions/win-sign-action
|
||||||
with:
|
with:
|
||||||
base-dir: ${{ github.workspace }}\tmp
|
base-dir: ${{ github.workspace }}\tmp
|
||||||
@@ -379,21 +371,11 @@ jobs:
|
|||||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign burn engine with Actalis CodeSigner
|
|
||||||
if: inputs.sign || github.event_name == 'release'
|
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
|
||||||
with:
|
|
||||||
base-dir: 'tmp'
|
|
||||||
file-extensions: 'exe'
|
|
||||||
sign-description: 'Cryptomator Bundle Installer'
|
|
||||||
sign-url: 'https://cryptomator.org'
|
|
||||||
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
|
|
||||||
password: ${{ secrets.WIN_CODESIGN_PW }}
|
|
||||||
- name: Reattach signed burn engine to installer
|
- name: Reattach signed burn engine to installer
|
||||||
run: >
|
run: >
|
||||||
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
|
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
|
||||||
- name: Sign EXE installer with Azure Trusted Signing
|
- name: Sign EXE installer with Azure Trusted Signing
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule'
|
||||||
uses: ./.github/actions/win-sign-action
|
uses: ./.github/actions/win-sign-action
|
||||||
with:
|
with:
|
||||||
base-dir: ${{ github.workspace }}\installer
|
base-dir: ${{ github.workspace }}\installer
|
||||||
@@ -403,16 +385,6 @@ jobs:
|
|||||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign installer with Actalis CodeSigner
|
|
||||||
if: inputs.sign || github.event_name == 'release'
|
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
|
||||||
with:
|
|
||||||
base-dir: 'installer'
|
|
||||||
file-extensions: 'exe'
|
|
||||||
sign-description: 'Cryptomator Bundle Installer'
|
|
||||||
sign-url: 'https://cryptomator.org'
|
|
||||||
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
|
|
||||||
password: ${{ secrets.WIN_CODESIGN_PW }}
|
|
||||||
- name: Add possible alpha/beta tags to installer name
|
- name: Add possible alpha/beta tags to installer name
|
||||||
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
|
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
|
||||||
- name: Create detached GPG signature with key 615D449FE6E6A235
|
- name: Create detached GPG signature with key 615D449FE6E6A235
|
||||||
@@ -479,7 +451,7 @@ jobs:
|
|||||||
- name: Slack Notification
|
- name: Slack Notification
|
||||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
||||||
env:
|
env:
|
||||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
||||||
SLACK_USERNAME: 'Cryptobot'
|
SLACK_USERNAME: 'Cryptobot'
|
||||||
SLACK_ICON: false
|
SLACK_ICON: false
|
||||||
SLACK_ICON_EMOJI: ':bot:'
|
SLACK_ICON_EMOJI: ':bot:'
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator-Dev/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator-Dev/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/.config/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/.config/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/.local/share/Cryptomator-Dev/logs" -Dcryptomator.pluginDir="@{userhome}/.local/share/Cryptomator-Dev/plugins" -Dcryptomator.mountPointsDir="@{userhome}/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dcryptomator.hub.enableTrustOnFirstUse=true -Dfuse.experimental="true" -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator" -Dcryptomator.pluginDir="@{appdata}/Cryptomator/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.integrationsWin.windowsHelloKeychainPaths="@{appdata}/Cryptomator/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator" -Dcryptomator.pluginDir="@{appdata}/Cryptomator/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.integrationsWin.windowsHelloKeychainPaths="@{appdata}/Cryptomator/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator-Dev" -Dcryptomator.pluginDir="@{appdata}/Cryptomator-Dev/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.integrationsWin.windowsHelloKeychainPaths="@{appdata}/Cryptomator-Dev/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/windowsHelloKeychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="@{localappdata}/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{localappdata}/Cryptomator-Dev" -Dcryptomator.pluginDir="@{appdata}/Cryptomator-Dev/Plugins" -Dcryptomator.integrationsWin.keychainPaths="@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.integrationsWin.windowsHelloKeychainPaths="@{appdata}/Cryptomator-Dev/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/windowsHelloKeychain.json" -Dcryptomator.p12Path="@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
</envs>
|
</envs>
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
</envs>
|
</envs>
|
||||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator-Dev" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Library/Application Support/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator-Dev" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Library/Application Support/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Dcryptomator.hub.enableTrustOnFirstUse=true -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
@@ -7,6 +7,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
The changelog starts with version 1.19.0.
|
The changelog starts with version 1.19.0.
|
||||||
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
|
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
|
||||||
|
|
||||||
|
|
||||||
|
## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.19.1...HEAD)
|
||||||
|
|
||||||
|
No changes yet.
|
||||||
|
|
||||||
|
|
||||||
|
## [1.19.2](https://github.com/cryptomator/cryptomator/releases/1.19.2) - 2026-03-20
|
||||||
|
|
||||||
|
### Security
|
||||||
|
* Cryptomamtor Hub Vaults: Additional patch for (#4179, [GHSA-34rf-rwr3-7g43](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-34rf-rwr3-7g43))
|
||||||
|
|
||||||
|
|
||||||
|
## [1.19.1](https://github.com/cryptomator/cryptomator/releases/1.19.1) - 2026-03-12
|
||||||
|
|
||||||
|
### Security
|
||||||
|
* Cryptomamtor Hub Vaults: Fixed possible man-in-the-middle attack with tampered vault config (#4179, [GHSA-34rf-rwr3-7g43](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-34rf-rwr3-7g43))
|
||||||
|
* Disallow unencrypted http connections to hub by default ([CVE-2026-32309](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-vv33-h7qx-c264))
|
||||||
|
* Disallow loading of masterkey file from arbitrary paths (#4180, [CVE-2026-32310](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-5phc-5pfx-hr52))
|
||||||
|
* Fixed not-configured plugin directory does not disable plugin search ([#4176](https://github.com/cryptomator/cryptomator/pull/4176))
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Trust on first use, adding new config properties `cryptomator.hub.allowedHosts` and `cryptomator.hub.enableTrustOnFirstUse` (#4179)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Fixed Finder window opens twice when revealing vault on macOS ([#4177](https://github.com/cryptomator/cryptomator/pull/4177))
|
||||||
|
* Fixed app does not start due to secret service detection failure on Linux ([#4175](https://github.com/cryptomator/cryptomator/pull/4175))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Pin version of appimagetool([#4181](https://github.com/cryptomator/cryptomator/pull/4181))
|
||||||
|
* Updated translations
|
||||||
|
* Updated dependencies:
|
||||||
|
* `org.cryptomator:integrations-api` from 1.8.0-beta1 to 1.8.0
|
||||||
|
* `org.cryptomator:integrations-linux` from 1.7.0-beta4 to 1.7.0
|
||||||
|
* `org.cryptomator:integrations-mac` from 1.5.0-beta3 to 1.5.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.19.0](https://github.com/cryptomator/cryptomator/releases/tag/1.19.0) - 2026-03-09
|
## [1.19.0](https://github.com/cryptomator/cryptomator/releases/tag/1.19.0) - 2026-03-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Vendored
+2
-1
@@ -99,6 +99,7 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
|
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
|
||||||
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
|
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
|
||||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
|
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
|
||||||
--resource-dir ../resources
|
--resource-dir ../resources
|
||||||
|
|
||||||
# transform AppDir
|
# transform AppDir
|
||||||
@@ -123,7 +124,7 @@ ln -s org.cryptomator.Cryptomator.metainfo.xml Cryptomator.AppDir/usr/share/meta
|
|||||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||||
|
|
||||||
# load AppImageTool
|
# load AppImageTool
|
||||||
curl -L https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage
|
curl -L https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-${CPU_ARCH}.AppImage -o /tmp/appimagetool.AppImage
|
||||||
chmod +x /tmp/appimagetool.AppImage
|
chmod +x /tmp/appimagetool.AppImage
|
||||||
|
|
||||||
# create AppImage
|
# create AppImage
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
<url type="faq">https://community.cryptomator.org/c/kb/faq</url>
|
<url type="faq">https://community.cryptomator.org/c/kb/faq</url>
|
||||||
<url type="help">https://docs.cryptomator.org/</url>
|
<url type="help">https://docs.cryptomator.org/</url>
|
||||||
<url type="translate">https://translate.cryptomator.org</url>
|
<url type="translate">https://translate.cryptomator.org</url>
|
||||||
|
<url type="vcs-browser">https://github.com/cryptomator/cryptomator</url>
|
||||||
|
|
||||||
<developer id="de.skymatic">
|
<developer id="de.skymatic">
|
||||||
<name>Skymatic GmbH</name>
|
<name>Skymatic GmbH</name>
|
||||||
@@ -83,6 +84,12 @@
|
|||||||
</content_rating>
|
</content_rating>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release date="2026-03-20" version="1.19.2">
|
||||||
|
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.2</url>
|
||||||
|
</release>
|
||||||
|
<release date="2026-03-12" version="1.19.1">
|
||||||
|
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.1</url>
|
||||||
|
</release>
|
||||||
<release date="2026-03-09" version="1.19.0">
|
<release date="2026-03-09" version="1.19.0">
|
||||||
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.0</url>
|
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.0</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
Vendored
+1
@@ -64,6 +64,7 @@ override_dh_auto_build:
|
|||||||
--java-options "-Dcryptomator.disableUpdateCheck=\"${DISABLE_UPDATE_CHECK}\"" \
|
--java-options "-Dcryptomator.disableUpdateCheck=\"${DISABLE_UPDATE_CHECK}\"" \
|
||||||
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
|
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
|
||||||
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
|
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
|
||||||
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
|
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
|
||||||
--resource-dir resources \
|
--resource-dir resources \
|
||||||
--verbose
|
--verbose
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# From: https://gitlab.gnome.org/GNOME/gnome-builder/-/blob/main/build-aux/flatpak/fusermount-wrapper.sh
|
||||||
|
|
||||||
|
if [ -z "$_FUSE_COMMFD" ]; then
|
||||||
|
FD_ARGS=
|
||||||
|
else
|
||||||
|
FD_ARGS="--env=_FUSE_COMMFD=${_FUSE_COMMFD} --forward-fd=${_FUSE_COMMFD}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e /proc/self/fd/3 ] && [ 3 != "$_FUSE_COMMFD" ]; then
|
||||||
|
FD_ARGS="$FD_ARGS --forward-fd=3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec flatpak-spawn --host --forward-fd=1 --forward-fd=2 $FD_ARGS fusermount3 "$@"
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
app-id: org.cryptomator.Cryptomator
|
||||||
|
command: cryptomator
|
||||||
|
runtime: org.freedesktop.Platform
|
||||||
|
runtime-version: '25.08'
|
||||||
|
sdk: org.freedesktop.Sdk
|
||||||
|
separate-locales: false
|
||||||
|
finish-args:
|
||||||
|
# Required for FUSE, see https://github.com/flathub/org.cryptomator.Cryptomator/pull/68#issuecomment-1935136502
|
||||||
|
- --device=all
|
||||||
|
# Set the PATH environment variable in the application, as flatpak is resetting the shell's PATH
|
||||||
|
- --env=PATH=/app/bin/:/usr/bin/
|
||||||
|
# Allow filesystem access to the user's home dir
|
||||||
|
# Needed to manage vaults there
|
||||||
|
- --filesystem=home
|
||||||
|
# Reading system certificates
|
||||||
|
- --filesystem=host-etc:ro
|
||||||
|
# Allow access to the XDG data directory
|
||||||
|
# Needed to connect to KeePassXC's UNIX domain socket
|
||||||
|
- --filesystem=xdg-run/org.keepassxc.KeePassXC.BrowserServer
|
||||||
|
- --filesystem=xdg-run/app/org.keepassxc.KeePassXC/
|
||||||
|
# Share IPC namespace with the host, without it the X11 shared memory extension will not work
|
||||||
|
- --share=ipc
|
||||||
|
# Allow access to the network
|
||||||
|
- --share=network
|
||||||
|
# Show windows using X11
|
||||||
|
- --socket=x11
|
||||||
|
# Needed to reveal encrypted files
|
||||||
|
- --talk-name=org.freedesktop.FileManager1
|
||||||
|
# Run any command on the host
|
||||||
|
# Needed to spawn fusermount on the host
|
||||||
|
- --talk-name=org.freedesktop.Flatpak
|
||||||
|
# Allow desktop notifications
|
||||||
|
- --talk-name=org.freedesktop.Notifications
|
||||||
|
# Allow access to the GNOME secret service API and to talk to the GNOME keyring daemon
|
||||||
|
- --talk-name=org.freedesktop.secrets
|
||||||
|
- --talk-name=org.gnome.keyring
|
||||||
|
# Allow to talk to the KDE kwallet daemon
|
||||||
|
- --talk-name=org.kde.kwalletd5
|
||||||
|
- --talk-name=org.kde.kwalletd6
|
||||||
|
# Needed to talk to the gvfs daemons over D-Bus and list mounts using the GIO APIs
|
||||||
|
- --talk-name=org.gtk.vfs.*
|
||||||
|
# Allow access to appindicator icons
|
||||||
|
- --talk-name=org.ayatana
|
||||||
|
# Allow access to appindicator icons on KDE
|
||||||
|
- --talk-name=org.kde.StatusNotifierWatcher
|
||||||
|
cleanup:
|
||||||
|
- /include
|
||||||
|
- /lib/pkgconfig
|
||||||
|
modules:
|
||||||
|
- shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json
|
||||||
|
- name: libfuse
|
||||||
|
buildsystem: meson
|
||||||
|
config-opts:
|
||||||
|
- -Dexamples=false
|
||||||
|
- -Dinitscriptdir=
|
||||||
|
- -Duseroot=false
|
||||||
|
- -Dtests=false
|
||||||
|
# don't install rules on the host
|
||||||
|
- -Dudevrulesdir=/tmp/
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://github.com/libfuse/libfuse/releases/download/fuse-3.16.2/fuse-3.16.2.tar.gz
|
||||||
|
sha256: f797055d9296b275e981f5f62d4e32e089614fc253d1ef2985851025b8a0ce87
|
||||||
|
x-checker-data:
|
||||||
|
type: anitya
|
||||||
|
project-id: 861
|
||||||
|
url-template: https://github.com/libfuse/libfuse/releases/download/fuse-$version/fuse-$version.tar.gz
|
||||||
|
versions: {<: '3.17.0'}
|
||||||
|
- name: host-command-wrapper
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- install fusermount-wrapper.sh /app/bin/fusermount3
|
||||||
|
sources:
|
||||||
|
- type: file
|
||||||
|
path: build-aux/fusermount-wrapper.sh
|
||||||
|
- name: cryptomator
|
||||||
|
buildsystem: simple
|
||||||
|
build-options:
|
||||||
|
build-args:
|
||||||
|
- --share=network
|
||||||
|
env:
|
||||||
|
PATH: /app/bin:/usr/bin
|
||||||
|
MAVEN_OPTS: -Dmaven.repo.local=.m2/repository
|
||||||
|
JAVA_HOME: jdk
|
||||||
|
JMODS_PATH: jmods
|
||||||
|
VERSION: $FLATPAK_VERSION
|
||||||
|
REVISION_NO: '$FLATPAK_REVISION'
|
||||||
|
build-commands:
|
||||||
|
# Setup Java
|
||||||
|
- tar xvfz jdk.tar.gz --transform 's!^[^/]*!jdk!'
|
||||||
|
- mkdir jmods
|
||||||
|
- unzip -j openjfx.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods
|
||||||
|
# Setup Maven
|
||||||
|
- mkdir maven
|
||||||
|
- tar xf maven.tar.gz --strip-components=1 --exclude=jansi-native --directory=maven
|
||||||
|
# Build project
|
||||||
|
- maven/bin/mvn clean package -DskipTests -P"linux-$(uname -m)"
|
||||||
|
- cp target/cryptomator-*.jar target/mods
|
||||||
|
- cd target
|
||||||
|
- $JAVA_HOME/bin/jlink
|
||||||
|
--output runtime
|
||||||
|
--module-path $JMODS_PATH
|
||||||
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
|
||||||
|
--no-header-files
|
||||||
|
--no-man-pages
|
||||||
|
--strip-debug
|
||||||
|
--compress=zip-0
|
||||||
|
- $JAVA_HOME/bin/jpackage
|
||||||
|
--type app-image
|
||||||
|
--runtime-image runtime
|
||||||
|
--input target/libs
|
||||||
|
--module-path target/mods
|
||||||
|
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
|
||||||
|
--dest .
|
||||||
|
--name Cryptomator
|
||||||
|
--vendor 'Skymatic GmbH'
|
||||||
|
--copyright '(C) 2016 - 2025 Skymatic GmbH'
|
||||||
|
--java-options '--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator'
|
||||||
|
--java-options "--sun-misc-unsafe-memory-access=allow"
|
||||||
|
--java-options '-Xss5m'
|
||||||
|
--java-options '-Xmx256m'
|
||||||
|
--java-options '-Dfile.encoding='utf-8''
|
||||||
|
--java-options '-Djava.net.useSystemProxies=true'
|
||||||
|
--java-options "-Dcryptomator.appVersion='${VERSION}'"
|
||||||
|
--java-options "-Dcryptomator.buildNumber='flatpak-${REVISION_NO}'"
|
||||||
|
--java-options '-Dcryptomator.ipcSocketPath='@{userhome}/.config/Cryptomator/ipc.socket''
|
||||||
|
--java-options '-Dcryptomator.adminConfigPath='/run/host/etc/cryptomator/config.properties''
|
||||||
|
--java-options '-Dcryptomator.logDir='@{userhome}/.local/share/Cryptomator/logs''
|
||||||
|
--java-options '-Dcryptomator.mountPointsDir='@{userhome}/.local/share/Cryptomator/mnt''
|
||||||
|
--java-options '-Dcryptomator.pluginDir='@{userhome}/.local/share/Cryptomator/plugins''
|
||||||
|
--java-options '-Dcryptomator.p12Path='@{userhome}/.config/Cryptomator/key.p12''
|
||||||
|
--java-options '-Dcryptomator.settingsPath='@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json''
|
||||||
|
--java-options '-Dcryptomator.showTrayIcon=true'
|
||||||
|
--java-options '-Dcryptomator.updateMechanism=org.cryptomator.linux.update.FlatpakUpdater'
|
||||||
|
--java-options '-Dcryptomator.networking.truststore.p12Path='/run/host/etc/cryptomator/certs.p12''
|
||||||
|
--java-options '-Dcryptomator.hub.enableTrustOnFirstUse=true'
|
||||||
|
--app-version "${VERSION}.${REVISION_NO}"
|
||||||
|
--verbose
|
||||||
|
- cp -R Cryptomator /app/
|
||||||
|
- ln -s /app/Cryptomator/bin/Cryptomator /app/bin/cryptomator
|
||||||
|
- cp -R /app/lib/* /app/Cryptomator/lib/app/
|
||||||
|
- install -D -m0644 -t /app/share/applications/ dist/linux/common/org.cryptomator.Cryptomator.desktop
|
||||||
|
- install -D -m0644 -t /app/share/icons/hicolor/scalable/apps/ dist/linux/common/org.cryptomator.Cryptomator.svg
|
||||||
|
- install -D -m0644 -T dist/linux/common/org.cryptomator.Cryptomator.tray.svg /app/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg
|
||||||
|
- install -D -m0644 -T dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg /app/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg
|
||||||
|
- install -D -m0644 -t /app/share/metainfo/ dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml
|
||||||
|
sources:
|
||||||
|
- $CRYPTOMATOR_SOURCE
|
||||||
|
- type: file
|
||||||
|
dest-filename: jdk.tar.gz
|
||||||
|
only-arches:
|
||||||
|
- x86_64
|
||||||
|
url: https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.2%2B10/OpenJDK25U-jdk_x64_linux_hotspot_25.0.2_10.tar.gz
|
||||||
|
sha512: 29043fde119a031c2ca8d57aed445fedd9e7f74608fcdc7a809076ba84cfd1c31f08de2ecccf352e159fdcd1cae172395ed46363007552ff242057826c81ab3a
|
||||||
|
- type: file
|
||||||
|
dest-filename: jdk.tar.gz
|
||||||
|
only-arches:
|
||||||
|
- aarch64
|
||||||
|
url: https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.2%2B10/OpenJDK25U-jdk_aarch64_linux_hotspot_25.0.2_10.tar.gz
|
||||||
|
sha512: f1d3ccec3e1f1bed9d632f14b9223709d6e5c2e0d922125d068870dd3016492a2ca8f08924d4a9d0dc5eb2159fa09efee366a748fd0093475baf29e5c70c781a
|
||||||
|
- type: file
|
||||||
|
dest-filename: openjfx.zip
|
||||||
|
only-arches:
|
||||||
|
- x86_64
|
||||||
|
url: https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip
|
||||||
|
sha512: 21f550217101c513f9eb1d7947eba30cb79618238e6539ce770e54e84b01574cdaeba40af602391145f163dd8e43e3794395467413152f13ffffeff948b0ca1b
|
||||||
|
- type: file
|
||||||
|
dest-filename: openjfx.zip
|
||||||
|
only-arches:
|
||||||
|
- aarch64
|
||||||
|
url: https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip
|
||||||
|
sha512: a9268409b3803e386490bf1319d0f0a14173cebe862c12254cd51b430ee0a297437d9e38d5ebeae0da8899be898b312b103330d09dcfd3e63c1e7d15f2f14311
|
||||||
|
- type: file
|
||||||
|
dest-filename: maven.tar.gz
|
||||||
|
url: https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.13/apache-maven-3.9.13-bin.tar.gz
|
||||||
|
sha512: d9ccd44ba2991586e359c29eb86780ae8ff4ec1b88b0b8af3af074803472690cf2017782a9c4401343c62cbcd056231db9612e1e551cbd9747c21746d732c015
|
||||||
|
x-checker-data:
|
||||||
|
type: anitya
|
||||||
|
project-id: 1894
|
||||||
|
stable-only: true
|
||||||
|
url-template: https://repo1.maven.org/maven2/org/apache/maven/apache-maven/$version/apache-maven-$version-bin.tar.gz
|
||||||
|
versions: {<: '4.0'}
|
||||||
Vendored
+1
@@ -94,6 +94,7 @@ build() {
|
|||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
|
||||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
--java-options "-Dcryptomator.showTrayIcon=true" \
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
|
||||||
--app-version "${pkgver//_*/}" \
|
--app-version "${pkgver//_*/}" \
|
||||||
--verbose
|
--verbose
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -111,7 +111,6 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
--java-options "-Xmx256m" \
|
--java-options "-Xmx256m" \
|
||||||
--java-options "-Dfile.encoding=\"utf-8\"" \
|
--java-options "-Dfile.encoding=\"utf-8\"" \
|
||||||
--java-options "-Djava.net.useSystemProxies=true" \
|
--java-options "-Djava.net.useSystemProxies=true" \
|
||||||
--java-options "-Dapple.awt.enableTemplateImages=true" \
|
|
||||||
--java-options "-Dsun.java2d.metal=true" \
|
--java-options "-Dsun.java2d.metal=true" \
|
||||||
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
|
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" \
|
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" \
|
||||||
@@ -125,6 +124,7 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
--java-options "-Dcryptomator.showTrayIcon=true" \
|
||||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" \
|
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" \
|
||||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
|
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
|
||||||
|
--java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" \
|
||||||
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
|
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
|
||||||
--resource-dir ../resources
|
--resource-dir ../resources
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
@@ -167,6 +167,7 @@ $javaOptions = @(
|
|||||||
"--java-options", "-Dcryptomator.showTrayIcon=true"
|
"--java-options", "-Dcryptomator.showTrayIcon=true"
|
||||||
"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`""
|
"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`""
|
||||||
"--java-options", "-Dcryptomator.disableUpdateCheck=false"
|
"--java-options", "-Dcryptomator.disableUpdateCheck=false"
|
||||||
|
"--java-options", "-Dcryptomator.hub.enableTrustOnFirstUse=true"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.cryptomator</groupId>
|
<groupId>org.cryptomator</groupId>
|
||||||
<artifactId>cryptomator</artifactId>
|
<artifactId>cryptomator</artifactId>
|
||||||
<version>1.19.0</version>
|
<version>1.20.0-SNAPSHOT</version>
|
||||||
<name>Cryptomator Desktop App</name>
|
<name>Cryptomator Desktop App</name>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
@@ -35,10 +35,10 @@
|
|||||||
<!-- cryptomator dependencies -->
|
<!-- cryptomator dependencies -->
|
||||||
<cryptomator.cryptofs.version>2.10.0</cryptomator.cryptofs.version>
|
<cryptomator.cryptofs.version>2.10.0</cryptomator.cryptofs.version>
|
||||||
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
|
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
|
||||||
<cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version>
|
<cryptomator.integrations.version>1.8.0</cryptomator.integrations.version>
|
||||||
<cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
|
<cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
|
||||||
<cryptomator.integrations.mac.version>1.5.0-beta3</cryptomator.integrations.mac.version>
|
<cryptomator.integrations.mac.version>1.5.0-SNAPSHOT</cryptomator.integrations.mac.version>
|
||||||
<cryptomator.integrations.linux.version>1.7.0-beta4</cryptomator.integrations.linux.version>
|
<cryptomator.integrations.linux.version>1.7.0</cryptomator.integrations.linux.version>
|
||||||
<cryptomator.fuse.version>6.0.1</cryptomator.fuse.version>
|
<cryptomator.fuse.version>6.0.1</cryptomator.fuse.version>
|
||||||
<cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
|
<cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
|
||||||
<cryptomator.webdav-servlet.version>1.2.12</cryptomator.webdav-servlet.version>
|
<cryptomator.webdav-servlet.version>1.2.12</cryptomator.webdav-servlet.version>
|
||||||
@@ -527,11 +527,57 @@
|
|||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>linux</id>
|
<id>linux-aarch64</id>
|
||||||
<activation>
|
<activation>
|
||||||
<os>
|
<os>
|
||||||
<family>unix</family>
|
<family>unix</family>
|
||||||
<name>Linux</name>
|
<name>Linux</name>
|
||||||
|
<arch>aarch64</arch>
|
||||||
|
</os>
|
||||||
|
<property>
|
||||||
|
<name>idea.version</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.cryptomator</groupId>
|
||||||
|
<artifactId>integrations-linux</artifactId>
|
||||||
|
<version>${cryptomator.integrations.linux.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-base</artifactId>
|
||||||
|
<version>${javafx.version}</version>
|
||||||
|
<classifier>linux-aarch64</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-graphics</artifactId>
|
||||||
|
<version>${javafx.version}</version>
|
||||||
|
<classifier>linux-aarch64</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-controls</artifactId>
|
||||||
|
<version>${javafx.version}</version>
|
||||||
|
<classifier>linux-aarch64</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-fxml</artifactId>
|
||||||
|
<version>${javafx.version}</version>
|
||||||
|
<classifier>linux-aarch64</classifier>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>linux-x86_64</id>
|
||||||
|
<activation>
|
||||||
|
<os>
|
||||||
|
<family>unix</family>
|
||||||
|
<name>Linux</name>
|
||||||
|
<arch>amd64</arch>
|
||||||
</os>
|
</os>
|
||||||
<property>
|
<property>
|
||||||
<name>idea.version</name>
|
<name>idea.version</name>
|
||||||
|
|||||||
@@ -9,10 +9,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Spliterator;
|
import java.util.Spliterator;
|
||||||
import java.util.Spliterators;
|
import java.util.Spliterators;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
@@ -20,20 +23,22 @@ public class Environment {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
|
||||||
private static final int DEFAULT_MIN_PW_LENGTH = 8;
|
private static final int DEFAULT_MIN_PW_LENGTH = 8;
|
||||||
private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
|
public static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
|
||||||
private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
|
public static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
|
||||||
private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
|
public static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
|
||||||
private static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
|
public static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
|
||||||
private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
|
public static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
|
||||||
private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
|
public static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
|
||||||
private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
|
public static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
|
||||||
private static final String MOUNTPOINT_DIR_PROP_NAME = "cryptomator.mountPointsDir";
|
public static final String MOUNTPOINT_DIR_PROP_NAME = "cryptomator.mountPointsDir";
|
||||||
private static final String MIN_PW_LENGTH_PROP_NAME = "cryptomator.minPwLength";
|
public static final String MIN_PW_LENGTH_PROP_NAME = "cryptomator.minPwLength";
|
||||||
private static final String APP_VERSION_PROP_NAME = "cryptomator.appVersion";
|
public static final String APP_VERSION_PROP_NAME = "cryptomator.appVersion";
|
||||||
private static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
|
public static final String BUILD_NUMBER_PROP_NAME = "cryptomator.buildNumber";
|
||||||
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
|
public static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
|
||||||
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
|
public static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
|
||||||
private static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
|
public static final String DISABLE_UPDATE_CHECK_PROP_NAME = "cryptomator.disableUpdateCheck";
|
||||||
|
public static final String HUB_ALLOWED_HOSTS_PROP_NAME = "cryptomator.hub.allowedHosts";
|
||||||
|
public static final String HUB_TOFU_PROP_NAME = "cryptomator.hub.enableTrustOnFirstUse";
|
||||||
|
|
||||||
private Environment() {}
|
private Environment() {}
|
||||||
|
|
||||||
@@ -57,6 +62,8 @@ public class Environment {
|
|||||||
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
|
logCryptomatorSystemProperty(PLUGIN_DIR_PROP_NAME);
|
||||||
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
|
logCryptomatorSystemProperty(TRAY_ICON_PROP_NAME);
|
||||||
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME);
|
logCryptomatorSystemProperty(DISABLE_UPDATE_CHECK_PROP_NAME);
|
||||||
|
logCryptomatorSystemProperty(HUB_ALLOWED_HOSTS_PROP_NAME);
|
||||||
|
logCryptomatorSystemProperty(HUB_TOFU_PROP_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Environment getInstance() {
|
public static Environment getInstance() {
|
||||||
@@ -145,6 +152,18 @@ public class Environment {
|
|||||||
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
|
return Boolean.getBoolean(DISABLE_UPDATE_CHECK_PROP_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> hubAllowedHosts() {
|
||||||
|
var allowedHubHostsString = System.getProperty(HUB_ALLOWED_HOSTS_PROP_NAME, "");
|
||||||
|
return Arrays.stream(allowedHubHostsString.split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(Predicate.not(String::isEmpty))
|
||||||
|
.collect(Collectors.toUnmodifiableSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hubTrustOnFirstUse() {
|
||||||
|
return Boolean.getBoolean(HUB_TOFU_PROP_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
private Optional<Path> getPath(String propertyName) {
|
private Optional<Path> getPath(String propertyName) {
|
||||||
String value = System.getProperty(propertyName);
|
String value = System.getProperty(propertyName);
|
||||||
return Optional.ofNullable(value).map(Paths::get);
|
return Optional.ofNullable(value).map(Paths::get);
|
||||||
|
|||||||
@@ -24,9 +24,12 @@ import javafx.beans.property.SimpleStringProperty;
|
|||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.ObservableSet;
|
||||||
import javafx.geometry.NodeOrientation;
|
import javafx.geometry.NodeOrientation;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
|
|
||||||
@@ -78,6 +81,7 @@ public class Settings {
|
|||||||
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
||||||
public final ObjectProperty<Path> previouslyUsedVaultDirectory;
|
public final ObjectProperty<Path> previouslyUsedVaultDirectory;
|
||||||
public final StringProperty lastUpdateAttemptedByVersion;
|
public final StringProperty lastUpdateAttemptedByVersion;
|
||||||
|
public final ObservableSet<String> trustedHosts;
|
||||||
|
|
||||||
public static Settings create(SettingsProvider provider, Environment env) {
|
public static Settings create(SettingsProvider provider, Environment env) {
|
||||||
var defaults = new SettingsJson();
|
var defaults = new SettingsJson();
|
||||||
@@ -118,6 +122,7 @@ public class Settings {
|
|||||||
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
|
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
|
||||||
this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
|
this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
|
||||||
this.lastUpdateAttemptedByVersion = new SimpleStringProperty(this, "lastUpdateAttemptedByVersion", json.lastUpdateAttemptedByVersion);
|
this.lastUpdateAttemptedByVersion = new SimpleStringProperty(this, "lastUpdateAttemptedByVersion", json.lastUpdateAttemptedByVersion);
|
||||||
|
this.trustedHosts = FXCollections.observableSet(json.trustedHosts);
|
||||||
|
|
||||||
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
|
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
|
||||||
|
|
||||||
@@ -149,6 +154,7 @@ public class Settings {
|
|||||||
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
|
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
|
||||||
previouslyUsedVaultDirectory.addListener(this::somethingChanged);
|
previouslyUsedVaultDirectory.addListener(this::somethingChanged);
|
||||||
lastUpdateAttemptedByVersion.addListener(this::somethingChanged);
|
lastUpdateAttemptedByVersion.addListener(this::somethingChanged);
|
||||||
|
trustedHosts.addListener(this::somethingChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@@ -207,6 +213,7 @@ public class Settings {
|
|||||||
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
|
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
|
||||||
json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
|
json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
|
||||||
json.lastUpdateAttemptedByVersion = lastUpdateAttemptedByVersion.get();
|
json.lastUpdateAttemptedByVersion = lastUpdateAttemptedByVersion.get();
|
||||||
|
json.trustedHosts = Set.copyOf(trustedHosts);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,23 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||||
|
import com.fasterxml.jackson.annotation.Nulls;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
class SettingsJson {
|
class SettingsJson {
|
||||||
|
|
||||||
@JsonProperty("directories")
|
@JsonProperty("directories")
|
||||||
List<VaultSettingsJson> directories = List.of();
|
@JsonSetter(nulls = Nulls.AS_EMPTY)
|
||||||
|
List<VaultSettingsJson> directories = new ArrayList<>();
|
||||||
|
|
||||||
@JsonProperty("writtenByVersion")
|
@JsonProperty("writtenByVersion")
|
||||||
String writtenByVersion;
|
String writtenByVersion;
|
||||||
@@ -99,4 +105,8 @@ class SettingsJson {
|
|||||||
|
|
||||||
@JsonProperty("lastUpdateAttemptedByVersion")
|
@JsonProperty("lastUpdateAttemptedByVersion")
|
||||||
String lastUpdateAttemptedByVersion;
|
String lastUpdateAttemptedByVersion;
|
||||||
|
|
||||||
|
@JsonProperty("trustedHosts")
|
||||||
|
@JsonSetter(nulls = Nulls.AS_EMPTY)
|
||||||
|
Set<String> trustedHosts = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import java.util.Set;
|
|||||||
* <li>cryptomator.p12Path</li>
|
* <li>cryptomator.p12Path</li>
|
||||||
* <li>cryptomator.mountPointsDir</li>
|
* <li>cryptomator.mountPointsDir</li>
|
||||||
* <li>cryptomator.disableUpdateCheck</li>
|
* <li>cryptomator.disableUpdateCheck</li>
|
||||||
|
* <li>cryptomator.hub.allowedHosts</li>
|
||||||
|
* <li>cryptomator.hub.enableTrustOnFirstUse</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @see Properties
|
* @see Properties
|
||||||
@@ -42,7 +44,9 @@ class AdminPropertiesFactory {
|
|||||||
"cryptomator.pluginDir", //
|
"cryptomator.pluginDir", //
|
||||||
"cryptomator.p12Path", //
|
"cryptomator.p12Path", //
|
||||||
"cryptomator.mountPointsDir", //
|
"cryptomator.mountPointsDir", //
|
||||||
"cryptomator.disableUpdateCheck");
|
"cryptomator.disableUpdateCheck", //
|
||||||
|
"cryptomator.hub.allowedHosts", //
|
||||||
|
"cryptomator.hub.enableTrustOnFirstUse");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public enum FxmlFile {
|
|||||||
HEALTH_START("/fxml/health_start.fxml"), //
|
HEALTH_START("/fxml/health_start.fxml"), //
|
||||||
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
|
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
|
||||||
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
|
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
|
||||||
|
HUB_CHECK_HOST_TRUST("/fxml/hub_check_host_trust.fxml"), //
|
||||||
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
|
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
|
||||||
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //
|
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //
|
||||||
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
|
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
|
||||||
@@ -29,6 +30,7 @@ public enum FxmlFile {
|
|||||||
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), //
|
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), //
|
||||||
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
|
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
|
||||||
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
|
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
|
||||||
|
HUB_UNTRUSTED_HOST("/fxml/hub_untrusted_host.fxml"), //
|
||||||
HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), //
|
HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), //
|
||||||
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
||||||
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
||||||
|
|||||||
@@ -64,17 +64,6 @@ abstract class FxApplicationModule {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@FxApplicationScoped
|
|
||||||
static MainWindowComponent provideMainWindowComponent(MainWindowComponent.Builder builder) {
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@FxApplicationScoped
|
|
||||||
static PreferencesComponent providePreferencesComponent(PreferencesComponent.Builder builder) {
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
@@ -88,10 +77,4 @@ abstract class FxApplicationModule {
|
|||||||
return factory.create();
|
return factory.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@FxApplicationScoped
|
|
||||||
static NotificationComponent provideNotificationComponent(NotificationComponent.Factory factory) {
|
|
||||||
return factory.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,7 @@ import java.util.Optional;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionStage;
|
import java.util.concurrent.CompletionStage;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
public class FxApplicationWindows {
|
public class FxApplicationWindows {
|
||||||
@@ -47,15 +48,15 @@ public class FxApplicationWindows {
|
|||||||
|
|
||||||
private final Stage primaryStage;
|
private final Stage primaryStage;
|
||||||
private final Optional<TrayIntegrationProvider> trayIntegration;
|
private final Optional<TrayIntegrationProvider> trayIntegration;
|
||||||
private final Lazy<MainWindowComponent> mainWindow;
|
private final CachedLazy<MainWindowComponent> mainWindow;
|
||||||
private final Lazy<PreferencesComponent> preferencesWindow;
|
private final CachedLazy<PreferencesComponent> preferencesWindow;
|
||||||
private final QuitComponent.Builder quitWindowBuilder;
|
private final QuitComponent.Builder quitWindowBuilder;
|
||||||
private final UnlockComponent.Factory unlockWorkflowFactory;
|
private final UnlockComponent.Factory unlockWorkflowFactory;
|
||||||
private final UpdateReminderComponent.Factory updateReminderWindowFactory;
|
private final UpdateReminderComponent.Factory updateReminderWindowFactory;
|
||||||
private final LockComponent.Factory lockWorkflowFactory;
|
private final LockComponent.Factory lockWorkflowFactory;
|
||||||
private final ErrorComponent.Factory errorWindowFactory;
|
private final ErrorComponent.Factory errorWindowFactory;
|
||||||
private final Lazy<EventViewComponent> eventViewWindow;
|
private final CachedLazy<EventViewComponent> eventViewWindow;
|
||||||
private final Lazy<NotificationComponent> notificationWindow;
|
private final CachedLazy<NotificationComponent> notificationWindow;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
private final VaultOptionsComponent.Factory vaultOptionsWindow;
|
private final VaultOptionsComponent.Factory vaultOptionsWindow;
|
||||||
private final ShareVaultComponent.Factory shareVaultWindow;
|
private final ShareVaultComponent.Factory shareVaultWindow;
|
||||||
@@ -65,8 +66,8 @@ public class FxApplicationWindows {
|
|||||||
@Inject
|
@Inject
|
||||||
public FxApplicationWindows(@PrimaryStage Stage primaryStage, //
|
public FxApplicationWindows(@PrimaryStage Stage primaryStage, //
|
||||||
Optional<TrayIntegrationProvider> trayIntegration, //
|
Optional<TrayIntegrationProvider> trayIntegration, //
|
||||||
Lazy<MainWindowComponent> mainWindow, //
|
MainWindowComponent.Builder mainWindowBuilder, //
|
||||||
Lazy<PreferencesComponent> preferencesWindow, //
|
PreferencesComponent.Builder preferencesWindowBuilder, //
|
||||||
QuitComponent.Builder quitWindowBuilder, //
|
QuitComponent.Builder quitWindowBuilder, //
|
||||||
UnlockComponent.Factory unlockWorkflowFactory, //
|
UnlockComponent.Factory unlockWorkflowFactory, //
|
||||||
UpdateReminderComponent.Factory updateReminderWindowFactory, //
|
UpdateReminderComponent.Factory updateReminderWindowFactory, //
|
||||||
@@ -74,21 +75,21 @@ public class FxApplicationWindows {
|
|||||||
ErrorComponent.Factory errorWindowFactory, //
|
ErrorComponent.Factory errorWindowFactory, //
|
||||||
VaultOptionsComponent.Factory vaultOptionsWindow, //
|
VaultOptionsComponent.Factory vaultOptionsWindow, //
|
||||||
ShareVaultComponent.Factory shareVaultWindow, //
|
ShareVaultComponent.Factory shareVaultWindow, //
|
||||||
Lazy<EventViewComponent> eventViewWindow, //
|
EventViewComponent.Factory eventViewWindowFactory, //
|
||||||
Lazy<NotificationComponent> notificationWindow,
|
NotificationComponent.Factory notificationWindowFactory, //
|
||||||
ExecutorService executor, //
|
ExecutorService executor, //
|
||||||
Dialogs dialogs) {
|
Dialogs dialogs) {
|
||||||
this.primaryStage = primaryStage;
|
this.primaryStage = primaryStage;
|
||||||
this.trayIntegration = trayIntegration;
|
this.trayIntegration = trayIntegration;
|
||||||
this.mainWindow = mainWindow;
|
this.mainWindow = new CachedLazy<>(mainWindowBuilder::build);
|
||||||
this.preferencesWindow = preferencesWindow;
|
this.preferencesWindow = new CachedLazy<>(preferencesWindowBuilder::build);
|
||||||
this.quitWindowBuilder = quitWindowBuilder;
|
this.quitWindowBuilder = quitWindowBuilder;
|
||||||
this.unlockWorkflowFactory = unlockWorkflowFactory;
|
this.unlockWorkflowFactory = unlockWorkflowFactory;
|
||||||
this.updateReminderWindowFactory = updateReminderWindowFactory;
|
this.updateReminderWindowFactory = updateReminderWindowFactory;
|
||||||
this.lockWorkflowFactory = lockWorkflowFactory;
|
this.lockWorkflowFactory = lockWorkflowFactory;
|
||||||
this.errorWindowFactory = errorWindowFactory;
|
this.errorWindowFactory = errorWindowFactory;
|
||||||
this.eventViewWindow = eventViewWindow;
|
this.eventViewWindow = new CachedLazy<>(eventViewWindowFactory::create);
|
||||||
this.notificationWindow = notificationWindow;
|
this.notificationWindow = new CachedLazy<>(notificationWindowFactory::create);
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.vaultOptionsWindow = vaultOptionsWindow;
|
this.vaultOptionsWindow = vaultOptionsWindow;
|
||||||
this.shareVaultWindow = shareVaultWindow;
|
this.shareVaultWindow = shareVaultWindow;
|
||||||
@@ -218,4 +219,29 @@ public class FxApplicationWindows {
|
|||||||
LOG.error("Failed to display stage", error);
|
LOG.error("Failed to display stage", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class CachedLazy<T> implements Lazy<T> {
|
||||||
|
|
||||||
|
private final Supplier<T> supplier;
|
||||||
|
private volatile T instance = null;
|
||||||
|
|
||||||
|
public CachedLazy(Supplier<T> supplier) {
|
||||||
|
this.supplier = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get() {
|
||||||
|
T value = instance;
|
||||||
|
if (value == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
value = instance;
|
||||||
|
if (value == null) {
|
||||||
|
value = supplier.get();
|
||||||
|
instance = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.cryptomator.ui.keyloading.hub;
|
package org.cryptomator.ui.keyloading.hub;
|
||||||
|
|
||||||
import com.nimbusds.jose.JWEObject;
|
|
||||||
import dagger.Lazy;
|
import dagger.Lazy;
|
||||||
import org.cryptomator.ui.common.FxController;
|
import org.cryptomator.ui.common.FxController;
|
||||||
import org.cryptomator.ui.common.FxmlFile;
|
import org.cryptomator.ui.common.FxmlFile;
|
||||||
@@ -12,8 +11,6 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
|
||||||
import javafx.beans.binding.StringBinding;
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.concurrent.WorkerStateEvent;
|
import javafx.concurrent.WorkerStateEvent;
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
package org.cryptomator.ui.keyloading.hub;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
|
import org.cryptomator.common.Environment;
|
||||||
|
import org.cryptomator.common.settings.Settings;
|
||||||
|
import org.cryptomator.ui.common.FxController;
|
||||||
|
import org.cryptomator.ui.common.FxmlFile;
|
||||||
|
import org.cryptomator.ui.common.FxmlScene;
|
||||||
|
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||||
|
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||||
|
import org.jetbrains.annotations.VisibleForTesting;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.text.TextFlow;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@KeyLoadingScoped
|
||||||
|
public class CheckHostTrustController implements FxController {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(CheckHostTrustController.class);
|
||||||
|
private static final String CHECK_KEY = "hub.checkHostTrust.message.check";
|
||||||
|
private static final String ASK_SINGULAR_KEY = "hub.checkHostTrust.message.ask";
|
||||||
|
private static final String ASK_PLURAL_KEY = "hub.checkHostTrust.message.ask.plural";
|
||||||
|
private static final String TRUSTED_CRYPTOMATOR_CLOUD_DOMAIN = ".cryptomator.cloud";
|
||||||
|
|
||||||
|
private final Stage window;
|
||||||
|
private final HubConfig hubConfig;
|
||||||
|
private final URI canonicalHubUri;
|
||||||
|
private final URI canonicalAuthUri;
|
||||||
|
private final Lazy<Scene> authFlowScene;
|
||||||
|
private final Lazy<Scene> untrustedHostScene;
|
||||||
|
private final CompletableFuture<ReceivedKey> result;
|
||||||
|
private final Settings settings;
|
||||||
|
private final Environment env;
|
||||||
|
private final ResourceBundle resourceBundle;
|
||||||
|
private final SortedSet<String> hostnames;
|
||||||
|
private final StringProperty messageLabel;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextFlow hostnamesFlow;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CheckHostTrustController(@KeyLoading Stage window, //
|
||||||
|
HubConfig hubConfig, //
|
||||||
|
@FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, //
|
||||||
|
@FxmlScene(FxmlFile.HUB_UNTRUSTED_HOST) Lazy<Scene> untrustedHostScene, //
|
||||||
|
CompletableFuture<ReceivedKey> result, //
|
||||||
|
Settings settings, //
|
||||||
|
Environment env, //
|
||||||
|
ResourceBundle resourceBundle) {
|
||||||
|
this.window = window;
|
||||||
|
this.hubConfig = hubConfig;
|
||||||
|
this.canonicalHubUri = hubConfig.getApiBaseUrl();
|
||||||
|
this.canonicalAuthUri = URI.create(hubConfig.authEndpoint);
|
||||||
|
this.authFlowScene = authFlowScene;
|
||||||
|
this.untrustedHostScene = untrustedHostScene;
|
||||||
|
this.result = result;
|
||||||
|
this.settings = settings;
|
||||||
|
this.env = env;
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
this.hostnames = new TreeSet<>();
|
||||||
|
this.messageLabel = new SimpleStringProperty(resourceBundle.getString(CHECK_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void initialize() {
|
||||||
|
if (!isConsistentHubConfig()) {
|
||||||
|
LOG.warn("Inconsistent hub config detected. Denying access to protect the user.");
|
||||||
|
deny();
|
||||||
|
} else if (isAllCryptomatorCloud() && !isAnyHttpHost()) {
|
||||||
|
trust(); // trust *.cryptomator.cloud by default, domain is owned by Cryptomator maintainers
|
||||||
|
} else if (containsAllowedHosts(env.hubAllowedHosts())) {
|
||||||
|
trust(); // trust hosts explicitly allowlisted via system property
|
||||||
|
} else if (isAnyHttpHost() && !isAllLocalhost()) {
|
||||||
|
LOG.warn("Denying attempt to connect to hub instance via unencrypted HTTP.");
|
||||||
|
deny(); // never trust http hosts except for local testing
|
||||||
|
} else if (env.hubTrustOnFirstUse() && containsAllowedHosts(settings.trustedHosts)) {
|
||||||
|
trust(); // trust hosts previously allowlisted by the user
|
||||||
|
} else if (env.hubTrustOnFirstUse()) {
|
||||||
|
hostnames.add(getAuthority(canonicalHubUri));
|
||||||
|
hostnames.add(getAuthority(canonicalAuthUri));
|
||||||
|
renderHostnames(); // ask user whether to trust these hosts
|
||||||
|
} else {
|
||||||
|
LOG.warn("Cryptomator is not allowed to connect to {}. Check your {} config.", getAuthority(canonicalHubUri), Environment.HUB_ALLOWED_HOSTS_PROP_NAME);
|
||||||
|
deny();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void trust() {
|
||||||
|
settings.trustedHosts.addAll(hostnames);
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
window.setScene(authFlowScene.get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void deny() {
|
||||||
|
result.cancel(true);
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
window.setScene(untrustedHostScene.get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderHostnames() {
|
||||||
|
hostnamesFlow.getChildren().clear();
|
||||||
|
for (var hostname : hostnames) {
|
||||||
|
hostnamesFlow.getChildren().add(new Text(hostname + System.lineSeparator()));
|
||||||
|
}
|
||||||
|
var messageKey = hostnames.size() > 1 ? ASK_PLURAL_KEY : ASK_SINGULAR_KEY;
|
||||||
|
messageLabel.set(resourceBundle.getString(messageKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isConsistentHubConfig() {
|
||||||
|
var canonicalHubAuthority = getAuthority(canonicalHubUri);
|
||||||
|
var canonicalAuthAuthority = getAuthority(canonicalAuthUri);
|
||||||
|
|
||||||
|
// apiBaseURL.host == deviceUrl.host == authSuccessUrl.host == authErrorUrl.host
|
||||||
|
return (hubConfig.apiBaseUrl == null || getAuthority(hubConfig.apiBaseUrl).equals(canonicalHubAuthority)) //
|
||||||
|
&& (hubConfig.devicesResourceUrl == null || getAuthority(hubConfig.devicesResourceUrl).equals(canonicalHubAuthority)) //
|
||||||
|
&& getAuthority(hubConfig.authSuccessUrl).equals(canonicalHubAuthority) //
|
||||||
|
&& getAuthority(hubConfig.authErrorUrl).equals(canonicalHubAuthority) //
|
||||||
|
// authUrl.host == tokenUrl.host:
|
||||||
|
&& getAuthority(hubConfig.tokenEndpoint).equals(canonicalAuthAuthority);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAllCryptomatorCloud() {
|
||||||
|
return canonicalHubUri.getHost().endsWith(TRUSTED_CRYPTOMATOR_CLOUD_DOMAIN) && canonicalAuthUri.getHost().endsWith(TRUSTED_CRYPTOMATOR_CLOUD_DOMAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAnyHttpHost() {
|
||||||
|
return "http".equalsIgnoreCase(canonicalHubUri.getScheme()) || "http".equalsIgnoreCase(canonicalAuthUri.getScheme());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAllLocalhost() {
|
||||||
|
return "localhost".equalsIgnoreCase(canonicalHubUri.getHost()) && "localhost".equalsIgnoreCase(canonicalAuthUri.getHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean containsAllowedHosts(Set<String> allowedHubHosts) {
|
||||||
|
return allowedHubHosts.contains(getAuthority(canonicalHubUri)) && allowedHubHosts.contains(getAuthority(canonicalAuthUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAuthority(String string) {
|
||||||
|
return getAuthority(URI.create(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAuthority(URI uri) {
|
||||||
|
if (uri.getPort() == -1) {
|
||||||
|
return "%s://%s".formatted(uri.getScheme(), uri.getHost());
|
||||||
|
} else {
|
||||||
|
return "%s://%s:%s".formatted(uri.getScheme(), uri.getHost(), uri.getPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- JavaFX property getter & setter
|
||||||
|
public StringProperty messageLabelProperty() {
|
||||||
|
return messageLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessageLabel() {
|
||||||
|
return messageLabel.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -98,6 +98,13 @@ public abstract class HubKeyLoadingModule {
|
|||||||
return fxmlLoaders.createScene(FxmlFile.HUB_NO_KEYCHAIN);
|
return fxmlLoaders.createScene(FxmlFile.HUB_NO_KEYCHAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@FxmlScene(FxmlFile.HUB_CHECK_HOST_TRUST)
|
||||||
|
@KeyLoadingScoped
|
||||||
|
static Scene provideHubCheckHostTrustScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
|
||||||
|
return fxmlLoaders.createScene(FxmlFile.HUB_CHECK_HOST_TRUST);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@FxmlScene(FxmlFile.HUB_AUTH_FLOW)
|
@FxmlScene(FxmlFile.HUB_AUTH_FLOW)
|
||||||
@KeyLoadingScoped
|
@KeyLoadingScoped
|
||||||
@@ -168,6 +175,13 @@ public abstract class HubKeyLoadingModule {
|
|||||||
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
|
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@FxmlScene(FxmlFile.HUB_UNTRUSTED_HOST)
|
||||||
|
@KeyLoadingScoped
|
||||||
|
static Scene provideHubUntrustedHostScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
|
||||||
|
return fxmlLoaders.createScene(FxmlFile.HUB_UNTRUSTED_HOST);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT)
|
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT)
|
||||||
@KeyLoadingScoped
|
@KeyLoadingScoped
|
||||||
@@ -180,6 +194,11 @@ public abstract class HubKeyLoadingModule {
|
|||||||
@FxControllerKey(NoKeychainController.class)
|
@FxControllerKey(NoKeychainController.class)
|
||||||
abstract FxController bindNoKeychainController(NoKeychainController controller);
|
abstract FxController bindNoKeychainController(NoKeychainController controller);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FxControllerKey(CheckHostTrustController.class)
|
||||||
|
abstract FxController bindCheckHostAuthenticityController(CheckHostTrustController controller);
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FxControllerKey(AuthFlowController.class)
|
@FxControllerKey(AuthFlowController.class)
|
||||||
@@ -225,6 +244,11 @@ public abstract class HubKeyLoadingModule {
|
|||||||
@FxControllerKey(UnauthorizedDeviceController.class)
|
@FxControllerKey(UnauthorizedDeviceController.class)
|
||||||
abstract FxController bindUnauthorizedDeviceController(UnauthorizedDeviceController controller);
|
abstract FxController bindUnauthorizedDeviceController(UnauthorizedDeviceController controller);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FxControllerKey(UntrustedHostController.class)
|
||||||
|
abstract FxController bindUnauthorizedHostController(UntrustedHostController controller);
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FxControllerKey(RequireAccountInitController.class)
|
@FxControllerKey(RequireAccountInitController.class)
|
||||||
|
|||||||
@@ -36,19 +36,19 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy, FilesystemOwne
|
|||||||
private final Stage window;
|
private final Stage window;
|
||||||
private final KeychainManager keychainManager;
|
private final KeychainManager keychainManager;
|
||||||
private final AtomicReference<String> fsOwnerId;
|
private final AtomicReference<String> fsOwnerId;
|
||||||
private final Lazy<Scene> authFlowScene;
|
private final Lazy<Scene> checkHostTrustScene;
|
||||||
private final Lazy<Scene> noKeychainScene;
|
private final Lazy<Scene> noKeychainScene;
|
||||||
private final CompletableFuture<ReceivedKey> result;
|
private final CompletableFuture<ReceivedKey> result;
|
||||||
private final DeviceKey deviceKey;
|
private final DeviceKey deviceKey;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<ReceivedKey> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle, @Named("filesystemOwnerId") AtomicReference<String> fsOwnerId) {
|
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_CHECK_HOST_TRUST) Lazy<Scene> checkHostTrustScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<ReceivedKey> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle, @Named("filesystemOwnerId") AtomicReference<String> fsOwnerId) {
|
||||||
this.window = window;
|
this.window = window;
|
||||||
this.keychainManager = keychainManager;
|
this.keychainManager = keychainManager;
|
||||||
this.fsOwnerId = fsOwnerId;
|
this.fsOwnerId = fsOwnerId;
|
||||||
window.setTitle(windowTitle);
|
window.setTitle(windowTitle);
|
||||||
window.setOnCloseRequest(_ -> result.cancel(true));
|
window.setOnCloseRequest(_ -> result.cancel(true));
|
||||||
this.authFlowScene = authFlowScene;
|
this.checkHostTrustScene = checkHostTrustScene;
|
||||||
this.noKeychainScene = noKeychainScene;
|
this.noKeychainScene = noKeychainScene;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.deviceKey = deviceKey;
|
this.deviceKey = deviceKey;
|
||||||
@@ -62,7 +62,7 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy, FilesystemOwne
|
|||||||
throw new NoKeychainAccessProviderException();
|
throw new NoKeychainAccessProviderException();
|
||||||
}
|
}
|
||||||
var keypair = deviceKey.get();
|
var keypair = deviceKey.get();
|
||||||
showWindow(authFlowScene);
|
showWindow(checkHostTrustScene);
|
||||||
var jwe = result.get();
|
var jwe = result.get();
|
||||||
return jwe.decryptMasterkey(keypair.getPrivate());
|
return jwe.decryptMasterkey(keypair.getPrivate());
|
||||||
} catch (NoKeychainAccessProviderException e) {
|
} catch (NoKeychainAccessProviderException e) {
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.cryptomator.ui.keyloading.hub;
|
||||||
|
|
||||||
|
import org.cryptomator.ui.common.FxController;
|
||||||
|
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||||
|
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import javafx.stage.WindowEvent;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@KeyLoadingScoped
|
||||||
|
public class UntrustedHostController implements FxController {
|
||||||
|
|
||||||
|
private final Stage window;
|
||||||
|
private final CompletableFuture<ReceivedKey> result;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public UntrustedHostController(@KeyLoading Stage window, CompletableFuture<ReceivedKey> result) {
|
||||||
|
this.window = window;
|
||||||
|
this.result = result;
|
||||||
|
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void close() {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void windowClosed(WindowEvent windowEvent) {
|
||||||
|
result.cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-2
@@ -1,6 +1,7 @@
|
|||||||
package org.cryptomator.ui.keyloading.masterkeyfile;
|
package org.cryptomator.ui.keyloading.masterkeyfile;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.cryptomator.common.Constants;
|
||||||
import org.cryptomator.common.Passphrase;
|
import org.cryptomator.common.Passphrase;
|
||||||
import org.cryptomator.common.keychain.KeychainManager;
|
import org.cryptomator.common.keychain.KeychainManager;
|
||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
@@ -63,16 +64,21 @@ public class MasterkeyFileLoadingStrategy implements KeyLoadingStrategy {
|
|||||||
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
|
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
|
||||||
window.setTitle(resourceBundle.getString("unlock.title").formatted(vault.getDisplayName()));
|
window.setTitle(resourceBundle.getString("unlock.title").formatted(vault.getDisplayName()));
|
||||||
Preconditions.checkArgument(SCHEME.equalsIgnoreCase(keyId.getScheme()), "Only supports keys with scheme " + SCHEME);
|
Preconditions.checkArgument(SCHEME.equalsIgnoreCase(keyId.getScheme()), "Only supports keys with scheme " + SCHEME);
|
||||||
|
if (!Constants.MASTERKEY_FILENAME.equals(keyId.getSchemeSpecificPart())) {
|
||||||
|
LOG.warn("unsupported masterkey path found in vault.cryptomator: {}", keyId.getSchemeSpecificPart());
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Path filePath = vault.getPath().resolve(keyId.getSchemeSpecificPart());
|
// determine masterkey file path:
|
||||||
|
Path filePath = vault.getPath().resolve(Constants.MASTERKEY_FILENAME);
|
||||||
if (!Files.exists(filePath)) {
|
if (!Files.exists(filePath)) {
|
||||||
filePath = askUserForMasterkeyFilePath();
|
filePath = askUserForMasterkeyFilePath();
|
||||||
}
|
}
|
||||||
|
// unlock:
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
askForPassphrase();
|
askForPassphrase();
|
||||||
}
|
}
|
||||||
var masterkey = masterkeyFileAccess.load(filePath, passphrase);
|
var masterkey = masterkeyFileAccess.load(filePath, passphrase);
|
||||||
//backup
|
// backup on successful unlock:
|
||||||
if (filePath.startsWith(vault.getPath())) {
|
if (filePath.startsWith(vault.getPath())) {
|
||||||
try {
|
try {
|
||||||
BackupHelper.attemptBackup(filePath);
|
BackupHelper.attemptBackup(filePath);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import javax.inject.Inject;
|
|||||||
import javafx.beans.Observable;
|
import javafx.beans.Observable;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.ChoiceBox;
|
import javafx.scene.control.ChoiceBox;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
@@ -56,6 +57,7 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
public CheckBox autoCloseVaultsCheckbox;
|
public CheckBox autoCloseVaultsCheckbox;
|
||||||
public CheckBox debugModeCheckbox;
|
public CheckBox debugModeCheckbox;
|
||||||
public CheckBox autoStartCheckbox;
|
public CheckBox autoStartCheckbox;
|
||||||
|
public Button resetTrustedHostsButton;
|
||||||
public ToggleGroup nodeOrientation;
|
public ToggleGroup nodeOrientation;
|
||||||
|
|
||||||
private CompletionStage<Void> keychainMigrations = CompletableFuture.completedFuture(null);
|
private CompletionStage<Void> keychainMigrations = CompletableFuture.completedFuture(null);
|
||||||
@@ -105,6 +107,9 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
quickAccessServiceChoiceBox.setConverter(new NamedServiceConverter<>());
|
quickAccessServiceChoiceBox.setConverter(new NamedServiceConverter<>());
|
||||||
Bindings.bindBidirectional(settings.quickAccessService, quickAccessServiceChoiceBox.valueProperty(), quickAccessSettingsConverter);
|
Bindings.bindBidirectional(settings.quickAccessService, quickAccessServiceChoiceBox.valueProperty(), quickAccessSettingsConverter);
|
||||||
quickAccessServiceChoiceBox.disableProperty().bind(useQuickAccessCheckbox.selectedProperty().not());
|
quickAccessServiceChoiceBox.disableProperty().bind(useQuickAccessCheckbox.selectedProperty().not());
|
||||||
|
if (resetTrustedHostsButton != null) {
|
||||||
|
resetTrustedHostsButton.disableProperty().bind(Bindings.isEmpty(settings.trustedHosts));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) {
|
private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) {
|
||||||
@@ -131,6 +136,10 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
return autoStartProvider.isPresent();
|
return autoStartProvider.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHubTrustOnFirstUseEnabled() {
|
||||||
|
return environment.hubTrustOnFirstUse();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void toggleAutoStart() {
|
public void toggleAutoStart() {
|
||||||
autoStartProvider.ifPresent(autoStart -> {
|
autoStartProvider.ifPresent(autoStart -> {
|
||||||
@@ -153,6 +162,11 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
return !quickAccessServices.isEmpty();
|
return !quickAccessServices.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void resetTrustedHosts() {
|
||||||
|
settings.trustedHosts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void showLogfileDirectory() {
|
public void showLogfileDirectory() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ public class UpdatesPreferencesController implements FxController {
|
|||||||
|
|
||||||
public boolean isProhibitUpdateWhileUnlocked() {
|
public boolean isProhibitUpdateWhileUnlocked() {
|
||||||
// If the result of the last update check was from the fallback mechanism, we don't need to show the warning
|
// If the result of the last update check was from the fallback mechanism, we don't need to show the warning
|
||||||
return !unlockedVaults.isEmpty() && !FallbackUpdateInfo.class.isInstance(updateChecker.getUpdate());
|
return !unlockedVaults.isEmpty() && updateChecker.isUpdateAvailable() && !FallbackUpdateInfo.class.isInstance(updateChecker.getUpdate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding prohibitUpdateWhileUnlockedProperty() {
|
public BooleanBinding prohibitUpdateWhileUnlockedProperty() {
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class TrayMenuBuilder {
|
|||||||
vaults.addListener(this::vaultListChanged);
|
vaults.addListener(this::vaultListChanged);
|
||||||
vaults.forEach(v -> {
|
vaults.forEach(v -> {
|
||||||
v.displayNameProperty().addListener(this::vaultListChanged);
|
v.displayNameProperty().addListener(this::vaultListChanged);
|
||||||
|
v.stateProperty().addListener(this::vaultListChanged);
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -76,7 +77,9 @@ public class TrayMenuBuilder {
|
|||||||
for (Vault vault : vaults) {
|
for (Vault vault : vaults) {
|
||||||
VaultListManager.redetermineVaultState(vault);
|
VaultListManager.redetermineVaultState(vault);
|
||||||
}
|
}
|
||||||
|
rebuildMenu();
|
||||||
});
|
});
|
||||||
|
vaults.forEach(VaultListManager::redetermineVaultState);
|
||||||
rebuildMenu();
|
rebuildMenu();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
} catch (TrayMenuException e) {
|
} catch (TrayMenuException e) {
|
||||||
@@ -122,18 +125,27 @@ public class TrayMenuBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<TrayMenuItem> buildSubmenu(Vault vault) {
|
private List<TrayMenuItem> buildSubmenu(Vault vault) {
|
||||||
if (vault.isLocked()) {
|
return switch (vault.getState()) {
|
||||||
return List.of( //
|
case LOCKED -> List.of( //
|
||||||
new ActionItem(resourceBundle.getString("traymenu.vault.unlock"), () -> this.unlockVault(vault)) //
|
new ActionItem(resourceBundle.getString("traymenu.vault.unlock"), () -> this.unlockVault(vault)) //
|
||||||
);
|
);
|
||||||
} else if (vault.isUnlocked()) {
|
case UNLOCKED -> List.of( //
|
||||||
return List.of( //
|
|
||||||
new ActionItem(resourceBundle.getString("traymenu.vault.lock"), () -> this.lockVault(vault)), //
|
new ActionItem(resourceBundle.getString("traymenu.vault.lock"), () -> this.lockVault(vault)), //
|
||||||
new ActionItem(resourceBundle.getString("traymenu.vault.reveal"), () -> this.revealVault(vault)) //
|
new ActionItem(resourceBundle.getString("traymenu.vault.reveal"), () -> this.revealVault(vault)) //
|
||||||
);
|
);
|
||||||
} else {
|
case PROCESSING -> List.of( //
|
||||||
return List.of();
|
new ActionItem(resourceBundle.getString("vault.state.processing"), () -> {}, false) //
|
||||||
}
|
);
|
||||||
|
case MISSING, VAULT_CONFIG_MISSING, ALL_MISSING -> List.of( //
|
||||||
|
new ActionItem(resourceBundle.getString("vault.state.missing"), () -> {}, false) //
|
||||||
|
);
|
||||||
|
case NEEDS_MIGRATION -> List.of( //
|
||||||
|
new ActionItem(resourceBundle.getString("vault.state.migrationNeeded"), () -> {}, false) //
|
||||||
|
);
|
||||||
|
case ERROR -> List.of( //
|
||||||
|
new ActionItem(resourceBundle.getString("vault.state.error"), () -> {}, false) //
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* action listeners: */
|
/* action listeners: */
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.ButtonBar?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.Group?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.Region?>
|
||||||
|
<?import javafx.scene.layout.StackPane?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import javafx.scene.shape.Circle?>
|
||||||
|
<?import javafx.scene.text.TextFlow?>
|
||||||
|
<HBox xmlns:fx="http://javafx.com/fxml"
|
||||||
|
xmlns="http://javafx.com/javafx"
|
||||||
|
fx:controller="org.cryptomator.ui.keyloading.hub.CheckHostTrustController"
|
||||||
|
minWidth="400"
|
||||||
|
maxWidth="400"
|
||||||
|
minHeight="145"
|
||||||
|
spacing="12"
|
||||||
|
alignment="TOP_LEFT"
|
||||||
|
accessibleRole="DIALOG">
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="12"/>
|
||||||
|
</padding>
|
||||||
|
<children>
|
||||||
|
<Group>
|
||||||
|
<StackPane>
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="6"/>
|
||||||
|
</padding>
|
||||||
|
<Circle styleClass="glyph-icon-primary" radius="24"/>
|
||||||
|
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="QUESTION" glyphSize="24"/>
|
||||||
|
</StackPane>
|
||||||
|
</Group>
|
||||||
|
<VBox HBox.hgrow="ALWAYS">
|
||||||
|
<Label styleClass="label-large" text="${controller.messageLabel}" wrapText="true" textAlignment="LEFT">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="6" top="6"/>
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<TextFlow fx:id="hostnamesFlow" styleClass="text-flow" minHeight="60"/>
|
||||||
|
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
|
||||||
|
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||||
|
<buttons>
|
||||||
|
<Button text="%hub.checkHostTrust.denyBtn" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#deny"/>
|
||||||
|
<Button text="%hub.checkHostTrust.trustBtn" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#trust"/>
|
||||||
|
</buttons>
|
||||||
|
</ButtonBar>
|
||||||
|
</VBox>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.Group?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.ButtonBar?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.Region?>
|
||||||
|
<?import javafx.scene.layout.StackPane?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import javafx.scene.shape.Circle?>
|
||||||
|
<HBox xmlns:fx="http://javafx.com/fxml"
|
||||||
|
xmlns="http://javafx.com/javafx"
|
||||||
|
fx:controller="org.cryptomator.ui.keyloading.hub.UntrustedHostController"
|
||||||
|
minWidth="400"
|
||||||
|
maxWidth="400"
|
||||||
|
minHeight="145"
|
||||||
|
spacing="12"
|
||||||
|
alignment="TOP_LEFT"
|
||||||
|
accessibleRole="DIALOG">
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="12"/>
|
||||||
|
</padding>
|
||||||
|
<children>
|
||||||
|
<Group>
|
||||||
|
<StackPane>
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="6"/>
|
||||||
|
</padding>
|
||||||
|
<Circle styleClass="glyph-icon-primary" radius="24"/>
|
||||||
|
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="EXCLAMATION" glyphSize="24"/>
|
||||||
|
</StackPane>
|
||||||
|
</Group>
|
||||||
|
<VBox HBox.hgrow="ALWAYS">
|
||||||
|
<Label styleClass="label-large" text="%hub.untrustedHost.message" wrapText="true" textAlignment="LEFT">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="6" top="6"/>
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Label text="%hub.untrustedHost.description" wrapText="true"/>
|
||||||
|
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
|
||||||
|
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
|
||||||
|
<buttons>
|
||||||
|
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/>
|
||||||
|
</buttons>
|
||||||
|
</ButtonBar>
|
||||||
|
</VBox>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.CheckBox?>
|
<?import javafx.scene.control.CheckBox?>
|
||||||
<?import javafx.scene.control.ChoiceBox?>
|
<?import javafx.scene.control.ChoiceBox?>
|
||||||
<?import javafx.scene.control.Hyperlink?>
|
<?import javafx.scene.control.Hyperlink?>
|
||||||
@@ -34,6 +35,8 @@
|
|||||||
<CheckBox fx:id="useQuickAccessCheckbox" text="%preferences.general.quickAccessService"/>
|
<CheckBox fx:id="useQuickAccessCheckbox" text="%preferences.general.quickAccessService"/>
|
||||||
<ChoiceBox fx:id="quickAccessServiceChoiceBox" accessibleText="%preferences.general.quickAccessService"/>
|
<ChoiceBox fx:id="quickAccessServiceChoiceBox" accessibleText="%preferences.general.quickAccessService"/>
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
||||||
|
<Button fx:id="resetTrustedHostsButton" text="%preferences.general.resetTrustedHosts" visible="${controller.hubTrustOnFirstUseEnabled}" managed="${controller.hubTrustOnFirstUseEnabled}" onAction="#resetTrustedHosts"/>
|
||||||
<Region VBox.vgrow="ALWAYS"/>
|
<Region VBox.vgrow="ALWAYS"/>
|
||||||
|
|
||||||
<HBox spacing="12" alignment="CENTER_LEFT">
|
<HBox spacing="12" alignment="CENTER_LEFT">
|
||||||
|
|||||||
@@ -162,6 +162,12 @@ unlock.error.title=Unlock "%s" failed
|
|||||||
hub.noKeychain.message=Unable to access device key
|
hub.noKeychain.message=Unable to access device key
|
||||||
hub.noKeychain.description=In order to unlock Hub vaults, a device key is required, which is secured using a keychain. To proceed, enable “%s” and select a keychain in the preferences.
|
hub.noKeychain.description=In order to unlock Hub vaults, a device key is required, which is secured using a keychain. To proceed, enable “%s” and select a keychain in the preferences.
|
||||||
hub.noKeychain.openBtn=Open Preferences
|
hub.noKeychain.openBtn=Open Preferences
|
||||||
|
### Check Host Authenticity
|
||||||
|
hub.checkHostTrust.message.check=Checking Configuration…
|
||||||
|
hub.checkHostTrust.message.ask=Trust this host?
|
||||||
|
hub.checkHostTrust.message.ask.plural=Trust these hosts?
|
||||||
|
hub.checkHostTrust.trustBtn=Trust
|
||||||
|
hub.checkHostTrust.denyBtn=Deny
|
||||||
### Waiting
|
### Waiting
|
||||||
hub.auth.message=Waiting for authentication…
|
hub.auth.message=Waiting for authentication…
|
||||||
hub.auth.description=You should automatically be redirected to the login page.
|
hub.auth.description=You should automatically be redirected to the login page.
|
||||||
@@ -193,6 +199,9 @@ hub.archived.description=This vault has been archived and is no longer accessibl
|
|||||||
### Unauthorized
|
### Unauthorized
|
||||||
hub.unauthorized.message=Access denied
|
hub.unauthorized.message=Access denied
|
||||||
hub.unauthorized.description=You are not authorized to open this vault. Contact the vault's owner to request access.
|
hub.unauthorized.description=You are not authorized to open this vault. Contact the vault's owner to request access.
|
||||||
|
### Untrusted Host
|
||||||
|
hub.untrustedHost.message=Host not trusted
|
||||||
|
hub.untrustedHost.description=Connection to Hub was blocked for your security. If you believe the Hub host is safe, contact your Hub administrator or try again.
|
||||||
### Requires Account Initialization
|
### Requires Account Initialization
|
||||||
hub.requireAccountInit.message=Action required
|
hub.requireAccountInit.message=Action required
|
||||||
hub.requireAccountInit.description.0=To proceed, please complete the steps required in your
|
hub.requireAccountInit.description.0=To proceed, please complete the steps required in your
|
||||||
@@ -306,6 +315,7 @@ preferences.general.debugDirectory=Reveal log files
|
|||||||
preferences.general.autoStart=Launch Cryptomator on system start
|
preferences.general.autoStart=Launch Cryptomator on system start
|
||||||
preferences.general.keychainBackend=Store passwords with
|
preferences.general.keychainBackend=Store passwords with
|
||||||
preferences.general.quickAccessService=Add unlocked vaults to the quick access area
|
preferences.general.quickAccessService=Add unlocked vaults to the quick access area
|
||||||
|
preferences.general.resetTrustedHosts=Reset trusted hosts
|
||||||
## Interface
|
## Interface
|
||||||
preferences.interface=Interface
|
preferences.interface=Interface
|
||||||
preferences.interface.theme=Look & Feel
|
preferences.interface.theme=Look & Feel
|
||||||
@@ -717,4 +727,4 @@ eventView.entry.inUse.ignoreLock=Ignore use status
|
|||||||
## FileIsInUse Notification
|
## FileIsInUse Notification
|
||||||
notification.inUse.message=File is in use on another device
|
notification.inUse.message=File is in use on another device
|
||||||
notification.inUse.description=The file is open by %s on %s. Ask them to close the file and let synchronization finish. You can ignore the status to open it now, but this may cause conflicts or overwrite newer changes.
|
notification.inUse.description=The file is open by %s on %s. Ask them to close the file and let synchronization finish. You can ignore the status to open it now, but this may cause conflicts or overwrite newer changes.
|
||||||
notification.inUse.action=Ignore Use Status
|
notification.inUse.action=Ignore Use Status
|
||||||
|
|||||||
@@ -269,6 +269,8 @@ health.check.detail.checkFinishedAndFound=Kontrolproceduren er kørt færdig. Ge
|
|||||||
health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl.
|
health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl.
|
||||||
health.check.detail.checkCancelled=Kontrolproceduren blev annulleret.
|
health.check.detail.checkCancelled=Kontrolproceduren blev annulleret.
|
||||||
health.check.detail.listFilters.label=Filter
|
health.check.detail.listFilters.label=Filter
|
||||||
|
health.check.detail.filterSeverity=Filtrér efter sværhedsgrad
|
||||||
|
health.check.detail.filterFixState=Filtrér efter fix status
|
||||||
health.check.detail.fixAllSpecificBtn=Løs alle af type
|
health.check.detail.fixAllSpecificBtn=Løs alle af type
|
||||||
health.check.exportBtn=Eksportér rapport
|
health.check.exportBtn=Eksportér rapport
|
||||||
## Result view
|
## Result view
|
||||||
@@ -358,6 +360,7 @@ preferences.contribute.promptText=Indsæt koden for supporter-certifikatet her
|
|||||||
preferences.contribute.thankYou=Tak fordi du støtter Cryptomators open source-udvikling!
|
preferences.contribute.thankYou=Tak fordi du støtter Cryptomators open source-udvikling!
|
||||||
preferences.contribute.donate=Donér
|
preferences.contribute.donate=Donér
|
||||||
preferences.contribute.sponsor=Sponsor
|
preferences.contribute.sponsor=Sponsor
|
||||||
|
preferences.contribute.removeCert.tooltip=Fjern certifikat
|
||||||
|
|
||||||
### Remove License Key Dialog
|
### Remove License Key Dialog
|
||||||
removeCert.title=Fjern certifikat
|
removeCert.title=Fjern certifikat
|
||||||
@@ -367,6 +370,7 @@ removeCert.description=Cryptomators kernefunktioner påvirkes ikke af dette. Hve
|
|||||||
|
|
||||||
## About
|
## About
|
||||||
preferences.about=Om
|
preferences.about=Om
|
||||||
|
preferences.about.thirdPartyLicenses=Tredjepartslicenser
|
||||||
|
|
||||||
# Vault Statistics
|
# Vault Statistics
|
||||||
stats.title=Statistik for %s
|
stats.title=Statistik for %s
|
||||||
@@ -406,6 +410,7 @@ stats.access.total=Samlede adgang: %d
|
|||||||
# Main Window
|
# Main Window
|
||||||
## Vault List
|
## Vault List
|
||||||
main.vaultlist=Bokse
|
main.vaultlist=Bokse
|
||||||
|
main.vaultlist.listEntry=Boks %s (%s)
|
||||||
main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks
|
main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks
|
||||||
main.vaultlist.contextMenu.remove=Fjern…
|
main.vaultlist.contextMenu.remove=Fjern…
|
||||||
main.vaultlist.contextMenu.lock=Lås
|
main.vaultlist.contextMenu.lock=Lås
|
||||||
@@ -419,12 +424,15 @@ main.vaultlist.addVaultBtn.menuItemExisting=Åbn eksisterende boks…
|
|||||||
main.vaultlist.addVaultBtn.menuItemRecover=Genopret eksisterende boks…
|
main.vaultlist.addVaultBtn.menuItemRecover=Genopret eksisterende boks…
|
||||||
main.vaultlist.addVaultButton.tooltip=Tilføj boks
|
main.vaultlist.addVaultButton.tooltip=Tilføj boks
|
||||||
main.vaultlist.showEventsButton.tooltip=Åbn begivenhedsvisning
|
main.vaultlist.showEventsButton.tooltip=Åbn begivenhedsvisning
|
||||||
|
main.vaultlist.showPreferencesButton.tooltip=Vis Indstillinger
|
||||||
##Notification
|
##Notification
|
||||||
main.notification.updateAvailable=Opdatering er tilgængelig.
|
main.notification.updateAvailable=Opdatering er tilgængelig.
|
||||||
main.notification.support=Støt Cryptomator.
|
main.notification.support=Støt Cryptomator.
|
||||||
|
main.notification.closeButton.tooltip=Luk infobjælke
|
||||||
## Vault Detail
|
## Vault Detail
|
||||||
### Welcome
|
### Welcome
|
||||||
main.vaultDetail.welcomeOnboarding=Tak fordi du valgte Cryptomator til at beskytte dine filer. Hvis du har brug for hjælp, så tjek vores guider for at komme i gang:
|
main.vaultDetail.welcomeOnboarding=Tak fordi du valgte Cryptomator til at beskytte dine filer. Hvis du har brug for hjælp, så tjek vores guider for at komme i gang:
|
||||||
|
main.vaultDetail.storageLocation=Placering af boks
|
||||||
### Locked
|
### Locked
|
||||||
main.vaultDetail.lockedStatus=LÅST
|
main.vaultDetail.lockedStatus=LÅST
|
||||||
main.vaultDetail.unlockBtn=Lås op…
|
main.vaultDetail.unlockBtn=Lås op…
|
||||||
@@ -482,6 +490,7 @@ vaultOptions.general=Generelt
|
|||||||
vaultOptions.general.vaultName=Boks-navn
|
vaultOptions.general.vaultName=Boks-navn
|
||||||
vaultOptions.general.autoLock.lockAfterTimePart1=Lås efter inaktivitet i
|
vaultOptions.general.autoLock.lockAfterTimePart1=Lås efter inaktivitet i
|
||||||
vaultOptions.general.autoLock.lockAfterTimePart2=minutter
|
vaultOptions.general.autoLock.lockAfterTimePart2=minutter
|
||||||
|
vaultOptions.general.autoLock.accessibleText=Lås timeout i minutter
|
||||||
vaultOptions.general.unlockAfterStartup=Lås boksen op når Cryptomator starter
|
vaultOptions.general.unlockAfterStartup=Lås boksen op når Cryptomator starter
|
||||||
vaultOptions.general.actionAfterUnlock=Efter oplåsning af boks
|
vaultOptions.general.actionAfterUnlock=Efter oplåsning af boks
|
||||||
vaultOptions.general.actionAfterUnlock.ignore=Gør intet
|
vaultOptions.general.actionAfterUnlock.ignore=Gør intet
|
||||||
@@ -512,6 +521,7 @@ vaultOptions.masterkey.forgetSavedPasswordBtn=Glem gemt adgangskode
|
|||||||
vaultOptions.masterkey.recoveryKeyExplanation=En gendannelsesnøgle er den eneste måde du kan få adgang til din boks på, hvis du har glemt dit password.
|
vaultOptions.masterkey.recoveryKeyExplanation=En gendannelsesnøgle er den eneste måde du kan få adgang til din boks på, hvis du har glemt dit password.
|
||||||
vaultOptions.masterkey.showRecoveryKeyBtn=Vis gendannelsesnøgle
|
vaultOptions.masterkey.showRecoveryKeyBtn=Vis gendannelsesnøgle
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Nulstil adgangskode
|
vaultOptions.masterkey.recoverPasswordBtn=Nulstil adgangskode
|
||||||
|
vaultOptions.masterkey.missingMasterkeyFile=Disse tilvalg er kun tilgængelige hvis masterkeyfilen er til stede i boksmappen.
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Gendannelse
|
vaultOptions.hub=Gendannelse
|
||||||
vaultOptions.hub.convertInfo=Du kan bruge gendannelsesnøglen til at konvertere denne Hub-boks til en adgangskode-baseret boks i en nødsituation.
|
vaultOptions.hub.convertInfo=Du kan bruge gendannelsesnøglen til at konvertere denne Hub-boks til en adgangskode-baseret boks i en nødsituation.
|
||||||
@@ -665,6 +675,8 @@ decryptNames.filePicker.title=Vælg krypteret fil
|
|||||||
decryptNames.filePicker.extensionDescription=Cryptomator krypteret fil
|
decryptNames.filePicker.extensionDescription=Cryptomator krypteret fil
|
||||||
decryptNames.copyTable.tooltip=Kopiér tabel
|
decryptNames.copyTable.tooltip=Kopiér tabel
|
||||||
decryptNames.clearTable.tooltip=Ryd tabel
|
decryptNames.clearTable.tooltip=Ryd tabel
|
||||||
|
decryptNames.column.encrypted=Krypteret
|
||||||
|
decryptNames.column.decrypted=Dekrypteret
|
||||||
decryptNames.copyHint=Kopiér celleindhold med %s
|
decryptNames.copyHint=Kopiér celleindhold med %s
|
||||||
decryptNames.dropZone.message=Slip filer eller klik for at vælge
|
decryptNames.dropZone.message=Slip filer eller klik for at vælge
|
||||||
decryptNames.dropZone.error.vaultInternalFiles=Boks interne filer med intet dekryptérbart navn valgt
|
decryptNames.dropZone.error.vaultInternalFiles=Boks interne filer med intet dekryptérbart navn valgt
|
||||||
@@ -677,6 +689,8 @@ decryptNames.dropZone.error.generic=Kunne ikke dekryptere filnavne
|
|||||||
eventView.title=Begivenheder
|
eventView.title=Begivenheder
|
||||||
eventView.filter.allVaults=Alle
|
eventView.filter.allVaults=Alle
|
||||||
eventView.clearListButton.tooltip=Ryd liste
|
eventView.clearListButton.tooltip=Ryd liste
|
||||||
|
eventView.filterVaults=Filtrér efter boks
|
||||||
|
eventView.cell.actionsButton.tooltip=Begivenhedshandlinger
|
||||||
## event list entries
|
## event list entries
|
||||||
eventView.entry.vaultLocked.description=Lås "%s" op for detaljer
|
eventView.entry.vaultLocked.description=Lås "%s" op for detaljer
|
||||||
eventView.entry.conflictResolved.message=Løst konflikt
|
eventView.entry.conflictResolved.message=Løst konflikt
|
||||||
@@ -694,6 +708,7 @@ eventView.entry.brokenFileNode.copyDecrypted=Kopiér dekrypteret sti
|
|||||||
eventView.entry.inUse.message=Fil i brug
|
eventView.entry.inUse.message=Fil i brug
|
||||||
eventView.entry.inUse.showDecrypted=Vis dekrypteret fil
|
eventView.entry.inUse.showDecrypted=Vis dekrypteret fil
|
||||||
eventView.entry.inUse.showEncrypted=Vis krypteret fil
|
eventView.entry.inUse.showEncrypted=Vis krypteret fil
|
||||||
|
eventView.entry.inUse.copyUserAndDevice=Kopiér låsebruger og enhedsnavn
|
||||||
eventView.entry.inUse.ignoreLock=Ignorér anvendelsesstatus
|
eventView.entry.inUse.ignoreLock=Ignorér anvendelsesstatus
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ defaults.vault.vaultName=Vault
|
|||||||
|
|
||||||
# Tray Menu
|
# Tray Menu
|
||||||
traymenu.showMainWindow=보기
|
traymenu.showMainWindow=보기
|
||||||
traymenu.showPreferencesWindow=환경설정
|
traymenu.showPreferencesWindow=환경 설정
|
||||||
traymenu.lockAllVaults=모두 잠그기
|
traymenu.lockAllVaults=모두 잠그기
|
||||||
traymenu.quitApplication=종료
|
traymenu.quitApplication=종료
|
||||||
traymenu.vault.unlock=잠금 해제
|
traymenu.vault.unlock=잠금 해제
|
||||||
@@ -114,7 +114,7 @@ addvaultwizard.success.nextStepsInstructions="%s" Vault가 추가되었습니다
|
|||||||
addvaultwizard.success.unlockNow=지금 잠금 해제
|
addvaultwizard.success.unlockNow=지금 잠금 해제
|
||||||
|
|
||||||
# Remove Vault
|
# Remove Vault
|
||||||
removeVault.title=Vault 제거
|
removeVault.title=Vault "%s" 제거
|
||||||
removeVault.message=Vault를 삭제하시겠습니까?
|
removeVault.message=Vault를 삭제하시겠습니까?
|
||||||
removeVault.description=이 행위는 Cryptomator에서만 이 Vault를 지웁니다. 나중에 다시 추가할 수 있습니다. 암호화된 파일은 하드디스크에서 삭제되지 않습니다.
|
removeVault.description=이 행위는 Cryptomator에서만 이 Vault를 지웁니다. 나중에 다시 추가할 수 있습니다. 암호화된 파일은 하드디스크에서 삭제되지 않습니다.
|
||||||
|
|
||||||
@@ -132,18 +132,18 @@ forgetPassword.confirmBtn=비밀번호 삭제
|
|||||||
# Unlock
|
# Unlock
|
||||||
unlock.title="%s" 잠금 해제
|
unlock.title="%s" 잠금 해제
|
||||||
unlock.passwordPrompt="%s"의 비밀번호를 입력하십시오.
|
unlock.passwordPrompt="%s"의 비밀번호를 입력하십시오.
|
||||||
unlock.savePassword=비밀번호 기억
|
unlock.savePassword=비밀번호 기억하기
|
||||||
unlock.unlockBtn=잠금 해제
|
unlock.unlockBtn=잠금 해제
|
||||||
## Select
|
## Select
|
||||||
unlock.chooseMasterkey.message=마스터키 파일을 찾을 수 없습니다
|
unlock.chooseMasterkey.message=마스터키 파일을 찾을 수 없습니다
|
||||||
unlock.chooseMasterkey.description=이 Vault의 Masterkey를 찾지 못했습니다. 마스터 키 위치를 수동으로 선택하여 주십시오.
|
unlock.chooseMasterkey.description=이 "%s" Vault의 마스터키를 찾지 못했습니다. 마스터키 위치를 수동으로 선택하여 주십시오.
|
||||||
unlock.chooseMasterkey.restoreInstead=대신 마스터키 파일 복구
|
unlock.chooseMasterkey.restoreInstead=대신 마스터키 파일 복구
|
||||||
unlock.chooseMasterkey.filePickerTitle=Masterkey 파일 선택
|
unlock.chooseMasterkey.filePickerTitle=Masterkey 파일 선택
|
||||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
||||||
## Success
|
## Success
|
||||||
unlock.success.message=잠금 해제 성공
|
unlock.success.message=잠금 해제 성공
|
||||||
unlock.success.description="%s"이(가) 성공적으로 잠금 해제되었습니다. 이제 이 Vault를 마운트 지점으로 접근할 수 있습니다.
|
unlock.success.description="%s"이(가) 성공적으로 잠금 해제되었습니다. 이제 이 Vault를 마운트 지점으로 접근할 수 있습니다.
|
||||||
unlock.success.rememberChoice=선택 기억하기, 다시 묻지 않음
|
unlock.success.rememberChoice=선택을 기억하고 다시 묻지 않음
|
||||||
unlock.success.revealBtn=드라이브 표시
|
unlock.success.revealBtn=드라이브 표시
|
||||||
## Failure
|
## Failure
|
||||||
unlock.error.customPath.message=Vault를 사용자 정의 경로에 마운트할 수 없습니다.
|
unlock.error.customPath.message=Vault를 사용자 정의 경로에 마운트할 수 없습니다.
|
||||||
@@ -166,7 +166,7 @@ hub.auth.message=인증 대기 중…
|
|||||||
hub.auth.description=자동으로 로그인 페이지로 리다이렉트 될 것입니다.
|
hub.auth.description=자동으로 로그인 페이지로 리다이렉트 될 것입니다.
|
||||||
hub.auth.loginLink=수동으로 열려면 클릭하십시오.
|
hub.auth.loginLink=수동으로 열려면 클릭하십시오.
|
||||||
### Receive Key
|
### Receive Key
|
||||||
hub.receive.message=응답 처리중…
|
hub.receive.message=응답 처리 중…
|
||||||
hub.receive.description=Hub로부터 응답을 처리하고 있습니다. 잠시만 기다려 주십시오.
|
hub.receive.description=Hub로부터 응답을 처리하고 있습니다. 잠시만 기다려 주십시오.
|
||||||
### Register Device
|
### Register Device
|
||||||
hub.register.message=새 기기
|
hub.register.message=새 기기
|
||||||
@@ -181,7 +181,7 @@ hub.register.legacy.description=이 기기로부터 첫번째 Hub 접근입니
|
|||||||
hub.registerSuccess.message=기기 등록됨
|
hub.registerSuccess.message=기기 등록됨
|
||||||
hub.registerSuccess.description=등록에 성공하였습니다. Vault를 잠금 해제할 수 있습니다.
|
hub.registerSuccess.description=등록에 성공하였습니다. Vault를 잠금 해제할 수 있습니다.
|
||||||
hub.registerSuccess.unlockBtn=잠금 해제
|
hub.registerSuccess.unlockBtn=잠금 해제
|
||||||
hub.registerSuccess.legacy.description=Vault에 접근하기 위해서는 이 기기를 Vault 소유주가 추가적으로 허가해야 합니다.
|
hub.registerSuccess.legacy.description=Vault에 접근하기 위해서는 이 기기를 Vault 소유자가 추가적으로 허가해야 합니다.
|
||||||
### Registration Failed
|
### Registration Failed
|
||||||
hub.registerFailed.message=기기 등록 실패
|
hub.registerFailed.message=기기 등록 실패
|
||||||
hub.registerFailed.description.generic=등록 중에 오류가 발생했습니다. 앱 로그에서 자세한 정보를 확인할 수 있습니다.
|
hub.registerFailed.description.generic=등록 중에 오류가 발생했습니다. 앱 로그에서 자세한 정보를 확인할 수 있습니다.
|
||||||
@@ -209,18 +209,18 @@ lock.forced.retryBtn=재시도
|
|||||||
lock.forced.forceBtn=강제 잠금
|
lock.forced.forceBtn=강제 잠금
|
||||||
## Failure
|
## Failure
|
||||||
lock.fail.message=Vault 잠금에 실패하였습니다.
|
lock.fail.message=Vault 잠금에 실패하였습니다.
|
||||||
lock.fail.description="%s" Vault를 잠글 수 없습니다. 저장되지 않은 작업이 다른 곳에 저장된 것과 중요한 읽기/쓰기 동작이 완료되었는지 확인 하십시요. Vault를 닫기 위해, Cryptomator 프로세스를 강제로 종료 하십시오.
|
lock.fail.description="%s" Vault를 잠글 수 없습니다. 저장되지 않은 작업이 다른 곳에 저장된 것과 중요한 읽기/쓰기 동작이 완료되었는지 확인 하십시요. Vault를 닫기 위해, Cryptomator 프로세스를 강제로 종료하십시오.
|
||||||
|
|
||||||
# Migration
|
# Migration
|
||||||
migration.title=Vault 업그레이드
|
migration.title=Vault 업그레이드
|
||||||
## Start
|
## Start
|
||||||
migration.start.header=Vault 업그레이드
|
migration.start.header=Vault 업그레이드
|
||||||
migration.start.text=Vault "%s"를 현재 버전의 Cryptomator에서 열기 위해서는 해당 vault를 새 버전으로 업그레이드해야 합니다. 업그레이드를 하기 전에 다음 사항들을 알고 있어야 합니다:
|
migration.start.text=Vault "%s"를 현재 버전의 Cryptomator에서 열기 위해서는 해당 Vault를 새 버전으로 업그레이드해야 합니다. 업그레이드를 하기 전에 다음 사항들을 알고 있어야 합니다:
|
||||||
migration.start.remarkUndone=이 업그레이드는 되돌릴 수 없습니다.
|
migration.start.remarkUndone=이 업그레이드는 되돌릴 수 없습니다.
|
||||||
migration.start.remarkVersions=과거 버전의 Cryptomator는 업그레이드된 Vault를 열 수 없습니다.
|
migration.start.remarkVersions=과거 버전의 Cryptomator는 업그레이드된 Vault를 열 수 없습니다.
|
||||||
migration.start.remarkCanRun=이 Vault를 열 때 사용하는 모든 기기가 현재 버전의 Cryptomator를 실행할 수 있는지 확인해야 합니다.
|
migration.start.remarkCanRun=이 Vault를 열 때 사용하는 모든 기기가 현재 버전의 Cryptomator를 실행할 수 있는지 확인해야 합니다.
|
||||||
migration.start.remarkSynced=업그레이드하기 전에 해당 Vault가 모든 기기에 정상적으로 동기화되어야 합니다.
|
migration.start.remarkSynced=업그레이드하기 전에 해당 Vault가 모든 기기에 정상적으로 동기화되어야 합니다.
|
||||||
migration.start.confirm=나는 위 정보를 읽고 정말 이해했습니다.
|
migration.start.confirm=위 내용을 충분히 숙지하였음을 확인합니다.
|
||||||
## Run
|
## Run
|
||||||
migration.run.enterPassword="%s"의 비밀번호를 입력하십시오.
|
migration.run.enterPassword="%s"의 비밀번호를 입력하십시오.
|
||||||
migration.run.startMigrationBtn=Vault 마이그레이션
|
migration.run.startMigrationBtn=Vault 마이그레이션
|
||||||
@@ -231,8 +231,8 @@ migration.success.unlockNow=지금 잠금 해제
|
|||||||
## Missing file system capabilities
|
## Missing file system capabilities
|
||||||
migration.error.missingFileSystemCapabilities.title=지원하지 않는 파일 시스템
|
migration.error.missingFileSystemCapabilities.title=지원하지 않는 파일 시스템
|
||||||
migration.error.missingFileSystemCapabilities.description=Vault가 부적절한 파일 시스템에 있기 때문에 마이그레이션이 시작되지 않았습니다.
|
migration.error.missingFileSystemCapabilities.description=Vault가 부적절한 파일 시스템에 있기 때문에 마이그레이션이 시작되지 않았습니다.
|
||||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=너무 긴 파일 이름을 파일 시스템에서 지원하지 않습니다.
|
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=파일 시스템이 긴 파일 이름을 지원하지 않습니다.
|
||||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=너무 긴 경로를 파일 시스템에서 지원하지 않습니다.
|
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=파일 시스템이 긴 경로를 지원하지 않습니다.
|
||||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=파일 시스템이 읽기를 허용하지 않습니다.
|
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=파일 시스템이 읽기를 허용하지 않습니다.
|
||||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=파일 시스템이 쓰기를 허용하지 않습니다.
|
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=파일 시스템이 쓰기를 허용하지 않습니다.
|
||||||
## Impossible
|
## Impossible
|
||||||
@@ -267,7 +267,7 @@ health.check.detail.checkSkipped=선택된 검사항목이 없습니다.
|
|||||||
health.check.detail.checkFinished=검사가 성공적으로 완료되었습니다.
|
health.check.detail.checkFinished=검사가 성공적으로 완료되었습니다.
|
||||||
health.check.detail.checkFinishedAndFound=검사가 완료되었습니다. 검사 결과를 확인해주세요.
|
health.check.detail.checkFinishedAndFound=검사가 완료되었습니다. 검사 결과를 확인해주세요.
|
||||||
health.check.detail.checkFailed=오류로 인해 검사가 종료되었습니다.
|
health.check.detail.checkFailed=오류로 인해 검사가 종료되었습니다.
|
||||||
health.check.detail.checkCancelled=검사가 취소되었습니다
|
health.check.detail.checkCancelled=검사가 취소되었습니다.
|
||||||
health.check.detail.listFilters.label=필터
|
health.check.detail.listFilters.label=필터
|
||||||
health.check.detail.filterSeverity=중요도로 정렬
|
health.check.detail.filterSeverity=중요도로 정렬
|
||||||
health.check.detail.filterFixState=해결 상태로 정렬
|
health.check.detail.filterFixState=해결 상태로 정렬
|
||||||
@@ -286,7 +286,7 @@ health.result.severityTip.crit=상태: 심각\nVault 구조가 손상되었습
|
|||||||
health.result.fixStateFilter.all=모든 문제 해결 상태
|
health.result.fixStateFilter.all=모든 문제 해결 상태
|
||||||
health.result.fixStateFilter.fixable=문제 해결 가능
|
health.result.fixStateFilter.fixable=문제 해결 가능
|
||||||
health.result.fixStateFilter.notFixable=문제 해결 불가
|
health.result.fixStateFilter.notFixable=문제 해결 불가
|
||||||
health.result.fixStateFilter.fixing=문제 해결중…
|
health.result.fixStateFilter.fixing=문제 해결 중…
|
||||||
health.result.fixStateFilter.fixed=문제 해결됨
|
health.result.fixStateFilter.fixed=문제 해결됨
|
||||||
health.result.fixStateFilter.fixFailed=문제 해결 실패
|
health.result.fixStateFilter.fixFailed=문제 해결 실패
|
||||||
## Fix Application
|
## Fix Application
|
||||||
@@ -295,7 +295,7 @@ health.fix.successTip=문제 해결이 성공적으로 완료되었습니다
|
|||||||
health.fix.failTip=문제 해결 실패, 상세 정보는 로그를 참조하십시오.
|
health.fix.failTip=문제 해결 실패, 상세 정보는 로그를 참조하십시오.
|
||||||
|
|
||||||
# Preferences
|
# Preferences
|
||||||
preferences.title=환경설정
|
preferences.title=환경 설정
|
||||||
## General
|
## General
|
||||||
preferences.general=일반
|
preferences.general=일반
|
||||||
preferences.general.startHidden=Cryptomator를 시작할 때 창 숨김
|
preferences.general.startHidden=Cryptomator를 시작할 때 창 숨김
|
||||||
@@ -309,9 +309,9 @@ preferences.general.quickAccessService=열린 Vault를 빠른 접근 위치에
|
|||||||
preferences.interface=인터페이스
|
preferences.interface=인터페이스
|
||||||
preferences.interface.theme=테마
|
preferences.interface.theme=테마
|
||||||
preferences.interface.theme.automatic=자동
|
preferences.interface.theme.automatic=자동
|
||||||
preferences.interface.theme.dark=어둡게
|
preferences.interface.theme.dark=다크 모드
|
||||||
preferences.interface.theme.light=밝게
|
preferences.interface.theme.light=라이트 모드
|
||||||
preferences.interface.unlockThemes=다크모드 해제
|
preferences.interface.unlockThemes=다크 모드 사용 권한을 얻어보세요!
|
||||||
preferences.interface.language=언어 (재시작 필요)
|
preferences.interface.language=언어 (재시작 필요)
|
||||||
preferences.interface.language.auto=시스템 기본 설정
|
preferences.interface.language.auto=시스템 기본 설정
|
||||||
preferences.interface.interfaceOrientation=인터페이스 방향
|
preferences.interface.interfaceOrientation=인터페이스 방향
|
||||||
@@ -356,7 +356,7 @@ preferences.contribute=후원하기
|
|||||||
preferences.contribute.registeredFor=%s(으)로 후원자 인증 등록됨
|
preferences.contribute.registeredFor=%s(으)로 후원자 인증 등록됨
|
||||||
preferences.contribute.noCertificate=Cryptomator를 후원하시고 후원자 인증을 받으십시오. 라이선스 키와 비슷하지만 무료 소프트웨어를 사용하는 멋진 사람들을 위한 것입니다. ;-)
|
preferences.contribute.noCertificate=Cryptomator를 후원하시고 후원자 인증을 받으십시오. 라이선스 키와 비슷하지만 무료 소프트웨어를 사용하는 멋진 사람들을 위한 것입니다. ;-)
|
||||||
preferences.contribute.getCertificate=아직 후원자 인증이 없으신가요? 어떻게 얻는지 배울 수 있습니다.
|
preferences.contribute.getCertificate=아직 후원자 인증이 없으신가요? 어떻게 얻는지 배울 수 있습니다.
|
||||||
preferences.contribute.promptText=후원자 인증코드를 여기에 붙여넣기
|
preferences.contribute.promptText=후원자 인증 코드를 여기에 붙여넣기
|
||||||
preferences.contribute.thankYou=Cryptomator의 오픈 소스 개발을 지원해 주셔서 감사합니다!
|
preferences.contribute.thankYou=Cryptomator의 오픈 소스 개발을 지원해 주셔서 감사합니다!
|
||||||
preferences.contribute.donate=후원하기
|
preferences.contribute.donate=후원하기
|
||||||
preferences.contribute.sponsor=스폰서
|
preferences.contribute.sponsor=스폰서
|
||||||
@@ -364,7 +364,7 @@ preferences.contribute.removeCert.tooltip=인증서 제거
|
|||||||
|
|
||||||
### Remove License Key Dialog
|
### Remove License Key Dialog
|
||||||
removeCert.title=인증서 제거
|
removeCert.title=인증서 제거
|
||||||
removeCert.message=서포터 인증서를 제거하시겠습니까?
|
removeCert.message=후원자 인증서를 제거하시겠습니까?
|
||||||
removeCert.description=Cryptomator의 핵심 기능은 영향을 받지 않습니다. Vault에 대한 접근이 제한되거나 보안이 약화되지 않습니다.
|
removeCert.description=Cryptomator의 핵심 기능은 영향을 받지 않습니다. Vault에 대한 접근이 제한되거나 보안이 약화되지 않습니다.
|
||||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
#<-- Add entries for donations and code/translation/documentation contribution -->
|
||||||
|
|
||||||
@@ -392,7 +392,7 @@ stats.read.accessCount=총 읽기 횟수: %d
|
|||||||
stats.write.throughput.idle=쓰기: 대기 중
|
stats.write.throughput.idle=쓰기: 대기 중
|
||||||
stats.write.throughput.kibs=쓰기: %.2f KiB/s
|
stats.write.throughput.kibs=쓰기: %.2f KiB/s
|
||||||
stats.write.throughput.mibs=쓰기: %.2f MiB/s
|
stats.write.throughput.mibs=쓰기: %.2f MiB/s
|
||||||
stats.write.total.data.none=데이터 기록됨: -
|
stats.write.total.data.none=데이터 쓰기: -
|
||||||
stats.write.total.data.kib=데이터 쓰기: %.1f KiB
|
stats.write.total.data.kib=데이터 쓰기: %.1f KiB
|
||||||
stats.write.total.data.mib=데이터 쓰기: %.1f MiB
|
stats.write.total.data.mib=데이터 쓰기: %.1f MiB
|
||||||
stats.write.total.data.gib=데이터 쓰기: %.1f GiB
|
stats.write.total.data.gib=데이터 쓰기: %.1f GiB
|
||||||
@@ -427,11 +427,11 @@ main.vaultlist.showEventsButton.tooltip=이벤트 뷰어 열기
|
|||||||
main.vaultlist.showPreferencesButton.tooltip=환경 설정 표시
|
main.vaultlist.showPreferencesButton.tooltip=환경 설정 표시
|
||||||
##Notification
|
##Notification
|
||||||
main.notification.updateAvailable=업데이트가 있습니다.
|
main.notification.updateAvailable=업데이트가 있습니다.
|
||||||
main.notification.support=Cryptomator 지원하기.
|
main.notification.support=Cryptomator 지원해 주세요
|
||||||
main.notification.closeButton.tooltip=정보 표시줄 닫기
|
main.notification.closeButton.tooltip=정보 표시줄 닫기
|
||||||
## Vault Detail
|
## Vault Detail
|
||||||
### Welcome
|
### Welcome
|
||||||
main.vaultDetail.welcomeOnboarding=파일을 보호하기 위해 Cryptomator를 선택해주셔서 감사합니다. 만약 다른 도움이 필요하시면, 시작 안내서를 참조하시기 바랍니다.
|
main.vaultDetail.welcomeOnboarding=파일 보호를 위해 Cryptomator를 선택해 주셔서 감사합니다. 도움이 필요하시면 시작 가이드를 확인해 주십시오:
|
||||||
main.vaultDetail.storageLocation=Vault 저장 위치
|
main.vaultDetail.storageLocation=Vault 저장 위치
|
||||||
### Locked
|
### Locked
|
||||||
main.vaultDetail.lockedStatus=잠김
|
main.vaultDetail.lockedStatus=잠김
|
||||||
@@ -702,7 +702,7 @@ eventView.entry.decryptionFailed.message=복호화 실패
|
|||||||
eventView.entry.decryptionFailed.showEncrypted=암호화된 파일 보기
|
eventView.entry.decryptionFailed.showEncrypted=암호화된 파일 보기
|
||||||
eventView.entry.brokenDirFile.message=망가진 디렉터리 링크
|
eventView.entry.brokenDirFile.message=망가진 디렉터리 링크
|
||||||
eventView.entry.brokenDirFile.showEncrypted=망가진 암호화된 링크 보기
|
eventView.entry.brokenDirFile.showEncrypted=망가진 암호화된 링크 보기
|
||||||
eventView.entry.brokenFileNode.message=망가진 파일시스템 노드
|
eventView.entry.brokenFileNode.message=망가진 파일 시스템 노드
|
||||||
eventView.entry.brokenFileNode.showEncrypted=망가진 암호화된 노드 보기
|
eventView.entry.brokenFileNode.showEncrypted=망가진 암호화된 노드 보기
|
||||||
eventView.entry.brokenFileNode.copyDecrypted=복호화된 경로 복사하기
|
eventView.entry.brokenFileNode.copyDecrypted=복호화된 경로 복사하기
|
||||||
eventView.entry.inUse.message=파일 사용 중
|
eventView.entry.inUse.message=파일 사용 중
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ wrongFileAlert.link=Para obter assistência, visite
|
|||||||
## General
|
## General
|
||||||
vaultOptions.general=Geral
|
vaultOptions.general=Geral
|
||||||
vaultOptions.general.vaultName=Nome do cofre
|
vaultOptions.general.vaultName=Nome do cofre
|
||||||
vaultOptions.general.autoLock.lockAfterTimePart1=Bloquear quando inativo por
|
vaultOptions.general.autoLock.lockAfterTimePart1=Bloquear quando inativo após
|
||||||
vaultOptions.general.autoLock.lockAfterTimePart2=minuto(s)
|
vaultOptions.general.autoLock.lockAfterTimePart2=minuto(s)
|
||||||
vaultOptions.general.autoLock.accessibleText=Bloquear tempo limite em minutos
|
vaultOptions.general.autoLock.accessibleText=Bloquear tempo limite em minutos
|
||||||
vaultOptions.general.unlockAfterStartup=Desbloquear o cofre ao iniciar o Cryptomator
|
vaultOptions.general.unlockAfterStartup=Desbloquear o cofre ao iniciar o Cryptomator
|
||||||
|
|||||||
@@ -705,10 +705,15 @@ eventView.entry.brokenDirFile.showEncrypted=顯示損壞的加密路徑
|
|||||||
eventView.entry.brokenFileNode.message=損壞的檔案系統節點
|
eventView.entry.brokenFileNode.message=損壞的檔案系統節點
|
||||||
eventView.entry.brokenFileNode.showEncrypted=顯示損壞的加密節點
|
eventView.entry.brokenFileNode.showEncrypted=顯示損壞的加密節點
|
||||||
eventView.entry.brokenFileNode.copyDecrypted=複製解密路徑
|
eventView.entry.brokenFileNode.copyDecrypted=複製解密路徑
|
||||||
|
eventView.entry.inUse.message=檔案正在使用中
|
||||||
eventView.entry.inUse.showDecrypted=顯示解密的檔案
|
eventView.entry.inUse.showDecrypted=顯示解密的檔案
|
||||||
eventView.entry.inUse.showEncrypted=顯示加密的檔案
|
eventView.entry.inUse.showEncrypted=顯示加密的檔案
|
||||||
eventView.entry.inUse.copyUserAndDevice=複製鎖定的使用者和裝置名稱
|
eventView.entry.inUse.copyUserAndDevice=複製鎖定的使用者和裝置名稱
|
||||||
|
eventView.entry.inUse.ignoreLock=忽略使用狀態
|
||||||
|
|
||||||
|
|
||||||
# Notifications
|
# Notifications
|
||||||
## FileIsInUse Notification
|
## FileIsInUse Notification
|
||||||
|
notification.inUse.message=檔案正在被另一部裝置使用中
|
||||||
|
notification.inUse.description=這個檔案正在由 %s 在 %s 開啟中。告訴他們關閉檔案讓同步完成。您可以忽略這個狀態並且馬上開啟,但是可能會造成衝突或把新的變更覆蓋掉。
|
||||||
|
notification.inUse.action=忽略使用狀態
|
||||||
@@ -29,7 +29,8 @@ public class SettingsJsonTest {
|
|||||||
"checkForUpdatesEnabled": true,
|
"checkForUpdatesEnabled": true,
|
||||||
"port": 8080,
|
"port": 8080,
|
||||||
"language": "de-DE",
|
"language": "de-DE",
|
||||||
"numTrayNotifications": 42
|
"numTrayNotifications": 42,
|
||||||
|
"trustedHosts": null
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ public class SettingsJsonTest {
|
|||||||
Assertions.assertTrue(jsonObj.autoCloseVaults);
|
Assertions.assertTrue(jsonObj.autoCloseVaults);
|
||||||
Assertions.assertEquals("de-DE", jsonObj.language);
|
Assertions.assertEquals("de-DE", jsonObj.language);
|
||||||
Assertions.assertEquals(42, jsonObj.numTrayNotifications);
|
Assertions.assertEquals(42, jsonObj.numTrayNotifications);
|
||||||
|
Assertions.assertEquals(0, jsonObj.trustedHosts.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.cryptomator.ui.keyloading.hub;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
class CheckHostTrustControllerTest {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"https://auth.example.com, https://hub.example.com, true",
|
||||||
|
"https://hub.example.com, https://hub.example.com, true",
|
||||||
|
"https://auth.example.com, https://auth.example.com, true",
|
||||||
|
"https://auth.example.com, https://wrong.example.com, false",
|
||||||
|
"https://wrong.example.com, https://wrong.example.com, false"
|
||||||
|
})
|
||||||
|
void testContainsAllowedHosts(String apiBase, String authEndpoint, boolean expectedResult) {
|
||||||
|
var hubConfig = new HubConfig();
|
||||||
|
hubConfig.apiBaseUrl = apiBase;
|
||||||
|
hubConfig.authEndpoint = authEndpoint;
|
||||||
|
var controller = new CheckHostTrustController(Mockito.mock(), hubConfig, Mockito.mock(), Mockito.mock(), Mockito.mock(), Mockito.mock(), Mockito.mock(), Mockito.mock());
|
||||||
|
|
||||||
|
var actualResult = controller.containsAllowedHosts(Set.of("https://auth.example.com", "https://hub.example.com"));
|
||||||
|
|
||||||
|
Assertions.assertEquals(expectedResult, actualResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"https://example.com, https://example.com",
|
||||||
|
"https://example.com/foo/bar, https://example.com",
|
||||||
|
"https://example.com:8080, https://example.com:8080",
|
||||||
|
"https://user@example.com:8080/foo/bar, https://example.com:8080",
|
||||||
|
"https://user@example.com:443/foo/bar, https://example.com:443",
|
||||||
|
"http://user@example.com:80/foo/bar?foo=bar, http://example.com:80",
|
||||||
|
"http://user@example.com:8080/foo/bar?foo=bar, http://example.com:8080"
|
||||||
|
})
|
||||||
|
void testGetAuthority(String input, String expected) {
|
||||||
|
var actual = CheckHostTrustController.getAuthority(input);
|
||||||
|
|
||||||
|
Assertions.assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user