mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: only write config when a specific config update action occurs
This commit is contained in:
@@ -2,20 +2,18 @@
|
|||||||
version="3.11.0"
|
version="3.11.0"
|
||||||
extraOrigins="https://google.com,https://test.com"
|
extraOrigins="https://google.com,https://test.com"
|
||||||
[local]
|
[local]
|
||||||
[notifier]
|
|
||||||
[remote]
|
[remote]
|
||||||
wanaccess="yes"
|
wanaccess="yes"
|
||||||
wanport="8443"
|
wanport="8443"
|
||||||
upnpEnabled="no"
|
upnpEnabled="no"
|
||||||
apikey="_______________________BIG_API_KEY_HERE_________________________"
|
apikey="unraid_SfxcHvPqI5MIUE51KHJCb5m21QbIZeowqN3XT4QFHLJm0NQ2ZHAqUuMKW"
|
||||||
localApiKey="_______________________LOCAL_API_KEY_HERE_________________________"
|
localApiKey="_______________________LOCAL_API_KEY_HERE_________________________"
|
||||||
email="test@example.com"
|
email="ekbosley@gmail.com"
|
||||||
username="zspearmint"
|
username="Hi"
|
||||||
avatar="https://via.placeholder.com/200"
|
avatar=""
|
||||||
regWizTime="1611175408732_0951-1653-3509-FBA155FA23C0"
|
regWizTime="1611175408732_0951-1653-3509-FBA155FA23C0"
|
||||||
accesstoken=""
|
accesstoken=""
|
||||||
idtoken=""
|
idtoken=""
|
||||||
refreshtoken=""
|
refreshtoken=""
|
||||||
dynamicRemoteAccessType="DISABLED"
|
dynamicRemoteAccessType="DISABLED"
|
||||||
ssoSubIds=""
|
ssoSubIds=""
|
||||||
[upc]
|
|
||||||
|
|||||||
@@ -2,16 +2,15 @@
|
|||||||
version="3.11.0"
|
version="3.11.0"
|
||||||
extraOrigins="https://google.com,https://test.com"
|
extraOrigins="https://google.com,https://test.com"
|
||||||
[local]
|
[local]
|
||||||
[notifier]
|
|
||||||
[remote]
|
[remote]
|
||||||
wanaccess="yes"
|
wanaccess="yes"
|
||||||
wanport="8443"
|
wanport="8443"
|
||||||
upnpEnabled="no"
|
upnpEnabled="no"
|
||||||
apikey="_______________________BIG_API_KEY_HERE_________________________"
|
apikey="unraid_SfxcHvPqI5MIUE51KHJCb5m21QbIZeowqN3XT4QFHLJm0NQ2ZHAqUuMKW"
|
||||||
localApiKey="_______________________LOCAL_API_KEY_HERE_________________________"
|
localApiKey="_______________________LOCAL_API_KEY_HERE_________________________"
|
||||||
email="test@example.com"
|
email=""
|
||||||
username="zspearmint"
|
username="Hi"
|
||||||
avatar="https://via.placeholder.com/200"
|
avatar=""
|
||||||
regWizTime="1611175408732_0951-1653-3509-FBA155FA23C0"
|
regWizTime="1611175408732_0951-1653-3509-FBA155FA23C0"
|
||||||
accesstoken=""
|
accesstoken=""
|
||||||
idtoken=""
|
idtoken=""
|
||||||
@@ -19,7 +18,6 @@ refreshtoken=""
|
|||||||
dynamicRemoteAccessType="DISABLED"
|
dynamicRemoteAccessType="DISABLED"
|
||||||
ssoSubIds=""
|
ssoSubIds=""
|
||||||
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-100-0-2.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-100-0-2.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
||||||
[upc]
|
|
||||||
[connectionStatus]
|
[connectionStatus]
|
||||||
minigraph="PRE_INIT"
|
minigraph="ERROR_RETRYING"
|
||||||
upnpStatus=""
|
upnpStatus=""
|
||||||
|
|||||||
@@ -1,66 +1,22 @@
|
|||||||
import { startAppListening } from '@app/store/listeners/listener-middleware';
|
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
import { logger } from '@app/core/log';
|
|
||||||
import {
|
|
||||||
type ConfigType,
|
|
||||||
getWriteableConfig,
|
|
||||||
} from '@app/core/utils/files/config-file-normalizer';
|
|
||||||
import {
|
|
||||||
loadConfigFile,
|
|
||||||
loginUser,
|
|
||||||
logoutUser,
|
|
||||||
} from '@app/store/modules/config';
|
|
||||||
import { FileLoadStatus } from '@app/store/types';
|
|
||||||
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer';
|
|
||||||
import { isFulfilled } from '@reduxjs/toolkit';
|
|
||||||
import { environment } from '@app/environment';
|
|
||||||
import { writeFileSync } from 'fs';
|
import { writeFileSync } from 'fs';
|
||||||
|
|
||||||
const actionIsLoginOrLogout = isFulfilled(logoutUser, loginUser);
|
|
||||||
|
import type { ConfigType } from '@app/core/utils/files/config-file-normalizer';
|
||||||
|
import { logger } from '@app/core/log';
|
||||||
|
import { getWriteableConfig } from '@app/core/utils/files/config-file-normalizer';
|
||||||
|
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer';
|
||||||
|
import { startAppListening } from '@app/store/listeners/listener-middleware';
|
||||||
|
import { configUpdateActionsFlash, configUpdateActionsMemory } from '@app/store/modules/config';
|
||||||
|
|
||||||
export const enableConfigFileListener = (mode: ConfigType) => () =>
|
export const enableConfigFileListener = (mode: ConfigType) => () =>
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate(action, currentState, previousState) {
|
matcher: mode === 'flash' ? configUpdateActionsFlash : configUpdateActionsMemory,
|
||||||
if (!environment.IS_MAIN_PROCESS) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentState.config.status === FileLoadStatus.LOADED) {
|
|
||||||
const oldFlashConfig = previousState?.config.api.version
|
|
||||||
? getWriteableConfig(previousState.config, mode)
|
|
||||||
: null;
|
|
||||||
const newFlashConfig = getWriteableConfig(
|
|
||||||
currentState.config,
|
|
||||||
mode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
!isEqual(oldFlashConfig, newFlashConfig) &&
|
|
||||||
action.type !== loadConfigFile.fulfilled.type &&
|
|
||||||
action.type !== loadConfigFile.rejected.type
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionIsLoginOrLogout(action) && mode === 'memory') {
|
|
||||||
logger.trace(
|
|
||||||
'Logout / Login Action Encountered, writing memory config'
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
async effect(_, { getState }) {
|
async effect(_, { getState }) {
|
||||||
const { paths, config } = getState();
|
const { paths, config } = getState();
|
||||||
const pathToWrite =
|
const pathToWrite =
|
||||||
mode === 'flash'
|
mode === 'flash' ? paths['myservers-config'] : paths['myservers-config-states'];
|
||||||
? paths['myservers-config']
|
|
||||||
: paths['myservers-config-states'];
|
|
||||||
const writeableConfig = getWriteableConfig(config, mode);
|
const writeableConfig = getWriteableConfig(config, mode);
|
||||||
const serializedConfig =
|
const serializedConfig = safelySerializeObjectToIni(writeableConfig);
|
||||||
safelySerializeObjectToIni(writeableConfig);
|
|
||||||
logger.debug('Writing updated config to %s', pathToWrite);
|
logger.debug('Writing updated config to %s', pathToWrite);
|
||||||
writeFileSync(pathToWrite, serializedConfig);
|
writeFileSync(pathToWrite, serializedConfig);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { writeFileSync } from 'fs';
|
|||||||
import { access } from 'fs/promises';
|
import { access } from 'fs/promises';
|
||||||
|
|
||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
import { createAsyncThunk, createSlice, isAnyOf } from '@reduxjs/toolkit';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import merge from 'lodash/merge';
|
import merge from 'lodash/merge';
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@ import { setupRemoteAccessThunk } from '@app/store/actions/setup-remote-access';
|
|||||||
import { FileLoadStatus } from '@app/store/types';
|
import { FileLoadStatus } from '@app/store/types';
|
||||||
import { type RecursivePartial } from '@app/types';
|
import { type RecursivePartial } from '@app/types';
|
||||||
import { type MyServersConfig, type MyServersConfigMemory } from '@app/types/my-servers-config';
|
import { type MyServersConfig, type MyServersConfigMemory } from '@app/types/my-servers-config';
|
||||||
|
import { isFulfilled } from '@app/utils';
|
||||||
|
|
||||||
export type SliceState = {
|
export type SliceState = {
|
||||||
status: FileLoadStatus;
|
status: FileLoadStatus;
|
||||||
@@ -291,4 +292,24 @@ export const {
|
|||||||
setWanAccess,
|
setWanAccess,
|
||||||
} = actions;
|
} = actions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions that should trigger a flash write
|
||||||
|
*/
|
||||||
|
export const configUpdateActionsFlash = isAnyOf(
|
||||||
|
updateUserConfig,
|
||||||
|
updateAccessTokens,
|
||||||
|
updateAllowedOrigins,
|
||||||
|
setUpnpState,
|
||||||
|
setWanPortToValue,
|
||||||
|
setWanAccess,
|
||||||
|
setupRemoteAccessThunk.fulfilled,
|
||||||
|
logoutUser.fulfilled,
|
||||||
|
loginUser.fulfilled
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions that should trigger a memory write
|
||||||
|
*/
|
||||||
|
export const configUpdateActionsMemory = isAnyOf(configUpdateActionsFlash, setGraphqlConnectionStatus);
|
||||||
|
|
||||||
export const configReducer = reducer;
|
export const configReducer = reducer;
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export const setupConfigPathWatch = () => {
|
|||||||
ignoreInitial: false,
|
ignoreInitial: false,
|
||||||
usePolling: CHOKIDAR_USEPOLLING === true,
|
usePolling: CHOKIDAR_USEPOLLING === true,
|
||||||
})
|
})
|
||||||
.on('change', async () => {
|
.on('change', async (change) => {
|
||||||
|
logger.trace('Config File Changed, Reloading Config %s', change);
|
||||||
await store.dispatch(loadConfigFile());
|
await store.dispatch(loadConfigFile());
|
||||||
})
|
})
|
||||||
.on('unlink', async () => {
|
.on('unlink', async () => {
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ export class ServerHeaderStrategy extends PassportStrategy(Strategy, 'server-htt
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await this.authService.validateApiKeyCasbin(key);
|
const user = await this.authService.validateApiKeyCasbin(key);
|
||||||
this.logger.debug('API key validation successful', {
|
this.logger.debug('API key validation successful %o', {
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
roles: user?.roles,
|
roles: user?.roles,
|
||||||
});
|
});
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('API key validation failed', {
|
this.logger.error('API key validation failed %o', {
|
||||||
errorType: error instanceof Error ? error.constructor.name : 'Unknown',
|
errorType: error instanceof Error ? error.constructor.name : 'Unknown',
|
||||||
message: error instanceof Error ? error.message : 'Unknown error',
|
message: error instanceof Error ? error.message : 'Unknown error',
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user