diff --git a/ui/src/store/modules/user.js b/ui/src/store/modules/user.js index 46a1905619f..e535bd451e4 100644 --- a/ui/src/store/modules/user.js +++ b/ui/src/store/modules/user.js @@ -18,12 +18,15 @@ import Cookies from 'js-cookie' import message from 'ant-design-vue/es/message' import notification from 'ant-design-vue/es/notification' +import semver from 'semver' import { vueProps } from '@/vue-app' import router from '@/router' import store from '@/store' import { oauthlogin, login, logout, api } from '@/api' import { i18n } from '@/locales' +import { axios } from '../../utils/request' +import { getParsedVersion } from '@/utils/util' import { ACCESS_TOKEN, @@ -31,6 +34,7 @@ import { DEFAULT_THEME, APIS, ZONES, + SHOW_SECURTIY_GROUPS, TIMEZONE_OFFSET, USE_BROWSER_TIMEZONE, HEADER_NOTICES, @@ -38,7 +42,8 @@ import { DARK_MODE, CUSTOM_COLUMNS, OAUTH_DOMAIN, - OAUTH_PROVIDER + OAUTH_PROVIDER, + LATEST_CS_VERSION } from '@/store/mutation-types' const user = { @@ -120,6 +125,10 @@ const user = { state.zones = zones vueProps.$localStorage.set(ZONES, zones) }, + SET_SHOW_SECURITY_GROUPS: (state, show) => { + state.showSecurityGroups = show + vueProps.$localStorage.set(SHOW_SECURTIY_GROUPS, show) + }, SET_DOMAIN_STORE (state, domainStore) { state.domainStore = domainStore vueProps.$localStorage.set(DOMAIN_STORE, domainStore) @@ -167,6 +176,12 @@ const user = { }, SET_OAUTH_PROVIDER_USED_TO_LOGIN: (state, provider) => { vueProps.$localStorage.set(OAUTH_PROVIDER, provider) + }, + SET_LATEST_VERSION: (state, version) => { + if (version?.fetchedTs > 0) { + vueProps.$localStorage.set(LATEST_CS_VERSION, version) + state.latestVersion = version + } } }, @@ -212,6 +227,8 @@ const user = { commit('SET_2FA_PROVIDER', result.providerfor2fa) commit('SET_2FA_ISSUER', result.issuerfor2fa) commit('SET_LOGIN_FLAG', false) + const latestVersion = vueProps.$localStorage.get(LATEST_CS_VERSION, { version: '', fetchedTs: 0 }) + commit('SET_LATEST_VERSION', latestVersion) notification.destroy() resolve() @@ -259,6 +276,8 @@ const user = { commit('SET_2FA_PROVIDER', result.providerfor2fa) commit('SET_2FA_ISSUER', result.issuerfor2fa) commit('SET_LOGIN_FLAG', false) + const latestVersion = vueProps.$localStorage.get(LATEST_CS_VERSION, { version: '', fetchedTs: 0 }) + commit('SET_LATEST_VERSION', latestVersion) notification.destroy() resolve() @@ -276,14 +295,18 @@ const user = { const cachedUseBrowserTimezone = vueProps.$localStorage.get(USE_BROWSER_TIMEZONE, false) const cachedCustomColumns = vueProps.$localStorage.get(CUSTOM_COLUMNS, {}) const domainStore = vueProps.$localStorage.get(DOMAIN_STORE, {}) + const cachedShowSecurityGroups = vueProps.$localStorage.get(SHOW_SECURTIY_GROUPS, false) const darkMode = vueProps.$localStorage.get(DARK_MODE, false) + const latestVersion = vueProps.$localStorage.get(LATEST_CS_VERSION, { version: '', fetchedTs: 0 }) const hasAuth = Object.keys(cachedApis).length > 0 commit('SET_DOMAIN_STORE', domainStore) commit('SET_DARK_MODE', darkMode) + commit('SET_LATEST_VERSION', latestVersion) if (hasAuth) { console.log('Login detected, using cached APIs') commit('SET_ZONES', cachedZones) + commit('SET_SHOW_SECURITY_GROUPS', cachedShowSecurityGroups) commit('SET_APIS', cachedApis) commit('SET_TIMEZONE_OFFSET', cachedTimezoneOffset) commit('SET_USE_BROWSER_TIMEZONE', cachedUseBrowserTimezone) @@ -294,6 +317,7 @@ const user = { const result = response.listusersresponse.user[0] commit('SET_INFO', result) commit('SET_NAME', result.firstname + ' ' + result.lastname) + store.dispatch('SetCsLatestVersion', result.rolename) resolve(cachedApis) }).catch(error => { reject(error) @@ -314,7 +338,10 @@ const user = { const apiName = api.name apis[apiName] = { params: api.params, - response: api.response + response: api.response, + isasync: api.isasync, + since: api.since, + description: api.description } } commit('SET_APIS', apis) @@ -329,16 +356,54 @@ const user = { }).catch(error => { reject(error) }) + + api('listNetworks', { restartrequired: true, forvpc: false }).then(response => { + if (response.listnetworksresponse.count > 0) { + store.dispatch('AddHeaderNotice', { + key: 'NETWORK_RESTART_REQUIRED', + title: i18n.global.t('label.network.restart.required'), + description: i18n.global.t('message.network.restart.required'), + path: '/guestnetwork/', + query: { restartrequired: true, forvpc: false }, + status: 'done', + timestamp: new Date() + }) + } + }).catch(ignored => {}) + + api('listVPCs', { restartrequired: true }).then(response => { + if (response.listvpcsresponse.count > 0) { + store.dispatch('AddHeaderNotice', { + key: 'VPC_RESTART_REQUIRED', + title: i18n.global.t('label.vpc.restart.required'), + description: i18n.global.t('message.vpc.restart.required'), + path: '/vpc/', + query: { restartrequired: true }, + status: 'done', + timestamp: new Date() + }) + } + }).catch(ignored => {}) } api('listUsers', { username: Cookies.get('username') }).then(response => { const result = response.listusersresponse.user[0] commit('SET_INFO', result) commit('SET_NAME', result.firstname + ' ' + result.lastname) + store.dispatch('SetCsLatestVersion', result.rolename) }).catch(error => { reject(error) }) + api( + 'listNetworkServiceProviders', + { name: 'SecurityGroupProvider', state: 'Enabled' } + ).then(response => { + const showSecurityGroups = response.listnetworkserviceprovidersresponse.count > 0 + commit('SET_SHOW_SECURITY_GROUPS', showSecurityGroups) + }).catch(ignored => { + }) + api('listCapabilities').then(response => { const result = response.listcapabilitiesresponse.capability commit('SET_FEATURES', result) @@ -348,6 +413,9 @@ const user = { if (result && result.customhypervisordisplayname) { commit('SET_CUSTOM_HYPERVISOR_NAME', result.customhypervisordisplayname) } + if (result && result.securitygroupsenabled) { + commit('SET_SHOW_SECURITY_GROUPS', result.securitygroupsenabled) + } }).catch(error => { reject(error) }) @@ -364,6 +432,8 @@ const user = { commit('SET_CLOUDIAN', cloudian) }).catch(ignored => { }) + }).catch(error => { + console.error(error) }) }, @@ -485,6 +555,29 @@ const user = { SetDomainStore ({ commit }, domainStore) { commit('SET_DOMAIN_STORE', domainStore) }, + SetCsLatestVersion ({ commit }, rolename) { + const lastFetchTs = store.getters.latestVersion?.fetchedTs ? store.getters.latestVersion.fetchedTs : 0 + if (rolename === 'Root Admin' && (+new Date() - lastFetchTs) > 24 * 60 * 60 * 1000) { + axios.get( + 'https://api.github.com/repos/apache/cloudstack/releases' + ).then(response => { + let latestReleaseVersion = getParsedVersion(response[0].tag_name) + let latestTag = response[0].tag_name + + for (const release of response) { + if (release.tag_name.toLowerCase().includes('rc')) { + continue + } + const parsedVersion = getParsedVersion(release.tag_name) + if (semver.gte(parsedVersion, latestReleaseVersion)) { + latestReleaseVersion = parsedVersion + latestTag = release.tag_name + commit('SET_LATEST_VERSION', { version: latestTag, fetchedTs: (+new Date()) }) + } + } + }).catch(ignored => {}) + } + }, SetDarkMode ({ commit }, darkMode) { commit('SET_DARK_MODE', darkMode) }, @@ -497,4 +590,4 @@ const user = { } } -export default user +export default user \ No newline at end of file