diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 021275f7..5d18cea3 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -72,8 +72,8 @@ quarkus.flyway.locations=classpath:org/cryptomator/hub/flyway %test.quarkus.application.version=TEST_VERSION_3000 # HTTP Security Headers see e.g. https://owasp.org/www-project-secure-headers/#div-bestpractices -quarkus.http.header."Content-Security-Policy".value=default-src 'self'; object-src 'none'; child-src 'self'; img-src * data:; frame-ancestors 'none' -%dev.quarkus.http.header."Content-Security-Policy".value=default-src 'self'; connect-src 'self' localhost:8180; object-src 'none'; child-src 'self'; img-src * data:; frame-ancestors 'none' +quarkus.http.header."Content-Security-Policy".value=default-src 'self'; connect-src 'self' api.cryptomator.org; object-src 'none'; child-src 'self'; img-src * data:; frame-ancestors 'none' +%dev.quarkus.http.header."Content-Security-Policy".value=default-src 'self'; connect-src 'self' api.cryptomator.org localhost:8180; object-src 'none'; child-src 'self'; img-src * data:; frame-ancestors 'none' quarkus.http.header."Referrer-Policy".value=no-referrer quarkus.http.header."Strict-Transport-Security".value=max-age=31536000; includeSubDomains quarkus.http.header."X-Content-Type-Options".value=nosniff diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 714523d7..e864fded 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -17,6 +17,7 @@ "keycloak-js": "^18.0.0", "miscreant": "^0.3.2", "rfc4648": "^1.5.1", + "semver": "^7.3.7", "vue": "^3.2.31", "vue-i18n": "^9.1.10", "vue-router": "^4.0.15" @@ -30,6 +31,7 @@ "@types/file-saver": "^2.0.5", "@types/mocha": "^9.1.1", "@types/node": "^17.0.32", + "@types/semver": "^7.3.12", "@typescript-eslint/eslint-plugin": "^5.23.0", "@typescript-eslint/parser": "^5.23.0", "@vitejs/plugin-vue": "^2.3.3", @@ -528,6 +530,12 @@ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", + "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", @@ -3139,7 +3147,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4054,7 +4061,6 @@ "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -4861,8 +4867,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -5331,6 +5336,12 @@ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "dev": true }, + "@types/semver": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", + "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", @@ -7166,7 +7177,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -7831,7 +7841,6 @@ "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -8422,8 +8431,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.2", diff --git a/frontend/package.json b/frontend/package.json index fe390c95..e2de5afc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "@types/file-saver": "^2.0.5", "@types/mocha": "^9.1.1", "@types/node": "^17.0.32", + "@types/semver": "^7.3.12", "@typescript-eslint/eslint-plugin": "^5.23.0", "@typescript-eslint/parser": "^5.23.0", "@vitejs/plugin-vue": "^2.3.3", @@ -53,6 +54,7 @@ "keycloak-js": "^18.0.0", "miscreant": "^0.3.2", "rfc4648": "^1.5.1", + "semver": "^7.3.7", "vue": "^3.2.31", "vue-i18n": "^9.1.10", "vue-router": "^4.0.15" diff --git a/frontend/src/common/backend.ts b/frontend/src/common/backend.ts index 4a6eba83..8f13a7aa 100644 --- a/frontend/src/common/backend.ts +++ b/frontend/src/common/backend.ts @@ -11,7 +11,6 @@ const axiosBaseCfg: AxiosRequestConfig = { } }; -const axios = AxiosStatic.create(axiosBaseCfg); const axiosAuth = AxiosStatic.create(axiosBaseCfg); axiosAuth.interceptors.request.use(async request => { const auth = await authPromise; diff --git a/frontend/src/common/updatecheck.ts b/frontend/src/common/updatecheck.ts new file mode 100644 index 00000000..cef019f6 --- /dev/null +++ b/frontend/src/common/updatecheck.ts @@ -0,0 +1,33 @@ +import AxiosStatic from 'axios'; + +const axios = AxiosStatic.create(); + +export class LatestVersionDto { + constructor(public stable: string, public beta: string) { } +} + +class UpdatesService { + public async get(localVersion: string): Promise { + let config = { + headers: { + 'Content-Type': 'application/json', + 'X-Hub-Version': localVersion, + 'X-Hub-Instance': 'TODO' //for future uses + } + }; + return axios.get('https://api.cryptomator.org/updates/hub.json', config) + .then(response => response.data) + .catch(err => { + console.error(err); + throw new FetchUpdateError('Unable to get update info.'); + }); + } +} + +export class FetchUpdateError extends Error { + constructor(msg: string) { + super(msg); + } +} + +export const updateChecker = new UpdatesService(); diff --git a/frontend/src/components/Settings.vue b/frontend/src/components/Settings.vue index 549c324d..8431c75a 100644 --- a/frontend/src/components/Settings.vue +++ b/frontend/src/components/Settings.vue @@ -54,6 +54,27 @@
+ +

+

+

+

+

+

+

+

+

+

@@ -68,27 +89,53 @@ diff --git a/frontend/src/i18n/de-DE.json b/frontend/src/i18n/de-DE.json index fab09092..7c6c01e6 100644 --- a/frontend/src/i18n/de-DE.json +++ b/frontend/src/i18n/de-DE.json @@ -50,6 +50,10 @@ "settings.title": "Einstellungen", "settings.general.title": "Allgemein", "settings.general.language.title": "Sprache", + "settings.update.upToDate.description": "Hub ist aktuell", + "settings.update.updateExists.description": "Update auf Version {0} möglich", + "settings.update.fetchingUpdatesFailed.description": "Suche nach Updates ist fehlgeschlagen. Bitte prüfe manuell.", + "vaultDetails.notFound": "Tresor nicht gefunden", "vaultDetails.sharedWith.title": "Geteilt mit", diff --git a/frontend/src/i18n/en-US.json b/frontend/src/i18n/en-US.json index dec4da1b..f9de35fb 100644 --- a/frontend/src/i18n/en-US.json +++ b/frontend/src/i18n/en-US.json @@ -91,6 +91,9 @@ "settings.version.title": "Server Info", "settings.version.hub.title": "Hub version", "settings.version.keycloak.title": "Keycloak version", + "settings.update.upToDate.description": "Hub is up-to-date", + "settings.update.updateExists.description": "Update to version {0} possible", + "settings.update.fetchingUpdatesFailed.description": "Unable to check for updates. Please check manually.", "vaultDetails.description.header": "Description", "vaultDetails.description.empty": "No description provided.",