Skip to content

Commit

Permalink
feat(controller): added check for api version mismatch in units
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaile authored Sep 9, 2024
1 parent 5303318 commit 1031fe5
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 24 deletions.
1 change: 1 addition & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/// <reference types="vite/client" />
declare const UI_VERSION: string
declare const REQUIRED_API_VERSION: string
27 changes: 21 additions & 6 deletions package-lock.json

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

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"name": "nethsecurity-ui",
"version": "1.1.0",
"config": {
"requiredApiVersion": "~1.0.0"
},
"private": true,
"scripts": {
"dev": "vite --host",
Expand Down Expand Up @@ -64,6 +67,7 @@
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.4.1",
"semver": "^7.6.3",
"tailwindcss": "^3.3.2",
"typescript": "~5.0.4",
"vite": "^4.3.5",
Expand Down
7 changes: 6 additions & 1 deletion public/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2045,7 +2045,12 @@
"num_units_left_tooltip": "You have configured {num} of {max} units. Upgrade to a subscription plan to manage more units.",
"sync_unit_info": "Sync unit info",
"syncing_data": "Syncing data...",
"syncing_data_description": "Unit data hasn't been synced yet. You can do it now by clicking the three dots menu and then '@:controller.units.sync_unit_info '."
"syncing_data_description": "Unit data hasn't been synced yet. You can do it now by clicking the three dots menu and then '@:controller.units.sync_unit_info '.",
"cannot_open_unit": "Cannot open unit",
"cannot_open_unit_description": "The unit {name} must be updated before opening it. Access the unit UI directly and go to System > Updates page.",
"open_anyway": "Open anyway",
"warning_open_unit": "Controller is not up-to-date",
"warning_open_unit_description": "It appears that the controller is not up-to-date. It's recommended to update the controller instance on your NethServer 8 cluster before opening this unit to avoid compatibility issues."
},
"unit_terminal": {
"name_unit_terminal": "{name} unit terminal",
Expand Down
88 changes: 72 additions & 16 deletions src/components/controller/units/UnitsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,34 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import {
byteFormat1024,
deleteFromStorage,
formatDateLoc,
getAxiosErrorMessage,
getPreference,
NeButton,
NeDropdown,
NeInlineNotification,
NeLink,
NeTooltip,
NeModal,
NePaginator,
NeTable,
NeTableBody,
NeTableCell,
NeTableHead,
NeTableHeadCell,
NeTableBody,
NeTableRow,
NeTableCell,
NePaginator,
getAxiosErrorMessage,
getPreference,
NeTooltip,
savePreference,
byteFormat1024,
formatDateLoc,
deleteFromStorage,
useItemPagination
} from '@nethesis/vue-components'
import { useUnitsStore, type Unit } from '@/stores/controller/units'
import { type Unit, useUnitsStore } from '@/stores/controller/units'
import { useDefaultsStore } from '@/stores/controller/defaults'
import router from '@/router'
import { onMounted, ref, type PropType } from 'vue'
import { onMounted, type PropType, ref } from 'vue'
import { useLoginStore } from '@/stores/controller/controllerLogin'
import RemoveUnitModal from '@/components/controller/units/RemoveUnitModal.vue'
import { outside, satisfies } from 'semver'

const props = defineProps({
filteredUnits: {
Expand All @@ -54,6 +56,9 @@ const { currentPage, paginatedItems } = useItemPagination(() => props.filteredUn
const hideOpenUnitPopupsTooltip = ref(false)
const currentUnit = ref<Unit>()
const isShownRemoveUnitModal = ref(false)
const loadingOpenUnit = ref(false)
const showObsoleteApiModal = ref(false)
const showGreaterApiModal = ref(false)

let error = ref({
openUnit: ''
Expand All @@ -63,16 +68,38 @@ onMounted(() => {
hideOpenUnitPopupsTooltip.value = getPreference('hideOpenUnitPopupsTooltip', loginStore.username)
})

async function openUnit(unitId: string) {
async function openUnit(unit: Unit, versionCheck = true) {
error.value.openUnit = ''
currentUnit.value = unit
loadingOpenUnit.value = true

try {
await unitsStore.checkUnitToken(unitId)
const routeData = router.resolve({ path: `/controller/manage/${unitId}/dashboard` })
window.open(routeData.href, '_blank')
await unitsStore.getUnitInfo(currentUnit.value.id)
await unitsStore.getUnits()
// Find the now updated unit, as the currentUnit might have changed
currentUnit.value = unitsStore.units.find((u) => u.id == unit.id)!
// Logic on which message is shown is inside the ObsoleteApiModal component
let version = currentUnit.value?.info.api_version
if (version == '') {
version = '0.0.0'
}
if (versionCheck && !satisfies(version, REQUIRED_API_VERSION)) {
if (outside(version, REQUIRED_API_VERSION, '>')) {
showGreaterApiModal.value = true
} else {
showObsoleteApiModal.value = true
}
} else {
await unitsStore.checkUnitToken(unit.id)
const routeData = router.resolve({ path: `/controller/manage/${unit.id}/dashboard` })
window.open(routeData.href, '_blank')
showGreaterApiModal.value = false
}
} catch (err: any) {
console.error(err)
error.value.openUnit = t(getAxiosErrorMessage(err))
} finally {
loadingOpenUnit.value = false
}
}

Expand Down Expand Up @@ -393,8 +420,10 @@ function showRemoveUnitModal(unit: Unit) {
<template v-if="item.connected">
<NeButton
v-if="hideOpenUnitPopupsTooltip"
:disabled="loadingOpenUnit && currentUnit?.id == item.id"
:loading="loadingOpenUnit && currentUnit?.id == item.id"
kind="tertiary"
@click="openUnit(item.id)"
@click="openUnit(item)"
class="shrink-0"
>
<template #prefix>
Expand Down Expand Up @@ -469,5 +498,32 @@ function showRemoveUnitModal(unit: Unit) {
@close="isShownRemoveUnitModal = false"
@reloadData="emit('reloadData')"
/>
<!-- Modal that forbids opening units with obsolete API -->
<NeModal
:primaryLabel="t('common.close')"
:closeAriaLabel="t('common.close')"
:title="t('controller.units.cannot_open_unit')"
:visible="showObsoleteApiModal"
kind="info"
@close="showObsoleteApiModal = false"
@primaryClick="showObsoleteApiModal = false"
>
{{
t('controller.units.cannot_open_unit_description', { name: currentUnit?.info.unit_name })
}}
</NeModal>
<!-- Modal that shows a warning if the API version is newer than the required one -->
<NeModal
:primaryLabel="t('controller.units.open_anyway')"
:cancelLabel="t('common.close')"
:closeAriaLabel="t('common.close')"
:title="t('controller.units.warning_open_unit')"
:visible="showGreaterApiModal"
kind="warning"
@close="showGreaterApiModal = false"
@primaryClick="openUnit(currentUnit!, false)"
>
{{ t('controller.units.warning_open_unit_description') }}
</NeModal>
</div>
</template>
1 change: 1 addition & 0 deletions src/stores/controller/units.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface UnitInfo {
unit_id: string
unit_name: string
version: string
api_version: string
}

interface UnitVpnData {
Expand Down
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default defineConfig({
}
},
define: {
UI_VERSION: process.env.npm_package_version
UI_VERSION: JSON.stringify(process.env.npm_package_version),
REQUIRED_API_VERSION: JSON.stringify(process.env.npm_package_config_requiredApiVersion)
}
})

0 comments on commit 1031fe5

Please sign in to comment.