Add secondary persistence verification and UI integration

This commit is contained in:
cedricve
2025-04-23 15:24:24 +00:00
parent dd9b4d43ac
commit 9c7116a462
4 changed files with 141 additions and 16 deletions

View File

@@ -189,6 +189,8 @@
"description_kerberoshub": "Kerberos Agents can send heartbeats to a central",
"description2_kerberoshub": "installation. Heartbeats and other relevant information are synced to Kerberos Hub to show realtime information about your video landscape.",
"persistence": "Persistence",
"secondary_persistence": "Secondary Persistence",
"description_secondary_persistence": "Recordings will be sent to secondary persistence if the primary persistence is unavailable or fails. This can be useful for failover purposes.",
"saasoffering": "Kerberos Hub (SAAS offering)",
"description_persistence": "Having the ability to store your recordings is the beginning of everything. You can choose between our",
"description2_persistence": ", or a 3rd party provider",

View File

@@ -4,6 +4,7 @@ import {
doVerifyOnvif,
doVerifyHub,
doVerifyPersistence,
doVerifySecondaryPersistence,
doGetKerberosAgentTags,
doGetDashboardInformation,
doGetEvents,
@@ -107,6 +108,28 @@ export const verifyPersistence = (config, onSuccess, onError) => {
};
};
export const verifySecondaryPersistence = (config, onSuccess, onError) => {
return (dispatch) => {
doVerifySecondaryPersistence(
config,
() => {
dispatch({
type: 'VERIFY_SECONDARY_PERSISTENCE',
});
if (onSuccess) {
onSuccess();
}
},
(error) => {
const { data } = error.response.data;
if (onError) {
onError(data);
}
}
);
};
};
export const verifyHub = (config, onSuccess, onError) => {
return (dispatch) => {
doVerifyHub(

View File

@@ -72,6 +72,25 @@ export function doVerifyPersistence(config, onSuccess, onError) {
});
}
export function doVerifySecondaryPersistence(config, onSuccess, onError) {
const endpoint = API.post(`persistence/secondary/verify`, {
...config,
});
endpoint
.then((res) => {
if (res.status !== 200) {
throw new Error(res.data);
}
return res.data;
})
.then((data) => {
onSuccess(data);
})
.catch((error) => {
onError(error);
});
}
export function doVerifyHub(config, onSuccess, onError) {
const endpoint = API.post(`hub/verify`, {
...config,

View File

@@ -33,6 +33,7 @@ import {
verifyCamera,
verifyHub,
verifyPersistence,
verifySecondaryPersistence,
getConfig,
updateConfig,
} from '../../actions/agent';
@@ -125,6 +126,8 @@ class Settings extends React.Component {
this.onUpdateTimeline = this.onUpdateTimeline.bind(this);
this.initialiseLiveview = this.initialiseLiveview.bind(this);
this.verifyPersistenceSettings = this.verifyPersistenceSettings.bind(this);
this.verifySecondaryPersistenceSettings =
this.verifySecondaryPersistenceSettings.bind(this);
this.verifyHubSettings = this.verifyHubSettings.bind(this);
this.verifyCameraSettings = this.verifyCameraSettings.bind(this);
this.verifySubCameraSettings = this.verifySubCameraSettings.bind(this);
@@ -390,6 +393,8 @@ class Settings extends React.Component {
configError: false,
verifyPersistenceSuccess: false,
verifyPersistenceError: false,
verifySecondaryPersistenceSuccess: false,
verifySecondaryPersistenceError: false,
verifyHubSuccess: false,
verifyHubError: false,
verifyHubErrorMessage: '',
@@ -441,6 +446,8 @@ class Settings extends React.Component {
verifyHubError: false,
verifyPersistenceSuccess: false,
verifyPersistenceError: false,
verifySecondaryPersistenceSuccess: false,
verifySecondaryPersistenceError: false,
persistenceSuccess: false,
persistenceError: false,
verifyCameraSuccess: false,
@@ -477,6 +484,54 @@ class Settings extends React.Component {
}
}
verifySecondaryPersistenceSettings() {
const { config, dispatchVerifySecondaryPersistence } = this.props;
if (config) {
this.setState({
configSuccess: false,
configError: false,
verifyHubSuccess: false,
verifyHubError: false,
verifyPersistenceSuccess: false,
verifyPersistenceError: false,
verifySecondaryPersistenceSuccess: false,
verifySecondaryPersistenceError: false,
persistenceSuccess: false,
persistenceError: false,
verifyCameraSuccess: false,
verifyCameraError: false,
verifyOnvifSuccess: false,
verifyOnvifError: false,
verifyCameraErrorMessage: '',
loading: true,
});
dispatchVerifySecondaryPersistence(
config.config,
() => {
this.setState({
verifySecondaryPersistenceSuccess: true,
verifySecondaryPersistenceError: false,
verifySecondaryPersistenceMessage: '',
persistenceSuccess: false,
persistenceError: false,
loading: false,
});
},
(error) => {
this.setState({
verifySecondaryPersistenceSuccess: false,
verifySecondaryPersistenceError: true,
verifySecondaryPersistenceMessage: error,
persistenceSuccess: false,
persistenceError: false,
loading: false,
});
}
);
}
}
verifySubCameraSettings(event) {
this.verifyCameraSettings(event, 'secondary');
}
@@ -2516,19 +2571,28 @@ class Settings extends React.Component {
<h4>{t('settings.persistence.secondary_persistence')}</h4>
</BlockHeader>
<BlockBody>
<p>
{t(
'settings.persistence.description_secondary_persistence'
)}
</p>
<Input
noPadding
label={t('settings.persistence.kerberosvault_apiurl')}
placeholder={t(
'settings.persistence.kerberosvault_description_apiurl'
)}
value={config.kstorage ? config.kstorage.uri : ''}
value={
config.kstorage_secondary
? config.kstorage_secondary.uri
: ''
}
onChange={(value) =>
this.onUpdateField(
'kstorage',
'kstorage_secondary',
'uri',
value,
config.kstorage
config.kstorage_secondary
)
}
/>
@@ -2538,13 +2602,17 @@ class Settings extends React.Component {
placeholder={t(
'settings.persistence.kerberosvault_description_provider'
)}
value={config.kstorage ? config.kstorage.provider : ''}
value={
config.kstorage_secondary
? config.kstorage_secondary.provider
: ''
}
onChange={(value) =>
this.onUpdateField(
'kstorage',
'kstorage_secondary',
'provider',
value,
config.kstorage
config.kstorage_secondary
)
}
/>
@@ -2554,13 +2622,17 @@ class Settings extends React.Component {
placeholder={t(
'settings.persistence.kerberosvault_description_directory'
)}
value={config.kstorage ? config.kstorage.directory : ''}
value={
config.kstorage_secondary
? config.kstorage_secondary.directory
: ''
}
onChange={(value) =>
this.onUpdateField(
'kstorage',
'kstorage_secondary',
'directory',
value,
config.kstorage
config.kstorage_secondary
)
}
/>
@@ -2571,13 +2643,17 @@ class Settings extends React.Component {
placeholder={t(
'settings.persistence.kerberosvault_description_accesskey'
)}
value={config.kstorage ? config.kstorage.access_key : ''}
value={
config.kstorage_secondary
? config.kstorage_secondary.access_key
: ''
}
onChange={(value) =>
this.onUpdateField(
'kstorage',
'kstorage_secondary',
'access_key',
value,
config.kstorage
config.kstorage_secondary
)
}
/>
@@ -2589,14 +2665,16 @@ class Settings extends React.Component {
'settings.persistence.kerberosvault_description_secretkey'
)}
value={
config.kstorage ? config.kstorage.secret_access_key : ''
config.kstorage_secondary
? config.kstorage_secondary.secret_access_key
: ''
}
onChange={(value) =>
this.onUpdateField(
'kstorage',
'kstorage_secondary',
'secret_access_key',
value,
config.kstorage
config.kstorage_secondary
)
}
/>
@@ -2605,7 +2683,7 @@ class Settings extends React.Component {
<Button
label={t('settings.persistence.verify_connection')}
disabled={loading}
onClick={this.verifyPersistenceSettings}
onClick={this.verifySecondaryPersistenceSettings}
type={loading ? 'neutral' : 'default'}
icon="verify"
/>
@@ -2643,6 +2721,8 @@ const mapDispatchToProps = (dispatch /* , ownProps */) => ({
dispatch(verifyHub(config, success, error)),
dispatchVerifyPersistence: (config, success, error) =>
dispatch(verifyPersistence(config, success, error)),
dispatchVerifySecondaryPersistence: (config, success, error) =>
dispatch(verifySecondaryPersistence(config, success, error)),
dispatchGetConfig: (callback) => dispatch(getConfig(callback)),
dispatchUpdateConfig: (field, value) => dispatch(updateConfig(field, value)),
dispatchSaveConfig: (config, success, error) =>
@@ -2660,6 +2740,7 @@ Settings.propTypes = {
images: PropTypes.array.isRequired,
dispatchVerifyHub: PropTypes.func.isRequired,
dispatchVerifyPersistence: PropTypes.func.isRequired,
dispatchVerifySecondaryPersistence: PropTypes.func.isRequired,
dispatchGetConfig: PropTypes.func.isRequired,
dispatchUpdateConfig: PropTypes.func.isRequired,
dispatchSaveConfig: PropTypes.func.isRequired,