-
-
- Introducing Unraid Connect
-
-
-
- Enhance your Unraid experience
-
-
+
+
+
-
-
+
+
+
-
+
+
@@ -115,7 +115,7 @@ const installButtonClasses = 'text-white text-14px text-center w-full flex flex-
-
+
diff --git a/components/UserProfile/PromoFeature.vue b/components/UserProfile/PromoFeature.vue
index 188040b27..23b19f9a9 100644
--- a/components/UserProfile/PromoFeature.vue
+++ b/components/UserProfile/PromoFeature.vue
@@ -20,14 +20,14 @@ defineProps
();
-
\ No newline at end of file
diff --git a/store/account.ts b/store/account.ts
index 15033e8ee..33729081d 100644
--- a/store/account.ts
+++ b/store/account.ts
@@ -18,6 +18,8 @@ export const useAccountStore = defineStore('account', () => {
const accountAction = ref();
const accountActionStatus = ref<'failed' | 'ready' | 'success' | 'updating'>('ready');
+ const username = ref('');
+
// Actions
const recover = () => {
console.debug('[accountStore.recover]');
@@ -70,17 +72,20 @@ export const useAccountStore = defineStore('account', () => {
*/
const updatePluginConfig = async (action: ExternalSignIn | ExternalSignOut) => {
console.debug('[accountStore.updatePluginConfig]', action);
+ // save any existing username before updating
+ if (serverStore.username) username.value = serverStore.username;
+
accountAction.value = action;
accountActionStatus.value = 'updating';
const userPayload = {
- ...(action.user
+ ...(accountAction.value.user
? {
- apikey: action.apiKey,
+ apikey: accountAction.value.apiKey,
// avatar: '',
- email: action.user?.email,
+ email: accountAction.value.user?.email,
regWizTime: `${Date.now()}_${serverStore.guid}`, // set when signing in the first time and never unset for the sake of displaying Sign In/Up in the UPC without needing to validate guid every time
- username: action.user?.preferred_username,
+ username: accountAction.value.user?.preferred_username,
}
: {
accesstoken: '',
@@ -126,20 +131,20 @@ export const useAccountStore = defineStore('account', () => {
case 'updating':
return {
text: accountAction.value?.type === 'signIn'
- ? 'Signing in...'
- : 'Signing out...',
+ ? `Signing in ${accountAction.value.user?.preferred_username}...`
+ : `Signing out ${username.value}...`,
};
case 'success':
return {
text: accountAction.value?.type === 'signIn'
- ? 'Signed in successfully'
- : 'Signed out successfully',
+ ? `Signed ${accountAction.value.user?.preferred_username} In Successfully`
+ : `Signed Out ${username.value} Successfully`,
};
case 'failed':
return {
text: accountAction.value?.type === 'signIn'
- ? 'Sign in failed'
- : 'Sign out failed',
+ ? 'Sign In Failed'
+ : 'Sign Out Failed',
};
}
});
diff --git a/store/callback.ts b/store/callback.ts
index 875fd765e..718053084 100644
--- a/store/callback.ts
+++ b/store/callback.ts
@@ -1,9 +1,32 @@
import AES from 'crypto-js/aes';
import Utf8 from 'crypto-js/enc-utf8';
-import { ref } from 'vue';
import { defineStore, createPinia, setActivePinia } from 'pinia';
-export interface ServerAccountCallbackServerData {
+/**
+ * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
+ * @see https://github.com/vuejs/pinia/discussions/1085
+ */
+setActivePinia(createPinia());
+
+export type SignIn = 'signIn';
+export type SignOut = 'signOut';
+export type OemSignOut = 'oemSignOut';
+export type Troubleshoot = 'troubleshoot';
+export type Recover = 'recover';
+export type Replace = 'replace';
+export type TrialExtend = 'trialExtend';
+export type TrialStart = 'trialStart';
+export type Purchase = 'purchase';
+export type Redeem = 'redeem';
+export type Upgrade = 'upgrade';
+
+export type AccountAction = SignIn | SignOut | OemSignOut | Troubleshoot;
+export type AccountKeyAction = Recover | Replace | TrialExtend | TrialStart;
+export type PurchaseAction = Purchase | Redeem | Upgrade;
+
+export type ServerAction = AccountAction | AccountKeyAction | PurchaseAction;
+
+export interface ServerData {
description?: string;
deviceCount?: number;
expireTime?: number;
@@ -20,26 +43,9 @@ export interface ServerAccountCallbackServerData {
wanFQDN?: string;
}
-export type SignIn = 'signIn';
-export type SignOut = 'signOut';
-export type Troubleshoot = 'troubleshoot';
-export type Recover = 'recover';
-export type Replace = 'replace';
-export type TrialExtend = 'trialExtend';
-export type TrialStart = 'trialStart';
-export type Purchase = 'purchase';
-export type Redeem = 'redeem';
-export type Upgrade = 'upgrade';
-
-export type AccountAction = SignIn | SignOut | Troubleshoot;
-export type AccountKeyAction = Recover | Replace | TrialExtend | TrialStart;
-export type PurchaseAction = Purchase | Redeem | Upgrade;
-
-export type ServerStateDataActionType = AccountAction | AccountKeyAction | PurchaseAction;
-
export interface ServerPayload {
- server: ServerAccountCallbackServerData;
- type: ServerStateDataActionType;
+ server: ServerData;
+ type: ServerAction;
}
export interface ExternalSignIn {
@@ -48,7 +54,7 @@ export interface ExternalSignIn {
user: UserInfo;
}
export interface ExternalSignOut {
- type: SignOut;
+ type: SignOut | OemSignOut;
}
export interface ExternalKeyActions {
type: PurchaseAction | AccountKeyAction;
@@ -92,12 +98,6 @@ interface CallbackActionsStore {
sendType: 'fromUpc' | 'forUpc';
}
-/**
- * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
- * @see https://github.com/vuejs/pinia/discussions/1085
- */
-setActivePinia(createPinia());
-
export const useCallbackStoreGeneric = (
useCallbackActions: () => CallbackActionsStore,
) =>
@@ -105,10 +105,7 @@ export const useCallbackStoreGeneric = (
const callbackActions = useCallbackActions();
const encryptionKey = 'Uyv2o8e*FiQe8VeLekTqyX6Z*8XonB';
const sendType = 'fromUpc';
- // state
- const encryptedMessage = ref(null);
- // actions
const send = (url: string, payload: SendPayloads) => {
console.debug('[callback.send]');
const stringifiedData = JSON.stringify({
@@ -118,11 +115,11 @@ export const useCallbackStoreGeneric = (
sender: window.location.href,
type: sendType,
});
- encryptedMessage.value = AES.encrypt(stringifiedData, encryptionKey).toString();
+ const encryptedMessage = AES.encrypt(stringifiedData, encryptionKey).toString();
// build and go to url
const destinationUrl = new URL(url);
- destinationUrl.searchParams.set('data', encodeURI(encryptedMessage.value));
- console.debug('[callback.send]', encryptedMessage.value, destinationUrl);
+ destinationUrl.searchParams.set('data', encodeURI(encryptedMessage));
+ console.debug('[callback.send]', encryptedMessage, destinationUrl);
window.location.href = destinationUrl.toString();
return;
};
@@ -144,7 +141,6 @@ export const useCallbackStoreGeneric = (
};
return {
- // actions
send,
watcher,
};
diff --git a/store/callbackActions.ts b/store/callbackActions.ts
index e70d8a32d..f70675c7f 100644
--- a/store/callbackActions.ts
+++ b/store/callbackActions.ts
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
import { useAccountStore } from './account';
import { useInstallKeyStore } from './installKey';
-import { useCallbackStoreGeneric, type ExternalPayload, type ExternalActions, type ExternalKeyActions, type QueryPayloads } from './callback';
+import { useCallbackStoreGeneric, type ExternalPayload, type ExternalKeyActions, type QueryPayloads } from './callback';
// import { useServerStore } from './server';
export const useCallbackActionsStore = defineStore(
@@ -11,7 +11,7 @@ export const useCallbackActionsStore = defineStore(
const accountStore = useAccountStore();
const installKeyStore = useInstallKeyStore();
// const serverStore = useServerStore();
- type CallbackStatus = 'error' | 'loading' | 'ready' | 'done';
+ type CallbackStatus = 'error' | 'loading' | 'ready' | 'success';
const callbackStatus = ref('ready');
const callbackData = ref();
@@ -38,22 +38,21 @@ export const useCallbackActionsStore = defineStore(
if (action?.keyUrl) {
await installKeyStore.install(action as ExternalKeyActions);
}
- /** @todo add oemSignOut */
- if (action?.user || action.type === 'signOut') {
+ if (action?.user || action.type === 'signOut' || action.type === 'oemSignOut') {
await accountStore.updatePluginConfig(action);
}
// all actions have run
if (array.length === (index + 1)) {
- callbackStatus.value = 'done';
- // if (array.length > 1) {
- // // if we have more than 1 action it means there was a key install and an account action so both need to be successful
- // const allSuccess = accountStore.accountActionStatus === 'success' && installKeyStore.keyInstallStatus === 'success';
- // callbackStatus.value = allSuccess ? 'success' : 'error';
- // } else {
- // // only 1 action needs to be successful
- // const oneSuccess = accountStore.accountActionStatus === 'success' || installKeyStore.keyInstallStatus === 'success';
- // callbackStatus.value = oneSuccess ? 'success' : 'error';
- // }
+ // callbackStatus.value = 'done';
+ if (array.length > 1) {
+ // if we have more than 1 action it means there was a key install and an account action so both need to be successful
+ const allSuccess = accountStore.accountActionStatus === 'success' && installKeyStore.keyInstallStatus === 'success';
+ callbackStatus.value = allSuccess ? 'success' : 'error';
+ } else {
+ // only 1 action needs to be successful
+ const oneSuccess = accountStore.accountActionStatus === 'success' || installKeyStore.keyInstallStatus === 'success';
+ callbackStatus.value = oneSuccess ? 'success' : 'error';
+ }
}
});
};
@@ -83,6 +82,10 @@ export const useCallbackActionsStore = defineStore(
}
});
+ watch(callbackData, () => {
+ console.debug('[callbackData] watch', callbackData.value);
+ });
+
return {
redirectToCallbackType,
callbackData,
diff --git a/store/installKey.ts b/store/installKey.ts
index 815383bc3..34b4c3bb3 100644
--- a/store/installKey.ts
+++ b/store/installKey.ts
@@ -97,6 +97,7 @@ export const useInstallKeyStore = defineStore('installKey', () => {
// State
keyInstallStatus,
// getters
+ keyActionType,
keyInstallStatusCopy,
keyType,
keyUrl,
diff --git a/store/promo.ts b/store/promo.ts
index a099edd3b..35a685d41 100644
--- a/store/promo.ts
+++ b/store/promo.ts
@@ -1,6 +1,8 @@
import { useToggle } from '@vueuse/core';
import { defineStore, createPinia, setActivePinia } from 'pinia';
+import { useDropdownStore } from '~/store/dropdown';
+
/**
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
* @see https://github.com/vuejs/pinia/discussions/1085
@@ -8,17 +10,33 @@ import { defineStore, createPinia, setActivePinia } from 'pinia';
setActivePinia(createPinia());
export const usePromoStore = defineStore('promo', () => {
- const promoVisible = ref(false);
+ const dropdownStore = useDropdownStore();
+ const promoVisible = ref(false);
+
+ const openOnNextLoad = () => sessionStorage.setItem('unraidConnectPromo', 'show');
const promoHide = () => promoVisible.value = false;
const promoShow = () => promoVisible.value = true;
const promoToggle = useToggle(promoVisible);
+
watch(promoVisible, (newVal, _oldVal) => {
console.debug('[promoVisible]', newVal, _oldVal);
+ if (newVal) { // close the dropdown when the promo is opened
+ dropdownStore.dropdownHide();
+ }
+ });
+
+ onBeforeMount(() => {
+ if (sessionStorage.getItem('unraidConnectPromo') === 'show') {
+ sessionStorage.removeItem('unraidConnectPromo');
+ promoShow();
+ }
});
return {
promoVisible,
+
+ openOnNextLoad,
promoHide,
promoShow,
promoToggle,
diff --git a/types/callback.ts b/types/callback.ts
deleted file mode 100644
index 931a7ec1a..000000000
--- a/types/callback.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { CognitoUser, ChallengeName } from 'amazon-cognito-identity-js';
-import type {
- ServerAccountCallbackSendPayload,
- ServerPurchaseCallbackSendPayload,
- ServerStateDataActionType,
-} from '~/types/server';
-
-/**
- * These user interfaces are mimiced from the Auth repo
- */
-export interface UserInfo {
- 'custom:ips_id'?: string;
- email?: string;
- email_verifed?: 'true' | 'false';
- preferred_username?: string;
- sub?: string;
- username?: string;
-}
-export interface CallbackSendPayload {
- server: ServerAccountCallbackSendPayload|ServerPurchaseCallbackSendPayload;
- type: ServerStateDataActionType;
-}
-
-export interface CallbackAction {
- apiKey?: string;
- keyUrl?: string;
- type: ServerStateDataActionType;
- user?: UserInfo;
-}
-
-export interface CallbackReceivePayload {
- actions: CallbackAction[];
- sender: string;
-}
\ No newline at end of file