Skip to content

Commit

Permalink
Issue 6481 - UI - When ports that are in use are used to update a DS …
Browse files Browse the repository at this point in the history
…instance the error message is not helpful

Bug description:
When updating port values on a DS instance, if the port value is already in use
the error message displayed by the UI is not helpful.

Fix description:
Add a UI method that checks if the updated port value is already in use.
If it is, disable the save button.

Fixes: 389ds#6481

Reviewed by:
  • Loading branch information
jchapma committed Jan 8, 2025
1 parent 89aef89 commit 3f6de55
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 13 deletions.
114 changes: 101 additions & 13 deletions src/cockpit/389-console/src/lib/server/settings.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cockpit from "cockpit";
import React from "react";
import { log_cmd, valid_dn, isValidIpAddress } from "../tools.jsx";
import { log_cmd, valid_dn, isValidIpAddress, is_port_in_use } from "../tools.jsx";
import {
Button,
Checkbox,
Expand Down Expand Up @@ -187,26 +187,106 @@ export class ServerSettings extends React.Component {
this.reloadDiskMonitoring = this.reloadDiskMonitoring.bind(this);
this.handleSaveAdvanced = this.handleSaveAdvanced.bind(this);
this.reloadAdvanced = this.reloadAdvanced.bind(this);
this.onMinusConfig = (id, nav_tab) => {
this.setState({
[id]: Number(this.state[id]) - 1
}, () => { this.validateSaveBtn(nav_tab, id, Number(this.state[id])) });

this.onMinusConfig = async (id, nav_tab) => {
const errObj = { ...this.state.errObjConfig };

if (id === 'nsslapd-port' || id === 'nsslapd-secureport') {
const portValue = Number(this.state[id]) - 1;
try {
// Is the updated port value already used
errObj[id] = await is_port_in_use(portValue);
this.setState({
errObjConfig: errObj,
[id]: portValue,
}, () => {
this.validateSaveBtn(nav_tab, id, portValue);
});
} catch (error) {
console.error("Error checking port:", error);
errObj[id] = true;
this.setState({
errObjConfig: errObj,
}, () => {
this.validateSaveBtn(nav_tab, id, portValue);
});
}
} else {
this.setState({
[id]: Number(this.state[id]) - 1
}, () => {
this.validateSaveBtn(nav_tab, id, Number(this.state[id]));
});
}
};
this.onConfigChange = (event, id, min, max, nav_tab) => {
this.onConfigChange = async (event, id, min, max, nav_tab) => {
const errObj = { ...this.state.errObjConfig };
let maxValue = this.maxValue;
if (max !== 0) {
maxValue = max;
}
let newValue = isNaN(event.target.value) ? min : Number(event.target.value);
newValue = newValue > maxValue ? maxValue : newValue < min ? min : newValue;
this.setState({
[id]: newValue
}, () => { this.validateSaveBtn(nav_tab, id, newValue) });

if (id === 'nsslapd-port' || id === 'nsslapd-secureport') {
if (newValue) {
try {
// Is the updated port value already used
errObj[id] = await is_port_in_use(newValue);
this.setState({
errObjConfig: errObj,
[id]: newValue,
}, () => {
this.validateSaveBtn(nav_tab, id, newValue);
});
} catch (error) {
console.error("Error checking port:", error);
errObj[id] = true;
this.setState({
errObjConfig: errObj,
}, () => {
this.validateSaveBtn(nav_tab, id, newValue);
});
}
}
} else {
this.setState({
[id]: newValue
}, () => {
this.validateSaveBtn(nav_tab, id, Number(this.state[id]));
});
}
};
this.onPlusConfig = (id, nav_tab) => {
this.setState({
[id]: Number(this.state[id]) + 1
}, () => { this.validateSaveBtn(nav_tab, id, Number(this.state[id])) });
this.onPlusConfig = async (id, nav_tab) => {
const errObj = { ...this.state.errObjConfig };

if (id === 'nsslapd-port' || id === 'nsslapd-secureport') {
const portValue = Number(this.state[id]) + 1;
try {
// Is the updated port value already used
errObj[id] = await is_port_in_use(portValue);
this.setState({
errObjConfig: errObj,
[id]: portValue,
}, () => {
this.validateSaveBtn(nav_tab, id, portValue);
});
} catch (error) {
console.error("Error checking port:", error);
errObj[id] = true;
this.setState({
errObjConfig: errObj,
}, () => {
this.validateSaveBtn(nav_tab, id, portValue);
});
}
} else {
this.setState({
[id]: Number(this.state[id]) + 1
}, () => {
this.validateSaveBtn(nav_tab, id, Number(this.state[id]));
});
}
};
this.validateSaveBtn = this.validateSaveBtn.bind(this);
}
Expand Down Expand Up @@ -298,6 +378,12 @@ export class ServerSettings extends React.Component {
valueErr = true;
disableSaveBtn = true;
}
if (attr === 'nsslapd-port' || attr === 'nsslapd-secureport') {
// Check errObj for port values that are already in use.
if (errObj[attr] == true) {
disableSaveBtn = true;
}
}
} else if (nav_tab === "rootdn") {
// Handle validating passwords are in sync
if (attr === 'nsslapd-rootpw') {
Expand Down Expand Up @@ -1007,6 +1093,8 @@ export class ServerSettings extends React.Component {
});
}



render() {
let body = "";
let diskMonitor = "";
Expand Down
26 changes: 26 additions & 0 deletions src/cockpit/389-console/src/lib/tools.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,32 @@ export function valid_port(val) {
return result;
}

export function is_port_in_use(port) {
// Check if a port number is being used
return new Promise((resolve, reject) => {
// First check port number is within range
if (!valid_port(port)) {
reject('Invalid port number');
return;
}

let cmd = ['bash', '-c', `sudo lsof -i :${port} || echo "free"`];
log_cmd("is_port_in_use", cmd);

cockpit
.spawn(cmd, { superuser: true, err: "message" })
.done((result) => {
const isPortInUse = result.trim() !== "free";
// Resolve the promise with a result
resolve(isPortInUse);
})
.fail((error) => {
// Reject the promise on error
reject('Error checking port');
});
});
}

export function valid_dn(dn) {
// Validate value is a valid DN (sanity validation)
if (dn === "" || dn.endsWith(",")) {
Expand Down

0 comments on commit 3f6de55

Please sign in to comment.