Skip to content

Commit

Permalink
Merge pull request #121 from cryptomator/update-check
Browse files Browse the repository at this point in the history
Fetch and show update info in settings screen
  • Loading branch information
infeo authored Aug 16, 2022
2 parents 3c55d7c + 9418fb5 commit e7a903c
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 16 deletions.
4 changes: 2 additions & 2 deletions backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 16 additions & 8 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
1 change: 0 additions & 1 deletion frontend/src/common/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions frontend/src/common/updatecheck.ts
Original file line number Diff line number Diff line change
@@ -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<LatestVersionDto> {
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();
57 changes: 52 additions & 5 deletions frontend/src/components/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@
<div class="col-span-6 sm:col-span-3">
<label for="hubVersion" class="block text-sm font-medium text-gray-700">{{ t('settings.version.hub.title') }}</label>
<input id="hubVersion" v-model="version.hubVersion" type="text" class="mt-1 focus:ring-primary focus:border-primary block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-200" readonly />

<p v-if="errorOnFetchingUpdates" id="version-description" class="inline-flex mt-2 text-sm text-gray-500">
<ExclamationIcon class="shrink-0 text-orange-500 mr-1 h-5 w-5" aria-hidden="true" />
{{ t('settings.update.fetchingUpdatesFailed.description') }}
</p>
<p v-else-if="!stableUpdateExists && !betaUpdateExists" id="version-description" class="inline-flex mt-2 text-sm text-gray-500">
<CheckIcon class="shrink-0 text-primary mr-1 h-5 w-5" aria-hidden="true" />
{{ t('settings.update.upToDate.description') }}
</p>
<p v-else-if="stableUpdateExists" id="version-description" class="inline-flex mt-2 text-sm text-gray-500">
<ExclamationIcon class="shrink-0 text-orange-500 mr-1 h-5 w-5" aria-hidden="true" />
{{ t('settings.update.updateExists.description', [latestVersion?.stable]) }}
</p>
<p v-else-if="betaUpdateExists && isBeta" id="version-description" class="inline-flex mt-2 text-sm text-gray-500">
<ExclamationIcon class="shrink-0 text-orange-500 mr-1 h-5 w-5" aria-hidden="true" />
{{ t('settings.update.updateExists.description', [latestVersion?.beta]) }}
</p>
<p v-else-if="betaUpdateExists && !isBeta" id="version-description" class="inline-flex mt-2 text-sm text-gray-500">
<InformationCircleIcon class="shrink-0 text-primary mr-1 h-5 w-5" aria-hidden="true" />
{{ t('settings.update.updateExists.description', [latestVersion?.beta]) }}
</p>
</div>
<div class="col-span-6 sm:col-span-3">
<label for="keycloakVersion" class="block text-sm font-medium text-gray-700">{{ t('settings.version.keycloak.title') }}</label>
Expand All @@ -68,27 +89,53 @@
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { CheckIcon, ExclamationIcon, InformationCircleIcon } from '@heroicons/vue/solid';
import semver from 'semver';
import { computed, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import backend, { VersionDto } from '../common/backend';
import { FetchUpdateError, LatestVersionDto, updateChecker } from '../common/updatecheck';
import { Locale } from '../i18n';
import FetchError from './FetchError.vue';
const { t } = useI18n({ useScope: 'global' });
const version = ref<VersionDto>();
const latestVersion = ref<LatestVersionDto>();
const onFetchError = ref<Error | null>();
const errorOnFetchingUpdates = ref<boolean>(false);
const isBeta = computed(() => semver.prerelease(version.value?.hubVersion ?? '0.1.0') != null);
const stableUpdateExists = computed(() => {
if (version.value && latestVersion.value?.stable) {
return semver.lt(version.value?.hubVersion , latestVersion.value.stable ?? '0.1.0');
}
return false;
});
const betaUpdateExists = computed(() => {
if (version.value && latestVersion.value?.beta) {
return semver.lt(version.value?.hubVersion , latestVersion.value.beta ?? '0.1.0-beta1');
}
return false;
});
onMounted(fetchData);
async function fetchData() {
onFetchError.value = null;
try {
version.value = await backend.version.get();
let versionInstalled = backend.version.get();
let versionAvailable = versionInstalled.then(versionDto => updateChecker.get(versionDto.hubVersion));
version.value = await versionInstalled;
latestVersion.value = await versionAvailable;
} catch (err) {
console.error('Retrieving version failed.', err);
onFetchError.value = err instanceof Error ? err : new Error('Unknown Error');
if (err instanceof FetchUpdateError) {
errorOnFetchingUpdates.value = true;
} else {
console.error('Retrieving version information failed.', err);
onFetchError.value = err instanceof Error ? err : new Error('Unknown Error');
}
}
}
</script>
4 changes: 4 additions & 0 deletions frontend/src/i18n/de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down

0 comments on commit e7a903c

Please sign in to comment.