diff --git a/web/app.vue b/web/app.vue
index 2ddbece3b..af48a55d2 100644
--- a/web/app.vue
+++ b/web/app.vue
@@ -1,6 +1,7 @@
diff --git a/web/composables/gql/graphql.ts b/web/composables/gql/graphql.ts
index b9c36401c..0095f19f3 100644
--- a/web/composables/gql/graphql.ts
+++ b/web/composables/gql/graphql.ts
@@ -220,11 +220,11 @@ export type Case = {
export type Cloud = {
__typename?: 'Cloud';
- allowedOrigins: Array;
- apiKey: ApiKeyResponse;
- cloud: CloudResponse;
+ allowedOrigins?: Array;
+ apiKey?: ApiKeyResponse;
+ cloud?: CloudResponse;
error?: Maybe;
- minigraphql: MinigraphqlResponse;
+ minigraphql?: MinigraphqlResponse;
relay?: Maybe;
};
diff --git a/web/composables/services/keyServer.ts b/web/composables/services/keyServer.ts
index a3d68ca10..724229330 100644
--- a/web/composables/services/keyServer.ts
+++ b/web/composables/services/keyServer.ts
@@ -12,10 +12,11 @@ export interface StartTrialResponse {
license?: string;
trial?: string
}
-export const startTrial = async (payload: StartTrialPayload) => await KeyServer
+export const startTrial = async (payload: StartTrialPayload): Promise => await KeyServer
.url('/account/trial')
.formUrl(payload)
- .post();
+ .post()
+ .json();
export interface ValidateGuidResponse {
hasNewerKeyfile : boolean;
@@ -30,7 +31,7 @@ export interface ValidateGuidPayload {
guid: string;
keyfile?: string;
}
-export const validateGuid = async (payload: ValidateGuidPayload) => await KeyServer
+export const validateGuid = async (payload: ValidateGuidPayload): Promise => await KeyServer
.url('/validate/guid')
.formUrl(payload)
.post()
@@ -42,10 +43,11 @@ export interface KeyLatestPayload {
export interface KeyLatestResponse {
license: string;
}
-export const keyLatest = async (payload: KeyLatestPayload) => await KeyServer
+export const keyLatest = async (payload: KeyLatestPayload): Promise => await KeyServer
.url('/key/latest')
.formUrl(payload)
- .post();
+ .post()
+ .json();
export const getOsReleaseBySha256 = async (sha256: string): Promise => await KeyServer
.url(`/versions/sha256/${sha256}`)
diff --git a/web/composables/services/request.ts b/web/composables/services/request.ts
index 4ddf5331f..cf4e4978b 100644
--- a/web/composables/services/request.ts
+++ b/web/composables/services/request.ts
@@ -16,10 +16,22 @@ export const request = wretch()
return (
response
.error('Error', (error) => {
- errorsStore.setError(error);
+ errorsStore.setError({
+ heading: `WretchError ${error.status}`,
+ message: `${error.text} • ${error.url}`,
+ level: 'error',
+ ref: 'wretchError',
+ type: 'request',
+ });
})
.error('TypeError', (error) => {
- errorsStore.setError(error);
+ errorsStore.setError({
+ heading: `WretchTypeError ${error.status}`,
+ message: `${error.text} • ${error.url}`,
+ level: 'error',
+ ref: 'wretchTypeError',
+ type: 'request',
+ });
})
);
});
diff --git a/web/nuxt.config.ts b/web/nuxt.config.ts
index 3362bfbab..341adda6b 100644
--- a/web/nuxt.config.ts
+++ b/web/nuxt.config.ts
@@ -56,6 +56,9 @@ export default defineNuxtConfig({
{ path: '~/components/UserProfile', prefix: 'Upc' },
'~/components',
],
+ // typescript: {
+ // typeCheck: true
+ // },
vite: {
build: {
minify: 'terser',
@@ -71,6 +74,7 @@ export default defineNuxtConfig({
},
customElements: {
entries: [
+ // @ts-ignore
{
name: 'UnraidComponents',
tags: [
diff --git a/web/pages/index.vue b/web/pages/index.vue
index 55d4d7e77..7eb420360 100644
--- a/web/pages/index.vue
+++ b/web/pages/index.vue
@@ -6,10 +6,11 @@ import { serverState } from '~/_data/serverState';
const nuxtApp = useNuxtApp();
onBeforeMount(() => {
+ // @ts-ignore
nuxtApp.$customElements.registerEntry('UnraidComponents');
});
-const valueToMakeCallback = ref('');
+const valueToMakeCallback = ref();
const callbackDestination = ref('');
const createCallbackUrl = (payload: SendPayloads, sendType: string) => { // params differs from callbackActions.send
diff --git a/web/pages/webComponents.vue b/web/pages/webComponents.vue
index a2c63c327..ce08eac3a 100644
--- a/web/pages/webComponents.vue
+++ b/web/pages/webComponents.vue
@@ -3,6 +3,7 @@ import { serverState } from '~/_data/serverState';
const nuxtApp = useNuxtApp();
onBeforeMount(() => {
+ // @ts-ignore
nuxtApp.$customElements.registerEntry('UnraidComponents');
});
diff --git a/web/store/account.ts b/web/store/account.ts
index 8e89e2d5e..3d3b0d9d5 100644
--- a/web/store/account.ts
+++ b/web/store/account.ts
@@ -147,7 +147,7 @@ export const useAccountStore = defineStore('account', () => {
(connectSignInPayload.value && (!connectSignInPayload.value.apiKey || !connectSignInPayload.value.email || !connectSignInPayload.value.preferred_username))
) {
accountActionStatus.value = 'failed';
- return;
+ return console.error('[connectSignInMutation] incorrect payload', connectSignInPayload.value);
}
accountActionStatus.value = 'updating';
@@ -197,11 +197,11 @@ export const useAccountStore = defineStore('account', () => {
const connectSignOutMutation = async () => {
accountActionStatus.value = 'updating';
// @todo is this still needed here with the change to a mutation?
- if (!serverStore.registered && accountAction.value && !accountAction.value.user) {
- accountActionHide.value = true;
- accountActionStatus.value = 'success';
- return;
- }
+ // if (!serverStore.registered && accountAction.value && !accountAction.value?.user) {
+ // accountActionHide.value = true;
+ // accountActionStatus.value = 'success';
+ // return;
+ // }
const { mutate: signOutMutation, onDone, onError } = await useMutation(CONNECT_SIGN_OUT);
diff --git a/web/store/callbackActions.ts b/web/store/callbackActions.ts
index 611d1ced1..07d3a0462 100644
--- a/web/store/callbackActions.ts
+++ b/web/store/callbackActions.ts
@@ -5,7 +5,15 @@ import { useAccountStore } from '~/store/account';
import { useInstallKeyStore } from '~/store/installKey';
import { useServerStore } from '~/store/server';
import { useUpdateOsStore, useUpdateOsActionsStore } from '~/store/updateOsActions';
-import { useCallbackStoreGeneric, type CallbackActionsStore, type ExternalKeyActions, type QueryPayloads } from '~/store/callback';
+import {
+ useCallbackStoreGeneric,
+ type CallbackActionsStore,
+ type ExternalKeyActions,
+ type ExternalSignIn,
+ type ExternalSignOut,
+ type ExternalUpdateOsAction,
+ type QueryPayloads,
+} from '~/store/callback';
export const useCallbackActionsStore = defineStore('callbackActions', () => {
const accountStore = useAccountStore();
@@ -35,6 +43,16 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => {
redirectToCallbackType?.();
};
+ const actionTypesWithKey = [
+ 'recover',
+ 'replace',
+ 'trialExtend',
+ 'trialStart',
+ 'purchase',
+ 'redeem',
+ 'renew',
+ 'upgrade',
+ ];
const redirectToCallbackType = () => {
console.debug('[redirectToCallbackType]');
if (!callbackData.value || !callbackData.value.type || callbackData.value.type !== 'forUpc' || !callbackData.value.actions?.length) {
@@ -49,33 +67,28 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => {
callbackData.value.actions.forEach(async (action, index, array) => {
console.debug('[redirectToCallbackType]', { action, index, array });
- if (action?.keyUrl) {
+ if (actionTypesWithKey.includes(action.type)) {
await installKeyStore.install(action as ExternalKeyActions);
}
- if (action?.user || action.type === 'signIn') {
- accountStore.setAccountAction(action);
- accountStore.setConnectSignInPayload({
- apiKey: action.apiKey,
- email: action.user.email,
- preferred_username: action.user.preferred_username,
+
+ if (action.type === 'signIn' && action?.user) {
+ accountStore.setAccountAction(action as ExternalSignIn);
+ await accountStore.setConnectSignInPayload({
+ apiKey: action?.apiKey ?? '',
+ email: action.user?.email ?? '',
+ preferred_username: action.user?.preferred_username ?? '',
});
}
+
if (action.type === 'signOut' || action.type === 'oemSignOut') {
- accountStore.setAccountAction(action);
- accountStore.setQueueConnectSignOut(true);
+ accountStore.setAccountAction(action as ExternalSignOut);
+ await accountStore.setQueueConnectSignOut(true);
}
- if (action.type === 'updateOs' && action?.sha256) {
- console.debug('[redirectToCallbackType] updateOs', action);
- const foundRelease = await updateOsActionsStore.getReleaseFromKeyServer(action.sha256);
- console.debug('[redirectToCallbackType] updateOs foundRelease', foundRelease);
- if (!foundRelease) {
- throw new Error('Release not found');
- }
- if (foundRelease.version === serverStore.osVersion) {
- throw new Error('Release version is the same as the server\'s current version');
- }
- updateOsActionsStore.confirmUpdateOs(foundRelease);
+ if (action.type === 'updateOs') {
+ updateOsActionsStore.setUpdateOsAction(action as ExternalUpdateOsAction);
+ await updateOsActionsStore.actOnUpdateOsAction();
+
if (array.length === 1) { // only 1 action, skip refresh server state
console.debug('[redirectToCallbackType] updateOs done');
// removing query string relase is set so users can't refresh the page and go through the same actions
diff --git a/web/store/errors.ts b/web/store/errors.ts
index 06d8f782f..38976f238 100644
--- a/web/store/errors.ts
+++ b/web/store/errors.ts
@@ -11,7 +11,7 @@ import type { Server } from '~/types/server';
*/
setActivePinia(createPinia());
-export type ErrorType = 'account' | 'callback' | 'installKey' | 'server' | 'serverState' | 'unraidApiGQL' | 'unraidApiState';
+export type ErrorType = 'account' | 'callback' | 'installKey' | 'request' | 'server' | 'serverState' | 'unraidApiGQL' | 'unraidApiState';
export interface Error {
actions?: ButtonProps[];
debugServer?: Server;
@@ -107,8 +107,14 @@ export const useErrorsStore = defineStore('errors', () => {
await new Promise(resolve => setTimeout(resolve, 100));
$panels = $modal.querySelectorAll('.allpanels');
}
- $panels.forEach(($panel: HTMLDivElement) => {
- if ($panel.id === 'troubleshoot_panel') { $panel.style.display = 'block'; } else { $panel.style.display = 'none'; }
+ $panels.forEach(($panel: Element) => {
+ if ($panel.id === 'troubleshoot_panel') {
+ // @ts-ignore
+ $panel.style.display = 'block';
+ } else {
+ // @ts-ignore
+ $panel.style.display = 'none';
+ }
});
} catch (error) {
console.error('[openTroubleshoot]', error);
diff --git a/web/store/installKey.ts b/web/store/installKey.ts
index 6d738e5af..8c2e16500 100644
--- a/web/store/installKey.ts
+++ b/web/store/installKey.ts
@@ -55,12 +55,17 @@ export const useInstallKeyStore = defineStore('installKey', () => {
}
} catch (error) {
console.error('[install] WebguiInstallKey error', error);
+ let errorMessage = 'Unknown error';
+ if (typeof error === "string") {
+ errorMessage = error.toUpperCase();
+ } else if (error instanceof Error) {
+ errorMessage = error.message;
+ }
keyInstallStatus.value = 'failed';
errorsStore.setError({
heading: 'Failed to install key',
- message: error.message,
+ message: errorMessage,
level: 'error',
-
ref: 'installKey',
type: 'installKey',
});
diff --git a/web/store/replaceRenew.ts b/web/store/replaceRenew.ts
index 9b493099a..e104cd058 100644
--- a/web/store/replaceRenew.ts
+++ b/web/store/replaceRenew.ts
@@ -148,7 +148,7 @@ export const useReplaceRenewStore = defineStore('replaceRenewCheck', () => {
const keyLatestResponse: KeyLatestResponse = await keyLatest({
keyfile: keyfile.value,
- }).json();
+ });
if (keyLatestResponse?.license) {
callbackStore.send(
diff --git a/web/store/server.ts b/web/store/server.ts
index a926ffaea..6fae4ff99 100644
--- a/web/store/server.ts
+++ b/web/store/server.ts
@@ -15,7 +15,6 @@ import {
import { useQuery } from '@vue/apollo-composable';
import { SERVER_STATE_QUERY } from './server.fragment';
-import type { serverStateQuery } from '~/composables/gql/graphql';
import { WebguiState } from '~/composables/services/webgui';
import { WEBGUI_SETTINGS_MANAGMENT_ACCESS } from '~/helpers/urls';
import { useAccountStore } from '~/store/account';
@@ -24,19 +23,19 @@ import { usePurchaseStore } from '~/store/purchase';
import { useThemeStore, type Theme } from '~/store/theme';
import { useUnraidApiStore } from '~/store/unraidApi';
+import type { Cloud, Config, serverStateQuery } from '~/composables/gql/graphql';
import type {
Server,
ServerAccountCallbackSendPayload,
ServerKeyTypeForPurchase,
ServerPurchaseCallbackSendPayload,
ServerState,
- ServerStateCloudStatus,
- ServerStateConfigStatus,
ServerStateData,
ServerStateDataAction,
ServerconnectPluginInstalled,
ServerDateTimeFormat,
ServerStateDataKeyActions,
+ ServerOsVersionBranch,
} from '~/types/server';
/**
@@ -65,8 +64,8 @@ export const useServerStore = defineStore('server', () => {
});
const apiVersion = ref('');
const avatar = ref(''); // @todo potentially move to a user store
- const cloud = ref();
- const config = ref();
+ const cloud = ref();
+ const config = ref();
const connectPluginInstalled = ref('');
const connectPluginVersion = ref('');
const csrf = ref(''); // required to make requests to Unraid webgui
@@ -89,7 +88,7 @@ export const useServerStore = defineStore('server', () => {
const locale = ref('');
const name = ref('');
const osVersion = ref('');
- const osVersionBranch = ref<'stable' | 'next' | 'preview' | 'test'>('stable');
+ const osVersionBranch = ref('stable');
const registered = ref();
const regDev = ref(0);
const regGen = ref(0);
@@ -238,7 +237,7 @@ export const useServerStore = defineStore('server', () => {
const serverDebugPayload = computed((): Server => {
const payload = {
- apiKey: apiKey.value ? `${apiKey.value.substring(0, 6)}__[REDACTED]` : '', // so we don't send full api key in email
+ apiKey: apiKey.value && typeof apiKey.value === 'string' ? `${apiKey.value.substring(0, 6)}__[REDACTED]` : '', // so we don't send full api key in email
apiVersion: apiVersion.value,
avatar: avatar.value,
connectPluginInstalled: connectPluginInstalled.value,
@@ -782,12 +781,13 @@ export const useServerStore = defineStore('server', () => {
};
const mutateServerStateFromApi = (data: serverStateQuery): Server => {
+ console.debug('mutateServerStateFromApi', data);
const mutatedData = {
// if we get an owners obj back and the username is root we don't want to overwrite the values
...(data.owner && data.owner.username !== 'root'
? {
// avatar: data.owner.avatar,
- username: data.owner.username,
+ username: data.owner.username ?? '',
registered: true,
}
: { // handles sign outs
@@ -796,19 +796,22 @@ export const useServerStore = defineStore('server', () => {
registered: false,
}
),
- name: (data.info && data.info.os) ? data.info.os.hostname : null,
- keyfile: (data.registration && data.registration.keyFile) ? data.registration.keyFile.contents : null,
- regGen: data.vars ? data.vars.regGen : null,
- state: data.vars ? data.vars.regState : null,
+ name: (data.info && data.info.os && data.info.os.hostname) ? data.info.os.hostname : undefined,
+ keyfile: (data.registration && data.registration.keyFile && data.registration.keyFile.contents) ? data.registration.keyFile.contents : undefined,
+ regGen: data.vars && data.vars.regGen ? parseInt(data.vars.regGen) : undefined,
+ state: data.vars && data.vars.regState? data.vars.regState : undefined,
config: data.config
? data.config
: {
- error: data.vars ? data.vars.configError : null,
- valid: data.vars ? data.vars.configValid : true,
+ error: data.vars && data.vars.configError ? data.vars.configError : undefined,
+ valid: data.vars && data.vars.configValid ? data.vars.configValid : true,
},
- expireTime: (data.registration && data.registration.expiration) ? data.registration.expiration : 0,
- ...(data.cloud && { cloud: data.cloud }),
+ expireTime: (data.registration && data.registration.expiration) ? parseInt(data.registration.expiration) : 0,
+ cloud: {
+ ...(data.cloud ?? {}),
+ },
};
+ console.debug('mutatedData', mutatedData);
return mutatedData;
};
@@ -883,13 +886,13 @@ export const useServerStore = defineStore('server', () => {
}, refreshTimeout);
};
- const filteredKeyActions = (filterType: 'by' | 'out', filters: ServerStateDataKeyActions[]): ServerStateDataAction[] | undefined => {
+ const filteredKeyActions = (filterType: 'by' | 'out', filters: string|ServerStateDataKeyActions[]): ServerStateDataAction[] | undefined => {
if (!stateData.value.actions) { return; }
return stateData.value.actions.filter((action) => {
return filterType === 'out'
- ? !filters.includes(action.name)
- : filters.includes(action.name);
+ ? !filters.includes(action.name as ServerStateDataKeyActions)
+ : filters.includes(action.name as ServerStateDataKeyActions);
});
};
diff --git a/web/store/trial.ts b/web/store/trial.ts
index 8aa0e43c2..3d1186630 100644
--- a/web/store/trial.ts
+++ b/web/store/trial.ts
@@ -31,7 +31,7 @@ export const useTrialStore = defineStore('trial', () => {
guid: serverStore.guid,
timestamp: Math.floor(Date.now() / 1000),
};
- const response: StartTrialResponse = await startTrial(payload).json();
+ const response: StartTrialResponse = await startTrial(payload);
if (!response.license) {
trialStatus.value = 'failed';
return console.error('[requestTrial]', 'No license returned', response);
@@ -48,7 +48,7 @@ export const useTrialStore = defineStore('trial', () => {
type: 'forUpc',
};
trialStatus.value = 'success';
- return callbackActionsStore.redirectToCallbackType(trialStartData);
+ return callbackActionsStore.saveCallbackData(trialStartData);
} catch (error) {
trialStatus.value = 'failed';
console.error('[requestTrial]', error);
diff --git a/web/store/unraidApi.ts b/web/store/unraidApi.ts
index 5dad258ec..6d949f409 100644
--- a/web/store/unraidApi.ts
+++ b/web/store/unraidApi.ts
@@ -1,3 +1,4 @@
+// @ts-ignore
import { from, ApolloClient, createHttpLink, InMemoryCache, split } from '@apollo/client/core/core.cjs';
import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';
@@ -81,12 +82,9 @@ export const useUnraidApiStore = defineStore('unraidApi', () => {
}),
);
- /**
- * @todo integrate errorsStore errorsStore.setError(error);
- */
- const errorLink = onError(({ graphQLErrors, networkError }) => {
+ const errorLink = onError(({ graphQLErrors, networkError }: any) => {
if (graphQLErrors) {
- graphQLErrors.map((error) => {
+ graphQLErrors.map((error: any) => {
console.error('[GraphQL error]', error);
const errorMsg = error.error && error.error.message ? error.error.message : error.message;
if (errorMsg && errorMsg.includes('offline')) {
@@ -140,9 +138,13 @@ export const useUnraidApiStore = defineStore('unraidApi', () => {
},
});
+ interface Definintion {
+ kind: string;
+ operation?: string;
+ };
const splitLinks = split(
- ({ query }) => {
- const definition = getMainDefinition(query);
+ ({ query }: any) => {
+ const definition: Definintion = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
@@ -189,21 +191,31 @@ export const useUnraidApiStore = defineStore('unraidApi', () => {
*/
const restartUnraidApiClient = async () => {
const command = unraidApiStatus.value === 'offline' ? 'start' : 'restart';
- console.debug('[restartUnraidApiClient]', { command });
unraidApiStatus.value = 'restarting';
try {
const response = await WebguiUnraidApiCommand({
csrf_token: serverStore.csrf,
command,
});
- console.debug('[restartUnraidApiClient] response', response);
return setTimeout(() => {
if (unraidApiClient.value) {
createApolloClient();
}
}, 5000);
} catch (error) {
- errorsStore.setError(error);
+ let errorMessage = 'Unknown error';
+ if (typeof error === "string") {
+ errorMessage = error.toUpperCase();
+ } else if (error instanceof Error) {
+ errorMessage = error.message;
+ }
+ errorsStore.setError({
+ heading: 'Error: unraid-api restart',
+ message: errorMessage,
+ level: 'error',
+ ref: 'restartUnraidApiClient',
+ type: 'request',
+ });
}
};
diff --git a/web/store/updateOs.ts b/web/store/updateOs.ts
index c1a1e3d87..3a919a5bb 100644
--- a/web/store/updateOs.ts
+++ b/web/store/updateOs.ts
@@ -108,21 +108,21 @@ extend(relativeTime);
export const RELEASES_LOCAL_STORAGE_KEY = 'unraidReleasesResponse';
-export const useUpdateOsStoreGeneric = (payload: UpdateOsStorePayload) =>
+export const useUpdateOsStoreGeneric = (payload?: UpdateOsStorePayload) =>
defineStore('updateOs', () => {
console.debug('[updateOs] payload', payload);
// Since this file is shared between account.unraid.net and the web components, we need to handle the state differently
// If useUpdateOsActions is passed in, we're in the webgui web components
- const updateOsActions = payload.useUpdateOsActions !== undefined ? payload.useUpdateOsActions() : undefined;
+ const updateOsActions = payload?.useUpdateOsActions !== undefined ? payload.useUpdateOsActions() : undefined;
console.debug('[updateOs] updateOsActions', updateOsActions);
// If useUpdateOsActions is not passed in, we're in account.unraid.net
// creating refs from the passed in values so that we can use them in the computed properties
- const paramCurrentOsVersion = ref(payload.currentOsVersion ?? '');
- const paramCurrentOsVersionBranch = ref(payload.currentOsVersionBranch ?? '');
- const paramCurrentRegExp = ref(payload.currentRegExp ?? 0);
- const paramCurrentRegUpdatesExpired = ref(payload.currentRegUpdatesExpired ?? false);
- const paramCurrentIsLoggedIn = ref(payload.currentIsLoggedIn ?? false);
- const paramCurrentAuthUserAttributes = ref(payload.currentAuthUserAttributes ?? {});
+ const paramCurrentOsVersion = ref(payload?.currentOsVersion ?? '');
+ const paramCurrentOsVersionBranch = ref(payload?.currentOsVersionBranch ?? '');
+ const paramCurrentRegExp = ref(payload?.currentRegExp ?? 0);
+ const paramCurrentRegUpdatesExpired = ref(payload?.currentRegUpdatesExpired ?? false);
+ const paramCurrentIsLoggedIn = ref(payload?.currentIsLoggedIn ?? false);
+ const paramCurrentAuthUserAttributes = ref(payload?.currentAuthUserAttributes ?? {});
// getters – when set from updateOsActions we're in the webgui web components otherwise we're in account.unraid.net
const osVersion = computed(() => updateOsActions?.osVersion ?? paramCurrentOsVersion.value ?? '');
const osVersionBranch = computed(() => updateOsActions?.osVersionBranch ?? paramCurrentOsVersionBranch.value ?? '');
diff --git a/web/store/updateOsActions.ts b/web/store/updateOsActions.ts
index 4bf7abaf6..dc76fa12f 100644
--- a/web/store/updateOsActions.ts
+++ b/web/store/updateOsActions.ts
@@ -15,6 +15,7 @@ import {
type UpdateOsActionStore,
} from '~/store/updateOs';
+import type { ExternalUpdateOsAction } from '~/store/callback';
import type { UserProfileLink } from '~/types/userProfile';
/**
@@ -33,6 +34,7 @@ export const useUpdateOsActionsStore = defineStore('updateOsActions', () => {
const { install: installPlugin } = useInstallPlugin();
// State
+ const updateAction = ref();
const osVersion = computed(() => serverStore.osVersion);
const osVersionBranch = computed(() => serverStore.osVersionBranch);
const regExp = computed(() => serverStore.regExp);
@@ -121,11 +123,15 @@ export const useUpdateOsActionsStore = defineStore('updateOsActions', () => {
);
};
+ const setUpdateOsAction = (payload: ExternalUpdateOsAction | undefined) => (updateAction.value = payload);
/**
* @description When receiving the callback the Account update page we'll use the provided sha256 of the release to get the release from the keyserver
*/
const getReleaseFromKeyServer = async (sha256: string) => {
console.debug('[getReleaseFromKeyServer]', sha256);
+ if (!sha256) {
+ throw new Error('No sha256 provided');
+ }
try {
const response = await getOsReleaseBySha256(sha256);
console.debug('[getReleaseFromKeyServer]', response);
@@ -141,6 +147,18 @@ export const useUpdateOsActionsStore = defineStore('updateOsActions', () => {
setStatus('confirming');
};
+ const actOnUpdateOsAction = async () => {
+ const foundRelease = await getReleaseFromKeyServer(updateAction.value?.sha256 ?? '');
+ console.debug('[redirectToCallbackType] updateOs foundRelease', foundRelease);
+ if (!foundRelease) {
+ throw new Error('Release not found');
+ }
+ if (foundRelease.version === serverStore.osVersion) {
+ throw new Error('Release version is the same as the server\'s current version');
+ }
+ confirmUpdateOs(foundRelease);
+ };
+
const installOsUpdate = () => {
if (!callbackUpdateRelease.value) {
return console.error('[installOsUpdate] release not found');
@@ -195,6 +213,7 @@ export const useUpdateOsActionsStore = defineStore('updateOsActions', () => {
ineligibleText,
toolsRegistrationAction,
// Actions
+ actOnUpdateOsAction,
confirmUpdateOs,
installOsUpdate,
initUpdateOsCallback,
@@ -202,6 +221,7 @@ export const useUpdateOsActionsStore = defineStore('updateOsActions', () => {
rebootServer,
setStatus,
setRebootType,
+ setUpdateOsAction,
viewCurrentReleaseNotes,
getReleaseFromKeyServer,
};
diff --git a/web/types/server.ts b/web/types/server.ts
index 4a592fa31..ab3829a39 100644
--- a/web/types/server.ts
+++ b/web/types/server.ts
@@ -1,14 +1,7 @@
+import type { Cloud, Config } from '~/composables/gql/graphql';
import type { Theme } from '~/store/theme';
import type { UserProfileLink } from '~/types/userProfile';
-export interface ServerStateConfigStatus {
- error?: 'INVALID' | 'NO_KEY_SERVER' | 'UNKNOWN_ERROR' | 'WITHDRAWN';
- valid: boolean;
-}
-export interface ServerStateCloudStatus {
- error: string | undefined;
-}
-
export type ServerState = 'BASIC'
| 'PLUS'
| 'PRO'
@@ -37,13 +30,15 @@ export type ServerState = 'BASIC'
| 'LIFETIME'
| undefined;
+export type ServerOsVersionBranch = 'stable' | 'next' | 'preview' | 'test';
+
export type ServerconnectPluginInstalled = 'dynamix.unraid.net.plg' | 'dynamix.unraid.net.staging.plg' | 'dynamix.unraid.net.plg_installFailed' | 'dynamix.unraid.net.staging.plg_installFailed' | '';
export interface Server {
apiKey?: string;
apiVersion?: string;
avatar?: string;
- cloud?: ServerStateCloudStatus;
- config?: ServerStateConfigStatus | undefined;
+ cloud?: Cloud | undefined;
+ config?: Config | undefined;
connectPluginInstalled?: ServerconnectPluginInstalled;
connectPluginVersion?: string;
csrf?: string;
@@ -62,6 +57,7 @@ export interface Server {
locale?: string;
name?: string;
osVersion?: string;
+ osVersionBranch?: ServerOsVersionBranch;
registered?: boolean;
regDev?: number;
regGen?: number;
@@ -95,10 +91,12 @@ export interface ServerAccountCallbackSendPayload {
locale?: string;
name?: string;
osVersion?: string;
+ osVersionBranch?: ServerOsVersionBranch;
registered: boolean;
+ regExp?: number;
regGen?: number;
regGuid?: string;
- regExp?: number;
+ regTy?: string;
regUpdatesExpired?: boolean;
site?: string;
state: ServerState;
@@ -117,6 +115,7 @@ export interface ServerPurchaseCallbackSendPayload {
keyTypeForPurchase: ServerKeyTypeForPurchase;
locale: string;
osVersion?: string;
+ osVersionBranch?: ServerOsVersionBranch;
registered: boolean;
regExp?: number;
regUpdatesExpired?: boolean;