mirror of
https://github.com/unraid/api.git
synced 2026-05-05 14:41:54 -05:00
feat: settings through the API (#867)
* feat: api settings fully working * refactor: nuxt config ConnectSettings --------- Co-authored-by: Zack Spear <hi@zackspear.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="3.4.0"
|
||||
version="3.5.2+20f10951"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
[notifier]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="3.4.0"
|
||||
version="3.5.2+20f10951"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
[notifier]
|
||||
@@ -21,4 +21,5 @@ dynamicRemoteAccessType="DISABLED"
|
||||
[upc]
|
||||
apikey="unupc_fab6ff6ffe51040595c6d9ffb63a353ba16cc2ad7d93f813a2e80a5810"
|
||||
[connectionStatus]
|
||||
minigraph="PRE_INIT"
|
||||
minigraph="ERROR_RETRYING"
|
||||
upnpStatus="Success: UPNP Lease Renewed [4/24/2024 5:04:54 PM] Public Port [59138] Local Port [443]"
|
||||
|
||||
@@ -68,7 +68,7 @@ const getRemoteAccessUrlsForAllowedOrigins = (
|
||||
return [];
|
||||
};
|
||||
|
||||
const getExtraOrigins = (): string[] => {
|
||||
export const getExtraOrigins = (): string[] => {
|
||||
const { extraOrigins } = getters.config().api;
|
||||
if (extraOrigins) {
|
||||
return extraOrigins
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import * as Types from '@app/graphql/generated/api/types';
|
||||
|
||||
import { z } from 'zod'
|
||||
import { AllowedOriginInput, ApiKey, ApiKeyResponse, ArrayType, ArrayCapacity, ArrayDisk, ArrayDiskFsColor, ArrayDiskStatus, ArrayDiskType, ArrayPendingState, ArrayState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, DockerContainer, DockerNetwork, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, Notification, NotificationFilter, NotificationInput, NotificationType, Os, Owner, ParityCheck, Partition, Pci, ProfileModel, Registration, RegistrationState, RelayResponse, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addApiKeyInput, addUserInput, arrayDiskInput, authenticateInput, deleteUserInput, mdState, registrationType, updateApikeyInput, usersInput } from '@app/graphql/generated/api/types'
|
||||
import { AllowedOriginInput, ApiKey, ApiKeyResponse, ArrayType, ArrayCapacity, ArrayDisk, ArrayDiskFsColor, ArrayDiskStatus, ArrayDiskType, ArrayPendingState, ArrayState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, DockerContainer, DockerNetwork, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, Notification, NotificationFilter, NotificationInput, NotificationType, Os, Owner, ParityCheck, Partition, Pci, ProfileModel, Registration, RegistrationState, RelayResponse, RemoteAccess, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addApiKeyInput, addUserInput, arrayDiskInput, authenticateInput, deleteUserInput, mdState, registrationType, updateApikeyInput, usersInput } from '@app/graphql/generated/api/types'
|
||||
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||
|
||||
type Properties<T> = Required<{
|
||||
@@ -702,6 +702,15 @@ export function RelayResponseSchema(): z.ZodObject<Properties<RelayResponse>> {
|
||||
})
|
||||
}
|
||||
|
||||
export function RemoteAccessSchema(): z.ZodObject<Properties<RemoteAccess>> {
|
||||
return z.object({
|
||||
__typename: z.literal('RemoteAccess').optional(),
|
||||
accessType: WAN_ACCESS_TYPESchema,
|
||||
forwardType: WAN_FORWARD_TYPESchema.nullish(),
|
||||
port: z.number().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function ServerSchema(): z.ZodObject<Properties<Server>> {
|
||||
return z.object({
|
||||
__typename: z.literal('Server').optional(),
|
||||
|
||||
@@ -874,6 +874,7 @@ export type Query = {
|
||||
dockerNetwork: DockerNetwork;
|
||||
/** All Docker networks */
|
||||
dockerNetworks: Array<Maybe<DockerNetwork>>;
|
||||
extraAllowedOrigins: Array<Scalars['String']['output']>;
|
||||
flash?: Maybe<Flash>;
|
||||
info?: Maybe<Info>;
|
||||
/** Current user account */
|
||||
@@ -883,6 +884,7 @@ export type Query = {
|
||||
owner?: Maybe<Owner>;
|
||||
parityHistory?: Maybe<Array<Maybe<ParityCheck>>>;
|
||||
registration?: Maybe<Registration>;
|
||||
remoteAccess: RemoteAccess;
|
||||
server?: Maybe<Server>;
|
||||
servers: Array<Server>;
|
||||
/** Network Shares */
|
||||
@@ -990,6 +992,13 @@ export type RelayResponse = {
|
||||
timeout?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type RemoteAccess = {
|
||||
__typename?: 'RemoteAccess';
|
||||
accessType: WAN_ACCESS_TYPE;
|
||||
forwardType?: Maybe<WAN_FORWARD_TYPE>;
|
||||
port?: Maybe<Scalars['Port']['output']>;
|
||||
};
|
||||
|
||||
export type Server = {
|
||||
__typename?: 'Server';
|
||||
apikey: Scalars['String']['output'];
|
||||
@@ -1646,6 +1655,7 @@ export type ResolversTypes = ResolversObject<{
|
||||
Registration: ResolverTypeWrapper<Registration>;
|
||||
RegistrationState: RegistrationState;
|
||||
RelayResponse: ResolverTypeWrapper<RelayResponse>;
|
||||
RemoteAccess: ResolverTypeWrapper<RemoteAccess>;
|
||||
Server: ResolverTypeWrapper<Server>;
|
||||
ServerStatus: ServerStatus;
|
||||
Service: ResolverTypeWrapper<Service>;
|
||||
@@ -1739,6 +1749,7 @@ export type ResolversParentTypes = ResolversObject<{
|
||||
Query: {};
|
||||
Registration: Registration;
|
||||
RelayResponse: RelayResponse;
|
||||
RemoteAccess: RemoteAccess;
|
||||
Server: Server;
|
||||
Service: Service;
|
||||
SetupRemoteAccessInput: SetupRemoteAccessInput;
|
||||
@@ -2312,6 +2323,7 @@ export type QueryResolvers<ContextType = Context, ParentType extends ResolversPa
|
||||
dockerContainers?: Resolver<Array<ResolversTypes['DockerContainer']>, ParentType, ContextType, Partial<QuerydockerContainersArgs>>;
|
||||
dockerNetwork?: Resolver<ResolversTypes['DockerNetwork'], ParentType, ContextType, RequireFields<QuerydockerNetworkArgs, 'id'>>;
|
||||
dockerNetworks?: Resolver<Array<Maybe<ResolversTypes['DockerNetwork']>>, ParentType, ContextType, Partial<QuerydockerNetworksArgs>>;
|
||||
extraAllowedOrigins?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
flash?: Resolver<Maybe<ResolversTypes['Flash']>, ParentType, ContextType>;
|
||||
info?: Resolver<Maybe<ResolversTypes['Info']>, ParentType, ContextType>;
|
||||
me?: Resolver<Maybe<ResolversTypes['Me']>, ParentType, ContextType>;
|
||||
@@ -2320,6 +2332,7 @@ export type QueryResolvers<ContextType = Context, ParentType extends ResolversPa
|
||||
owner?: Resolver<Maybe<ResolversTypes['Owner']>, ParentType, ContextType>;
|
||||
parityHistory?: Resolver<Maybe<Array<Maybe<ResolversTypes['ParityCheck']>>>, ParentType, ContextType>;
|
||||
registration?: Resolver<Maybe<ResolversTypes['Registration']>, ParentType, ContextType>;
|
||||
remoteAccess?: Resolver<ResolversTypes['RemoteAccess'], ParentType, ContextType>;
|
||||
server?: Resolver<Maybe<ResolversTypes['Server']>, ParentType, ContextType>;
|
||||
servers?: Resolver<Array<ResolversTypes['Server']>, ParentType, ContextType>;
|
||||
shares?: Resolver<Maybe<Array<Maybe<ResolversTypes['Share']>>>, ParentType, ContextType>;
|
||||
@@ -2347,6 +2360,13 @@ export type RelayResponseResolvers<ContextType = Context, ParentType extends Res
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type RemoteAccessResolvers<ContextType = Context, ParentType extends ResolversParentTypes['RemoteAccess'] = ResolversParentTypes['RemoteAccess']> = ResolversObject<{
|
||||
accessType?: Resolver<ResolversTypes['WAN_ACCESS_TYPE'], ParentType, ContextType>;
|
||||
forwardType?: Resolver<Maybe<ResolversTypes['WAN_FORWARD_TYPE']>, ParentType, ContextType>;
|
||||
port?: Resolver<Maybe<ResolversTypes['Port']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type ServerResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Server'] = ResolversParentTypes['Server']> = ResolversObject<{
|
||||
apikey?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
guid?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
@@ -2755,6 +2775,7 @@ export type Resolvers<ContextType = Context> = ResolversObject<{
|
||||
Query?: QueryResolvers<ContextType>;
|
||||
Registration?: RegistrationResolvers<ContextType>;
|
||||
RelayResponse?: RelayResponseResolvers<ContextType>;
|
||||
RemoteAccess?: RemoteAccessResolvers<ContextType>;
|
||||
Server?: ServerResolvers<ContextType>;
|
||||
Service?: ServiceResolvers<ContextType>;
|
||||
Share?: ShareResolvers<ContextType>;
|
||||
|
||||
@@ -27,12 +27,23 @@ enum WAN_FORWARD_TYPE {
|
||||
STATIC
|
||||
}
|
||||
|
||||
type RemoteAccess {
|
||||
accessType: WAN_ACCESS_TYPE!
|
||||
forwardType: WAN_FORWARD_TYPE
|
||||
port: Port
|
||||
}
|
||||
|
||||
input SetupRemoteAccessInput {
|
||||
accessType: WAN_ACCESS_TYPE!
|
||||
forwardType: WAN_FORWARD_TYPE
|
||||
port: Port
|
||||
}
|
||||
|
||||
type Query {
|
||||
remoteAccess: RemoteAccess!
|
||||
extraAllowedOrigins: [String!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
connectSignIn(input: ConnectSignInInput!): Boolean!
|
||||
connectSignOut: Boolean!
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import { getAllowedOrigins } from '@app/common/allowed-origins';
|
||||
import {
|
||||
getAllowedOrigins,
|
||||
getExtraOrigins,
|
||||
} from '@app/common/allowed-origins';
|
||||
import {
|
||||
WAN_ACCESS_TYPE,
|
||||
WAN_FORWARD_TYPE,
|
||||
type ConnectSignInInput,
|
||||
type SetupRemoteAccessInput,
|
||||
} from '@app/graphql/generated/api/types';
|
||||
import type { Cloud } from '@app/graphql/generated/api/types';
|
||||
import type { Cloud, RemoteAccess } from '@app/graphql/generated/api/types';
|
||||
|
||||
import { connectSignIn } from '@app/graphql/resolvers/mutation/connect/connect-sign-in';
|
||||
import { checkApi } from '@app/graphql/resolvers/query/cloud/check-api';
|
||||
import { checkCloud } from '@app/graphql/resolvers/query/cloud/check-cloud';
|
||||
import { checkMinigraphql } from '@app/graphql/resolvers/query/cloud/check-minigraphql';
|
||||
import { DynamicRemoteAccessType } from '@app/remoteAccess/types';
|
||||
import { setupRemoteAccessThunk } from '@app/store/actions/setup-remote-access';
|
||||
import { store } from '@app/store/index';
|
||||
import { getters, store } from '@app/store/index';
|
||||
import { logoutUser } from '@app/store/modules/config';
|
||||
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||
import { UseRoles } from 'nest-access-control';
|
||||
@@ -45,6 +52,44 @@ export class CloudResolver {
|
||||
};
|
||||
}
|
||||
|
||||
@Query()
|
||||
@UseRoles({
|
||||
resource: 'connect',
|
||||
action: 'read',
|
||||
possession: 'own',
|
||||
})
|
||||
public async remoteAccess(): Promise<RemoteAccess> {
|
||||
const hasWanAccess = getters.config().remote.wanaccess === 'yes';
|
||||
const dynamicRemoteAccessSettings: RemoteAccess = {
|
||||
accessType: hasWanAccess
|
||||
? getters.config().remote.dynamicRemoteAccessType !==
|
||||
DynamicRemoteAccessType.DISABLED
|
||||
? WAN_ACCESS_TYPE.DYNAMIC
|
||||
: WAN_ACCESS_TYPE.ALWAYS
|
||||
: WAN_ACCESS_TYPE.DISABLED,
|
||||
forwardType: getters.config().remote.upnpEnabled
|
||||
? WAN_FORWARD_TYPE.UPNP
|
||||
: WAN_FORWARD_TYPE.STATIC,
|
||||
port: getters.config().remote.wanport
|
||||
? Number(getters.config().remote.wanport)
|
||||
: null,
|
||||
};
|
||||
|
||||
return dynamicRemoteAccessSettings;
|
||||
}
|
||||
|
||||
@Query()
|
||||
@UseRoles({
|
||||
resource: 'connect',
|
||||
action: 'read',
|
||||
possession: 'own',
|
||||
})
|
||||
public async extraAllowedOrigins(): Promise<Array<string>> {
|
||||
const extraOrigins = getExtraOrigins();
|
||||
|
||||
return extraOrigins;
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
@UseRoles({
|
||||
resource: 'connect',
|
||||
|
||||
+2
-1
@@ -2,4 +2,5 @@ VITE_ACCOUNT=https://localhost:8008
|
||||
VITE_CONNECT=https://connect.myunraid.net
|
||||
VITE_UNRAID_NET=https://unraid.ddev.site
|
||||
VITE_CALLBACK_KEY=aNotSoSecretKeyUsedToObfuscateQueryParams
|
||||
VITE_ALLOW_CONSOLE_LOGS=false
|
||||
VITE_ALLOW_CONSOLE_LOGS=false
|
||||
VITE_WEBGUI=http://localhost
|
||||
@@ -0,0 +1,47 @@
|
||||
<script lang="ts" setup>
|
||||
import { useUnraidApiSettingsStore } from '~/store/unraidApiSettings';
|
||||
|
||||
const apiSettingsStore = useUnraidApiSettingsStore();
|
||||
|
||||
const originsText = ref<string>('');
|
||||
const errors = ref<string[]>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
const allowedOriginsSettings = await apiSettingsStore.getAllowedOrigins();
|
||||
originsText.value = allowedOriginsSettings.join(', ');
|
||||
});
|
||||
|
||||
const origins = computed<string[]>(() => {
|
||||
console.log('originsText.value: ' + originsText.value);
|
||||
const newOrigins: string[] = [];
|
||||
if (originsText.value) {
|
||||
originsText.value.split(',').forEach((origin) => {
|
||||
try {
|
||||
const newUrl = new URL(origin.trim());
|
||||
newOrigins.push(newUrl.toString());
|
||||
} catch (e) {
|
||||
errors.value.push(`Invalid origin: ${origin}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return newOrigins;
|
||||
});
|
||||
|
||||
const setAllowedOrigins = () => {
|
||||
apiSettingsStore.setAllowedOrigins(origins.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<h2>Setup Allowed Origins</h2>
|
||||
<input v-model="originsText" type="text" placeholder="Input Comma Separated List of URLs">
|
||||
<button type="button" @click="setAllowedOrigins()">
|
||||
Set Allowed Origins
|
||||
</button>
|
||||
<div v-for="(error, index) of errors" :key="index">
|
||||
<p>{{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import 'tailwindcss/tailwind.css';
|
||||
import '~/assets/main.css';
|
||||
|
||||
// import { useI18n } from 'vue-i18n';
|
||||
|
||||
// const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthCe />
|
||||
<!-- @todo: flashback up -->
|
||||
<WanIpCheckCe />
|
||||
<ConnectSettingsRemoteAccess />
|
||||
<ConnectSettingsAllowedOrigins />
|
||||
<DownloadApiLogsCe />
|
||||
</template>
|
||||
@@ -0,0 +1,60 @@
|
||||
<script lang="ts" setup>
|
||||
import { WAN_ACCESS_TYPE, WAN_FORWARD_TYPE } from '~/composables/gql/graphql';
|
||||
import { useUnraidApiSettingsStore } from '~/store/unraidApiSettings';
|
||||
|
||||
const apiSettingsStore = useUnraidApiSettingsStore();
|
||||
|
||||
const accessType = ref<WAN_ACCESS_TYPE>(WAN_ACCESS_TYPE.Disabled);
|
||||
const forwardType = ref<WAN_FORWARD_TYPE | null>(null);
|
||||
const port = ref<number | null>(null);
|
||||
|
||||
onMounted(async () => {
|
||||
const remoteAccessSettings = await apiSettingsStore.getRemoteAccess();
|
||||
accessType.value =
|
||||
remoteAccessSettings?.accessType ?? WAN_ACCESS_TYPE.Disabled;
|
||||
forwardType.value = remoteAccessSettings?.forwardType ?? null;
|
||||
port.value = remoteAccessSettings?.port ?? null;
|
||||
});
|
||||
|
||||
const setRemoteAccess = () => {
|
||||
apiSettingsStore.setupRemoteAccess({
|
||||
accessType: accessType.value,
|
||||
...(forwardType.value ? { forwardType: forwardType.value } : {}),
|
||||
...(port.value ? { port: port.value } : {}),
|
||||
});
|
||||
};
|
||||
|
||||
watch(accessType, (newVal) => {
|
||||
if (newVal !== WAN_ACCESS_TYPE.Disabled) {
|
||||
forwardType.value = WAN_FORWARD_TYPE.Static;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<h2>Setup Remote Access</h2>
|
||||
<label for="forwardType">Forward Type</label>
|
||||
<select id="forwardType" v-model="accessType">
|
||||
<option v-for="(val, index) in Object.values(WAN_ACCESS_TYPE)" :key="index" :value="val">
|
||||
{{ val }}
|
||||
</option>
|
||||
</select>
|
||||
<template v-if="accessType !== WAN_ACCESS_TYPE.Disabled">
|
||||
<label for="forwardType">Forward Type</label>
|
||||
<select id="forwardType" v-model="forwardType">
|
||||
<option v-for="(val, index) in Object.values(WAN_FORWARD_TYPE)" :key="index" :value="val">
|
||||
{{ val }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-if="forwardType === WAN_FORWARD_TYPE.Static && accessType !== WAN_ACCESS_TYPE.Disabled">
|
||||
<label for="port">Port</label>
|
||||
<input id="port" v-model="port" type="number">
|
||||
</template>
|
||||
|
||||
<button @click="setRemoteAccess">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -17,6 +17,10 @@ const documents = {
|
||||
"\n mutation SignOut {\n connectSignOut\n }\n": types.SignOutDocument,
|
||||
"\n fragment PartialCloud on Cloud {\n error\n apiKey {\n valid\n error\n }\n cloud {\n status\n error\n }\n minigraphql {\n status\n error\n }\n relay {\n status\n error\n }\n }\n": types.PartialCloudFragmentDoc,
|
||||
"\n query serverState {\n cloud {\n ...PartialCloud\n }\n config {\n error\n valid\n }\n info {\n os {\n hostname\n }\n }\n owner {\n avatar\n username\n }\n registration {\n state\n expiration\n keyFile {\n contents\n }\n updateExpiration\n }\n vars {\n regGen\n regState\n configError\n configValid\n }\n }\n": types.serverStateDocument,
|
||||
"\n query getExtraAllowedOrigins {\n extraAllowedOrigins\n }\n": types.getExtraAllowedOriginsDocument,
|
||||
"\n query getRemoteAccess {\n remoteAccess {\n accessType\n forwardType\n port\n }\n }\n": types.getRemoteAccessDocument,
|
||||
"\n mutation setAdditionalAllowedOrigins($input: AllowedOriginInput!) {\n setAdditionalAllowedOrigins(input: $input)\n }\n": types.setAdditionalAllowedOriginsDocument,
|
||||
"\n mutation setupRemoteAccess($input: SetupRemoteAccessInput!) {\n setupRemoteAccess(input: $input)\n }\n": types.setupRemoteAccessDocument,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,6 +53,22 @@ export function graphql(source: "\n fragment PartialCloud on Cloud {\n error
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query serverState {\n cloud {\n ...PartialCloud\n }\n config {\n error\n valid\n }\n info {\n os {\n hostname\n }\n }\n owner {\n avatar\n username\n }\n registration {\n state\n expiration\n keyFile {\n contents\n }\n updateExpiration\n }\n vars {\n regGen\n regState\n configError\n configValid\n }\n }\n"): (typeof documents)["\n query serverState {\n cloud {\n ...PartialCloud\n }\n config {\n error\n valid\n }\n info {\n os {\n hostname\n }\n }\n owner {\n avatar\n username\n }\n registration {\n state\n expiration\n keyFile {\n contents\n }\n updateExpiration\n }\n vars {\n regGen\n regState\n configError\n configValid\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query getExtraAllowedOrigins {\n extraAllowedOrigins\n }\n"): (typeof documents)["\n query getExtraAllowedOrigins {\n extraAllowedOrigins\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query getRemoteAccess {\n remoteAccess {\n accessType\n forwardType\n port\n }\n }\n"): (typeof documents)["\n query getRemoteAccess {\n remoteAccess {\n accessType\n forwardType\n port\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation setAdditionalAllowedOrigins($input: AllowedOriginInput!) {\n setAdditionalAllowedOrigins(input: $input)\n }\n"): (typeof documents)["\n mutation setAdditionalAllowedOrigins($input: AllowedOriginInput!) {\n setAdditionalAllowedOrigins(input: $input)\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation setupRemoteAccess($input: SetupRemoteAccessInput!) {\n setupRemoteAccess(input: $input)\n }\n"): (typeof documents)["\n mutation setupRemoteAccess($input: SetupRemoteAccessInput!) {\n setupRemoteAccess(input: $input)\n }\n"];
|
||||
|
||||
export function graphql(source: string) {
|
||||
return (documents as any)[source] ?? {};
|
||||
|
||||
@@ -878,6 +878,7 @@ export type Query = {
|
||||
dockerNetwork: DockerNetwork;
|
||||
/** All Docker networks */
|
||||
dockerNetworks: Array<Maybe<DockerNetwork>>;
|
||||
extraAllowedOrigins: Array<Scalars['String']['output']>;
|
||||
flash?: Maybe<Flash>;
|
||||
info?: Maybe<Info>;
|
||||
/** Current user account */
|
||||
@@ -887,6 +888,7 @@ export type Query = {
|
||||
owner?: Maybe<Owner>;
|
||||
parityHistory?: Maybe<Array<Maybe<ParityCheck>>>;
|
||||
registration?: Maybe<Registration>;
|
||||
remoteAccess: RemoteAccess;
|
||||
server?: Maybe<Server>;
|
||||
servers: Array<Server>;
|
||||
/** Network Shares */
|
||||
@@ -994,6 +996,13 @@ export type RelayResponse = {
|
||||
timeout?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type RemoteAccess = {
|
||||
__typename?: 'RemoteAccess';
|
||||
accessType: WAN_ACCESS_TYPE;
|
||||
forwardType?: Maybe<WAN_FORWARD_TYPE>;
|
||||
port?: Maybe<Scalars['Port']['output']>;
|
||||
};
|
||||
|
||||
export type Server = {
|
||||
__typename?: 'Server';
|
||||
apikey: Scalars['String']['output'];
|
||||
@@ -1523,7 +1532,35 @@ export type serverStateQuery = { __typename?: 'Query', cloud?: (
|
||||
& { ' $fragmentRefs'?: { 'PartialCloudFragment': PartialCloudFragment } }
|
||||
) | null, config: { __typename?: 'Config', error?: ConfigErrorState | null, valid?: boolean | null }, info?: { __typename?: 'Info', os?: { __typename?: 'Os', hostname?: string | null } | null } | null, owner?: { __typename?: 'Owner', avatar?: string | null, username?: string | null } | null, registration?: { __typename?: 'Registration', state?: RegistrationState | null, expiration?: string | null, updateExpiration?: string | null, keyFile?: { __typename?: 'KeyFile', contents?: string | null } | null } | null, vars?: { __typename?: 'Vars', regGen?: string | null, regState?: RegistrationState | null, configError?: ConfigErrorState | null, configValid?: boolean | null } | null };
|
||||
|
||||
export type getExtraAllowedOriginsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type getExtraAllowedOriginsQuery = { __typename?: 'Query', extraAllowedOrigins: Array<string> };
|
||||
|
||||
export type getRemoteAccessQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type getRemoteAccessQuery = { __typename?: 'Query', remoteAccess: { __typename?: 'RemoteAccess', accessType: WAN_ACCESS_TYPE, forwardType?: WAN_FORWARD_TYPE | null, port?: number | null } };
|
||||
|
||||
export type setAdditionalAllowedOriginsMutationVariables = Exact<{
|
||||
input: AllowedOriginInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type setAdditionalAllowedOriginsMutation = { __typename?: 'Mutation', setAdditionalAllowedOrigins: Array<string> };
|
||||
|
||||
export type setupRemoteAccessMutationVariables = Exact<{
|
||||
input: SetupRemoteAccessInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type setupRemoteAccessMutation = { __typename?: 'Mutation', setupRemoteAccess: boolean };
|
||||
|
||||
export const PartialCloudFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PartialCloud"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Cloud"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cloud"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"minigraphql"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"relay"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode<PartialCloudFragment, unknown>;
|
||||
export const ConnectSignInDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ConnectSignIn"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ConnectSignInInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"connectSignIn"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<ConnectSignInMutation, ConnectSignInMutationVariables>;
|
||||
export const SignOutDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SignOut"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"connectSignOut"}}]}}]} as unknown as DocumentNode<SignOutMutation, SignOutMutationVariables>;
|
||||
export const serverStateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"serverState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cloud"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PartialCloud"}}]}},{"kind":"Field","name":{"kind":"Name","value":"config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"valid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"os"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hostname"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"owner"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"registration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"expiration"}},{"kind":"Field","name":{"kind":"Name","value":"keyFile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"contents"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updateExpiration"}}]}},{"kind":"Field","name":{"kind":"Name","value":"vars"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"regGen"}},{"kind":"Field","name":{"kind":"Name","value":"regState"}},{"kind":"Field","name":{"kind":"Name","value":"configError"}},{"kind":"Field","name":{"kind":"Name","value":"configValid"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PartialCloud"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Cloud"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cloud"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"minigraphql"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"relay"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode<serverStateQuery, serverStateQueryVariables>;
|
||||
export const serverStateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"serverState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cloud"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PartialCloud"}}]}},{"kind":"Field","name":{"kind":"Name","value":"config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"valid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"os"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hostname"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"owner"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"registration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"expiration"}},{"kind":"Field","name":{"kind":"Name","value":"keyFile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"contents"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updateExpiration"}}]}},{"kind":"Field","name":{"kind":"Name","value":"vars"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"regGen"}},{"kind":"Field","name":{"kind":"Name","value":"regState"}},{"kind":"Field","name":{"kind":"Name","value":"configError"}},{"kind":"Field","name":{"kind":"Name","value":"configValid"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PartialCloud"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Cloud"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cloud"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"minigraphql"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"relay"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode<serverStateQuery, serverStateQueryVariables>;
|
||||
export const getExtraAllowedOriginsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"getExtraAllowedOrigins"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"extraAllowedOrigins"}}]}}]} as unknown as DocumentNode<getExtraAllowedOriginsQuery, getExtraAllowedOriginsQueryVariables>;
|
||||
export const getRemoteAccessDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"getRemoteAccess"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"remoteAccess"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accessType"}},{"kind":"Field","name":{"kind":"Name","value":"forwardType"}},{"kind":"Field","name":{"kind":"Name","value":"port"}}]}}]}}]} as unknown as DocumentNode<getRemoteAccessQuery, getRemoteAccessQueryVariables>;
|
||||
export const setAdditionalAllowedOriginsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"setAdditionalAllowedOrigins"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AllowedOriginInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"setAdditionalAllowedOrigins"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<setAdditionalAllowedOriginsMutation, setAdditionalAllowedOriginsMutationVariables>;
|
||||
export const setupRemoteAccessDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"setupRemoteAccess"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SetupRemoteAccessInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"setupRemoteAccess"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<setupRemoteAccessMutation, setupRemoteAccessMutationVariables>;
|
||||
@@ -54,6 +54,7 @@ export default defineNuxtConfig({
|
||||
],
|
||||
components: [
|
||||
{ path: '~/components/Brand', prefix: 'Brand' },
|
||||
{ path: '~/components/ConnectSettings', prefix: 'ConnectSettings' },
|
||||
{ path: '~/components/Ui', prefix: 'Ui' },
|
||||
{ path: '~/components/UserProfile', prefix: 'Upc' },
|
||||
{ path: '~/components/UpdateOs', prefix: 'UpdateOs' },
|
||||
@@ -88,6 +89,10 @@ export default defineNuxtConfig({
|
||||
name: 'UnraidAuth',
|
||||
path: '@/components/Auth.ce',
|
||||
},
|
||||
{
|
||||
name: 'UnraidConnectSettings',
|
||||
path: '@/components/ConnectSettings/ConnectSettings.ce',
|
||||
},
|
||||
{
|
||||
name: 'UnraidDownloadApiLogs',
|
||||
path: '@/components/DownloadApiLogs.ce',
|
||||
|
||||
+12
-5
@@ -72,21 +72,28 @@ onMounted(() => {
|
||||
<UserProfileCe :server="serverState" />
|
||||
</header>
|
||||
<hr class="border-black dark:border-white">
|
||||
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
ConnectSettingsCe
|
||||
</h3>
|
||||
<ConnectSettingsCe />
|
||||
<hr class="border-black dark:border-white">
|
||||
|
||||
<!-- <h3 class="text-lg font-semibold font-mono">
|
||||
DownloadApiLogsCe
|
||||
</h3>
|
||||
<DownloadApiLogsCe />
|
||||
<hr class="border-black dark:border-white">
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
<hr class="border-black dark:border-white"> -->
|
||||
<!-- <h3 class="text-lg font-semibold font-mono">
|
||||
AuthCe
|
||||
</h3>
|
||||
<AuthCe />
|
||||
<hr class="border-black dark:border-white">
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
<hr class="border-black dark:border-white"> -->
|
||||
<!-- <h3 class="text-lg font-semibold font-mono">
|
||||
WanIpCheckCe
|
||||
</h3>
|
||||
<WanIpCheckCe php-wan-ip="47.184.85.45" />
|
||||
<hr class="border-black dark:border-white">
|
||||
<hr class="border-black dark:border-white"> -->
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
UpdateOsCe
|
||||
</h3>
|
||||
|
||||
@@ -9,7 +9,9 @@ onBeforeMount(() => {
|
||||
|
||||
<template>
|
||||
<client-only>
|
||||
<unraid-i18n-host class="flex flex-col gap-6 p-6 mx-auto text-black bg-white dark:text-white dark:bg-black">
|
||||
<unraid-i18n-host
|
||||
class="flex flex-col gap-6 p-6 mx-auto text-black bg-white dark:text-white dark:bg-black"
|
||||
>
|
||||
<h2 class="text-xl font-semibold font-mono">
|
||||
Web Components
|
||||
</h2>
|
||||
@@ -25,6 +27,12 @@ onBeforeMount(() => {
|
||||
</div>
|
||||
<unraid-user-profile :server="JSON.stringify(serverState)" />
|
||||
</header>
|
||||
<hr class="border-black dark:border-white" >
|
||||
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
ConnectSettingsCe
|
||||
</h3>
|
||||
<ConnectSettingsCe />
|
||||
<hr class="border-black dark:border-white">
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
DownloadApiLogsCe
|
||||
@@ -54,7 +62,10 @@ onBeforeMount(() => {
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
DowngradeOsCe
|
||||
</h3>
|
||||
<unraid-downgrade-os restore-release-date="2022-10-10" restore-version="6.11.2" />
|
||||
<unraid-downgrade-os
|
||||
restore-release-date="2022-10-10"
|
||||
restore-version="6.11.2"
|
||||
/>
|
||||
<hr class="border-black dark:border-white">
|
||||
<h3 class="text-lg font-semibold font-mono">
|
||||
RegistrationCe
|
||||
|
||||
+49
-49
@@ -9,25 +9,25 @@ import {
|
||||
import {
|
||||
type ApolloClient as ApolloClientType,
|
||||
type InMemoryCache as InMemoryCacheType,
|
||||
} from "@apollo/client/core";
|
||||
import { onError } from "@apollo/client/link/error";
|
||||
import { RetryLink } from "@apollo/client/link/retry";
|
||||
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
|
||||
import { getMainDefinition } from "@apollo/client/utilities";
|
||||
import { ArrowPathIcon, CogIcon } from "@heroicons/vue/24/solid";
|
||||
import { provideApolloClient } from "@vue/apollo-composable";
|
||||
} from '@apollo/client';
|
||||
import { onError } from '@apollo/client/link/error';
|
||||
import { RetryLink } from '@apollo/client/link/retry';
|
||||
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
|
||||
import { getMainDefinition } from '@apollo/client/utilities';
|
||||
import { ArrowPathIcon, CogIcon } from '@heroicons/vue/24/solid';
|
||||
import { provideApolloClient } from '@vue/apollo-composable';
|
||||
// import { logErrorMessages } from '@vue/apollo-util';
|
||||
import { createClient } from "graphql-ws";
|
||||
import { defineStore, createPinia, setActivePinia } from "pinia";
|
||||
import type { UserProfileLink } from "~/types/userProfile";
|
||||
import { createClient } from 'graphql-ws';
|
||||
import { defineStore, createPinia, setActivePinia } from 'pinia';
|
||||
import type { UserProfileLink } from '~/types/userProfile';
|
||||
|
||||
import { WebguiUnraidApiCommand } from "~/composables/services/webgui";
|
||||
import { WebguiUnraidApiCommand } from '~/composables/services/webgui';
|
||||
import {
|
||||
WEBGUI_GRAPHQL,
|
||||
WEBGUI_SETTINGS_MANAGMENT_ACCESS,
|
||||
} from "~/helpers/urls";
|
||||
import { useErrorsStore } from "~/store/errors";
|
||||
import { useServerStore } from "~/store/server";
|
||||
} from '~/helpers/urls';
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
import { useServerStore } from '~/store/server';
|
||||
|
||||
/**
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
@@ -36,12 +36,12 @@ import { useServerStore } from "~/store/server";
|
||||
setActivePinia(createPinia());
|
||||
|
||||
const ERROR_CORS_403 =
|
||||
"The CORS policy for this site does not allow access from the specified Origin";
|
||||
'The CORS policy for this site does not allow access from the specified Origin';
|
||||
|
||||
const httpEndpoint = WEBGUI_GRAPHQL;
|
||||
const wsEndpoint = new URL(WEBGUI_GRAPHQL.toString().replace("http", "ws"));
|
||||
const wsEndpoint = new URL(WEBGUI_GRAPHQL.toString().replace('http', 'ws'));
|
||||
|
||||
export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
export const useUnraidApiStore = defineStore('unraidApi', () => {
|
||||
const errorsStore = useErrorsStore();
|
||||
const serverStore = useServerStore();
|
||||
const unraidApiClient = ref<ApolloClientType<InMemoryCacheType> | null>(null);
|
||||
@@ -50,21 +50,21 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
const apiResponse = serverStore.fetchServerFromApi();
|
||||
if (apiResponse) {
|
||||
// we have a response, so we're online
|
||||
unraidApiStatus.value = "online";
|
||||
unraidApiStatus.value = 'online';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// const unraidApiErrors = ref<any[]>([]);
|
||||
const unraidApiStatus = ref<
|
||||
"connecting" | "offline" | "online" | "restarting"
|
||||
>("offline");
|
||||
'connecting' | 'offline' | 'online' | 'restarting'
|
||||
>('offline');
|
||||
const prioritizeCorsError = ref(false); // Ensures we don't overwrite this specific error message with a non-descriptive network error message
|
||||
|
||||
const unraidApiRestartAction = computed((): UserProfileLink | undefined => {
|
||||
const { connectPluginInstalled, stateDataError } = serverStore;
|
||||
if (
|
||||
unraidApiStatus.value !== "offline" ||
|
||||
unraidApiStatus.value !== 'offline' ||
|
||||
!connectPluginInstalled ||
|
||||
stateDataError
|
||||
) {
|
||||
@@ -74,7 +74,7 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
click: () => restartUnraidApiClient(),
|
||||
emphasize: true,
|
||||
icon: ArrowPathIcon,
|
||||
text: "Restart unraid-api",
|
||||
text: 'Restart unraid-api',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -83,9 +83,9 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
*/
|
||||
const createApolloClient = () => {
|
||||
// return; // @todo remove
|
||||
unraidApiStatus.value = "connecting";
|
||||
unraidApiStatus.value = 'connecting';
|
||||
|
||||
const headers = { "x-api-key": serverStore.apiKey };
|
||||
const headers = { 'x-api-key': serverStore.apiKey };
|
||||
|
||||
const httpLink = createHttpLink({
|
||||
uri: httpEndpoint.toString(),
|
||||
@@ -106,13 +106,13 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
if (graphQLErrors) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
graphQLErrors.map((error: any) => {
|
||||
console.error("[GraphQL error]", error);
|
||||
console.error('[GraphQL error]', error);
|
||||
const errorMsg =
|
||||
error.error && error.error.message
|
||||
? error.error.message
|
||||
: error.message;
|
||||
if (errorMsg && errorMsg.includes("offline")) {
|
||||
unraidApiStatus.value = "offline";
|
||||
if (errorMsg && errorMsg.includes('offline')) {
|
||||
unraidApiStatus.value = 'offline';
|
||||
// attempt to automatically restart the unraid-api
|
||||
if (unraidApiRestartAction) {
|
||||
restartUnraidApiClient();
|
||||
@@ -122,16 +122,16 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
prioritizeCorsError.value = true;
|
||||
const msg = `<p>The CORS policy for the unraid-api does not allow access from the specified origin.</p><p>If you are using a reverse proxy, you need to copy your origin <strong class="font-mono"><em>${window.location.origin}</em></strong> and paste it into the "Extra Origins" list in the Connect settings.</p>`;
|
||||
errorsStore.setError({
|
||||
heading: "Unraid API • CORS Error",
|
||||
heading: 'Unraid API • CORS Error',
|
||||
message: msg,
|
||||
level: "error",
|
||||
ref: "unraidApiCorsError",
|
||||
type: "unraidApiGQL",
|
||||
level: 'error',
|
||||
ref: 'unraidApiCorsError',
|
||||
type: 'unraidApiGQL',
|
||||
actions: [
|
||||
{
|
||||
href: `${WEBGUI_SETTINGS_MANAGMENT_ACCESS.toString()}#extraOriginsSettings`,
|
||||
icon: CogIcon,
|
||||
text: "Go to Connect Settings",
|
||||
text: 'Go to Connect Settings',
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -144,10 +144,10 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
console.error(`[Network error]: ${networkError}`);
|
||||
const msg = networkError.message ? networkError.message : networkError;
|
||||
if (
|
||||
typeof msg === "string" &&
|
||||
msg.includes("Unexpected token < in JSON at position 0")
|
||||
typeof msg === 'string' &&
|
||||
msg.includes('Unexpected token < in JSON at position 0')
|
||||
) {
|
||||
return "Unraid API • CORS Error";
|
||||
return 'Unraid API • CORS Error';
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
@@ -176,8 +176,8 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
({ query }: any) => {
|
||||
const definition: Definintion = getMainDefinition(query);
|
||||
return (
|
||||
definition.kind === "OperationDefinition" &&
|
||||
definition.operation === "subscription"
|
||||
definition.kind === 'OperationDefinition' &&
|
||||
definition.operation === 'subscription'
|
||||
);
|
||||
},
|
||||
wsLink,
|
||||
@@ -190,13 +190,13 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
*/
|
||||
const additiveLink = from([errorLink, retryLink, splitLinks]);
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
const client: ApolloClientType<InMemoryCacheType> = new ApolloClient({
|
||||
link: additiveLink,
|
||||
cache: new InMemoryCache(),
|
||||
}) as ApolloClientType<InMemoryCacheType>;
|
||||
unraidApiClient.value = apolloClient;
|
||||
});
|
||||
unraidApiClient.value = client;
|
||||
|
||||
provideApolloClient(apolloClient);
|
||||
provideApolloClient(client);
|
||||
};
|
||||
/**
|
||||
* Automatically called when an apiKey is unset in the serverStore
|
||||
@@ -217,8 +217,8 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
* Can both start and restart the unraid-api depending on it's current status
|
||||
*/
|
||||
const restartUnraidApiClient = async () => {
|
||||
const command = unraidApiStatus.value === "offline" ? "start" : "restart";
|
||||
unraidApiStatus.value = "restarting";
|
||||
const command = unraidApiStatus.value === 'offline' ? 'start' : 'restart';
|
||||
unraidApiStatus.value = 'restarting';
|
||||
try {
|
||||
await WebguiUnraidApiCommand({
|
||||
csrf_token: serverStore.csrf,
|
||||
@@ -230,18 +230,18 @@ export const useUnraidApiStore = defineStore("unraidApi", () => {
|
||||
}
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
let errorMessage = "Unknown error";
|
||||
if (typeof error === "string") {
|
||||
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",
|
||||
heading: 'Error: unraid-api restart',
|
||||
message: errorMessage,
|
||||
level: "error",
|
||||
ref: "restartUnraidApiClient",
|
||||
type: "request",
|
||||
level: 'error',
|
||||
ref: 'restartUnraidApiClient',
|
||||
type: 'request',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { graphql } from '~/composables/gql/gql';
|
||||
|
||||
export const GET_ALLOWED_ORIGINS = graphql(/* GraphQL */ `
|
||||
query getExtraAllowedOrigins {
|
||||
extraAllowedOrigins
|
||||
}
|
||||
`);
|
||||
|
||||
export const GET_REMOTE_ACCESS = graphql(/* GraphQL */ `
|
||||
query getRemoteAccess {
|
||||
remoteAccess {
|
||||
accessType
|
||||
forwardType
|
||||
port
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const SET_ADDITIONAL_ALLOWED_ORIGINS = graphql(/* GraphQL */ `
|
||||
mutation setAdditionalAllowedOrigins($input: AllowedOriginInput!) {
|
||||
setAdditionalAllowedOrigins(input: $input)
|
||||
}
|
||||
`);
|
||||
|
||||
export const SETUP_REMOTE_ACCESS = graphql(/* GraphQL */ `
|
||||
mutation setupRemoteAccess($input: SetupRemoteAccessInput!) {
|
||||
setupRemoteAccess(input: $input)
|
||||
}
|
||||
`);
|
||||
@@ -0,0 +1,55 @@
|
||||
import type { SetupRemoteAccessInput } from '~/composables/gql/graphql';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import {
|
||||
GET_ALLOWED_ORIGINS,
|
||||
GET_REMOTE_ACCESS,
|
||||
SETUP_REMOTE_ACCESS,
|
||||
SET_ADDITIONAL_ALLOWED_ORIGINS,
|
||||
} from '~/store/unraidApiSettings.fragment';
|
||||
|
||||
export const useUnraidApiSettingsStore = defineStore(
|
||||
'unraidApiSettings',
|
||||
() => {
|
||||
const { unraidApiClient } = toRefs(useUnraidApiStore());
|
||||
|
||||
const getAllowedOrigins = async () => {
|
||||
const origins = await unraidApiClient.value?.query({
|
||||
query: GET_ALLOWED_ORIGINS,
|
||||
});
|
||||
|
||||
return origins?.data?.extraAllowedOrigins ?? [];
|
||||
};
|
||||
|
||||
const setAllowedOrigins = async (origins: string[]) => {
|
||||
const newOrigins = await unraidApiClient.value?.mutate({
|
||||
mutation: SET_ADDITIONAL_ALLOWED_ORIGINS,
|
||||
variables: { input: { origins } },
|
||||
});
|
||||
|
||||
return newOrigins?.data?.setAdditionalAllowedOrigins;
|
||||
};
|
||||
|
||||
const getRemoteAccess = async () => {
|
||||
const remoteAccess = await unraidApiClient.value?.query({
|
||||
query: GET_REMOTE_ACCESS,
|
||||
});
|
||||
|
||||
return remoteAccess?.data?.remoteAccess;
|
||||
};
|
||||
|
||||
const setupRemoteAccess = async (input: SetupRemoteAccessInput) => {
|
||||
const response = await unraidApiClient.value?.mutate({
|
||||
mutation: SETUP_REMOTE_ACCESS,
|
||||
variables: { input },
|
||||
});
|
||||
return response?.data?.setupRemoteAccess;
|
||||
};
|
||||
|
||||
return {
|
||||
getAllowedOrigins,
|
||||
setAllowedOrigins,
|
||||
getRemoteAccess,
|
||||
setupRemoteAccess,
|
||||
};
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user