Skip to content

Commit

Permalink
Pull request 2019: 1700-update-static-lease
Browse files Browse the repository at this point in the history
Updates #1700.

Squashed commit of the following:

commit b3fdf0a
Merge: 507cb9b 4479b32
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Oct 5 12:53:30 2023 +0300

    Merge branch 'master' into 1700-update-static-lease

commit 507cb9b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Oct 4 18:54:06 2023 +0300

    all: upd chlog

commit 0736b97
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Oct 4 16:05:35 2023 +0300

    client: fix update action

commit 351986b
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Oct 4 16:01:38 2023 +0300

    client: update static lease

commit 3c32828
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Sep 28 20:06:29 2023 +0300

    dhcpd: fix err msg

commit 5b2f8f5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Sep 28 16:28:07 2023 +0300

    dhcpd: imp code

commit a9d24e8
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Sep 27 17:43:04 2023 +0300

    all: add tests

commit 4537857
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Sep 26 20:14:17 2023 +0300

    dhcpd: update static lease
  • Loading branch information
schzhn committed Oct 5, 2023
1 parent 4479b32 commit e305bd8
Show file tree
Hide file tree
Showing 20 changed files with 624 additions and 225 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ NOTE: Add new changes BELOW THIS COMMENT.

### Added

- Ability to edit static leases on *DHCP settings* page ([#1700]).
- Ability to specify for how long clients should cache a filtered response,
using the *Blocked response TTL* field on the *DNS settings* page ([#4569]).

[#1700]: https://github.com/AdguardTeam/AdGuardHome/issues/1700
[#4569]: https://github.com/AdguardTeam/AdGuardHome/issues/4569

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions client/src/__locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@
"dhcp_dynamic_ip_found": "Your system uses dynamic IP address configuration for interface <0>{{interfaceName}}</0>. In order to use DHCP server, a static IP address must be set. Your current IP address is <0>{{ipAddress}}</0>. AdGuard Home will automatically set this IP address as static if you press the \"Enable DHCP server\" button.",
"dhcp_lease_added": "Static lease \"{{key}}\" successfully added",
"dhcp_lease_deleted": "Static lease \"{{key}}\" successfully deleted",
"dhcp_lease_updated": "Static lease \"{{key}}\" successfully updated",
"dhcp_new_static_lease": "New static lease",
"dhcp_edit_static_lease": "Edit static lease",
"dhcp_static_leases_not_found": "No DHCP static leases found",
"dhcp_add_static_lease": "Add static lease",
"dhcp_reset_leases": "Reset all leases",
Expand Down
18 changes: 18 additions & 0 deletions client/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,24 @@ export const removeStaticLease = (config) => async (dispatch) => {
}
};

export const updateStaticLeaseRequest = createAction('UPDATE_STATIC_LEASE_REQUEST');
export const updateStaticLeaseFailure = createAction('UPDATE_STATIC_LEASE_FAILURE');
export const updateStaticLeaseSuccess = createAction('UPDATE_STATIC_LEASE_SUCCESS');

export const updateStaticLease = (config) => async (dispatch) => {
dispatch(updateStaticLeaseRequest());
try {
await apiClient.updateStaticLease(config);
dispatch(updateStaticLeaseSuccess(config));
dispatch(addSuccessToast(i18next.t('dhcp_lease_updated', { key: config.hostname || config.ip })));
dispatch(toggleLeaseModal());
dispatch(getDhcpStatus());
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(updateStaticLeaseFailure());
}
};

export const removeToast = createAction('REMOVE_TOAST');

export const toggleBlocking = (
Expand Down
10 changes: 10 additions & 0 deletions client/src/api/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ class Api {

DHCP_REMOVE_STATIC_LEASE = { path: 'dhcp/remove_static_lease', method: 'POST' };

DHCP_UPDATE_STATIC_LEASE = { path: 'dhcp/update_static_lease', method: 'POST' };

DHCP_RESET = { path: 'dhcp/reset', method: 'POST' };

DHCP_LEASES_RESET = { path: 'dhcp/reset_leases', method: 'POST' };
Expand Down Expand Up @@ -320,6 +322,14 @@ class Api {
return this.makeRequest(path, method, parameters);
}

updateStaticLease(config) {
const { path, method } = this.DHCP_UPDATE_STATIC_LEASE;
const parameters = {
data: config,
};
return this.makeRequest(path, method, parameters);
}

resetDhcp() {
const { path, method } = this.DHCP_RESET;
return this.makeRequest(path, method);
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/Settings/Dhcp/StaticLeases/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Form = ({
submitting,
processingAdding,
cidr,
isEdit,
}) => {
const { t } = useTranslation();
const dispatch = useDispatch();
Expand All @@ -45,6 +46,7 @@ const Form = ({
placeholder={t('form_enter_mac')}
normalize={normalizeMac}
validate={[validateRequiredValue, validateMac]}
disabled={isEdit}
/>
</div>
<div className="form__group">
Expand Down Expand Up @@ -112,6 +114,7 @@ Form.propTypes = {
submitting: PropTypes.bool.isRequired,
processingAdding: PropTypes.bool.isRequired,
cidr: PropTypes.string.isRequired,
isEdit: PropTypes.bool,
};

export default reduxForm({ form: FORM_NAME.LEASE })(Form);
10 changes: 9 additions & 1 deletion client/src/components/Settings/Dhcp/StaticLeases/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import ReactModal from 'react-modal';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import Form from './Form';
import { toggleLeaseModal } from '../../../../actions';
import { MODAL_TYPE } from '../../../../helpers/constants';

const Modal = ({
isModalOpen,
modalType,
handleSubmit,
processingAdding,
cidr,
Expand All @@ -32,7 +34,11 @@ const Modal = ({
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">
<Trans>dhcp_new_static_lease</Trans>
{modalType === MODAL_TYPE.EDIT_LEASE ? (
<Trans>dhcp_edit_static_lease</Trans>
) : (
<Trans>dhcp_new_static_lease</Trans>
)}
</h4>
<button type="button" className="close" onClick={toggleModal}>
<span className="sr-only">Close</span>
Expand All @@ -53,6 +59,7 @@ const Modal = ({
cidr={cidr}
rangeStart={rangeStart}
rangeEnd={rangeEnd}
isEdit={modalType === MODAL_TYPE.EDIT_LEASE}
/>
</div>
</ReactModal>
Expand All @@ -61,6 +68,7 @@ const Modal = ({

Modal.propTypes = {
isModalOpen: PropTypes.bool.isRequired,
modalType: PropTypes.string.isRequired,
handleSubmit: PropTypes.func.isRequired,
processingAdding: PropTypes.bool.isRequired,
cidr: PropTypes.string.isRequired,
Expand Down
59 changes: 45 additions & 14 deletions client/src/components/Settings/Dhcp/StaticLeases/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import PropTypes from 'prop-types';
import ReactTable from 'react-table';
import { Trans, useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../../helpers/constants';
import { LEASES_TABLE_DEFAULT_PAGE_SIZE, MODAL_TYPE } from '../../../../helpers/constants';
import { sortIp } from '../../../../helpers/helpers';
import Modal from './Modal';
import { addStaticLease, removeStaticLease } from '../../../../actions';
import {
addStaticLease,
removeStaticLease,
toggleLeaseModal,
updateStaticLease,
} from '../../../../actions';

const cellWrap = ({ value }) => (
<div className="logs__row o-hidden">
Expand All @@ -18,8 +23,10 @@ const cellWrap = ({ value }) => (

const StaticLeases = ({
isModalOpen,
modalType,
processingAdding,
processingDeleting,
processingUpdating,
staticLeases,
cidr,
rangeStart,
Expand All @@ -31,7 +38,12 @@ const StaticLeases = ({

const handleSubmit = (data) => {
const { mac, ip, hostname } = data;
dispatch(addStaticLease({ mac, ip, hostname }));

if (modalType === MODAL_TYPE.EDIT_LEASE) {
dispatch(updateStaticLease({ mac, ip, hostname }));
} else {
dispatch(addStaticLease({ mac, ip, hostname }));
}
};

const handleDelete = (ip, mac, hostname = '') => {
Expand Down Expand Up @@ -80,19 +92,35 @@ const StaticLeases = ({
Cell: (row) => {
const { ip, mac, hostname } = row.original;

return <div className="logs__row logs__row--center">
<button
return (
<div className="logs__row logs__row--center">
<button
type="button"
className="btn btn-icon btn-icon--green btn-outline-secondary btn-sm"
title={t('delete_table_action')}
disabled={processingDeleting}
className="btn btn-icon btn-outline-primary btn-sm mr-2"
onClick={() => dispatch(toggleLeaseModal({
type: MODAL_TYPE.EDIT_LEASE,
config: { ip, mac, hostname },
}))}
disabled={processingUpdating}
title={t('edit_table_action')}
>
<svg className="icons icon12">
<use xlinkHref="#edit" />
</svg>
</button>
<button
type="button"
className="btn btn-icon btn-outline-secondary btn-sm"
onClick={() => handleDelete(ip, mac, hostname)}
>
<svg className="icons">
<use xlinkHref="#delete"/>
</svg>
</button>
</div>;
disabled={processingDeleting}
title={t('delete_table_action')}
>
<svg className="icons icon12">
<use xlinkHref="#delete" />
</svg>
</button>
</div>
);
},
},
]}
Expand All @@ -105,6 +133,7 @@ const StaticLeases = ({
/>
<Modal
isModalOpen={isModalOpen}
modalType={modalType}
handleSubmit={handleSubmit}
processingAdding={processingAdding}
cidr={cidr}
Expand All @@ -119,8 +148,10 @@ const StaticLeases = ({
StaticLeases.propTypes = {
staticLeases: PropTypes.array.isRequired,
isModalOpen: PropTypes.bool.isRequired,
modalType: PropTypes.string.isRequired,
processingAdding: PropTypes.bool.isRequired,
processingDeleting: PropTypes.bool.isRequired,
processingUpdating: PropTypes.bool.isRequired,
cidr: PropTypes.string.isRequired,
rangeStart: PropTypes.string,
rangeEnd: PropTypes.string,
Expand Down
5 changes: 5 additions & 0 deletions client/src/components/Settings/Dhcp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ const Dhcp = () => {
isModalOpen,
processingAdding,
processingDeleting,
processingUpdating,
processingDhcp,
v4,
v6,
interface_name: interfaceName,
enabled,
dhcp_available,
interfaces,
modalType,
} = useSelector((state) => state.dhcp, shallowEqual);

const interface_name = useSelector(
Expand Down Expand Up @@ -273,8 +275,11 @@ const Dhcp = () => {
<StaticLeases
staticLeases={staticLeases}
isModalOpen={isModalOpen}
toggleModal={toggleModal}
modalType={modalType}
processingAdding={processingAdding}
processingDeleting={processingDeleting}
processingUpdating={processingUpdating}
cidr={cidr}
rangeStart={dhcp?.values?.v4?.range_start}
rangeEnd={dhcp?.values?.v4?.range_end}
Expand Down
1 change: 1 addition & 0 deletions client/src/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export const MODAL_TYPE = {
CHOOSE_FILTERING_LIST: 'CHOOSE_FILTERING_LIST',
ADD_REWRITE: 'ADD_REWRITE',
EDIT_REWRITE: 'EDIT_REWRITE',
EDIT_LEASE: 'EDIT_LEASE',
};

export const CLIENT_ID = {
Expand Down
15 changes: 14 additions & 1 deletion client/src/reducers/dhcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ const dhcp = handleActions(
const newState = {
...state,
isModalOpen: !state.isModalOpen,
leaseModalConfig: payload,
modalType: payload?.type || '',
leaseModalConfig: payload?.config,
};
return newState;
},
Expand Down Expand Up @@ -175,6 +176,16 @@ const dhcp = handleActions(
};
return newState;
},

[actions.updateStaticLeaseRequest]: (state) => ({ ...state, processingUpdating: true }),
[actions.updateStaticLeaseFailure]: (state) => ({ ...state, processingUpdating: false }),
[actions.updateStaticLeaseSuccess]: (state) => {
const newState = {
...state,
processingUpdating: false,
};
return newState;
},
},
{
processing: true,
Expand All @@ -184,6 +195,7 @@ const dhcp = handleActions(
processingConfig: false,
processingAdding: false,
processingDeleting: false,
processingUpdating: false,
enabled: false,
interface_name: '',
check: null,
Expand All @@ -202,6 +214,7 @@ const dhcp = handleActions(
staticLeases: [],
isModalOpen: false,
leaseModalConfig: undefined,
modalType: '',
dhcp_available: false,
},
);
Expand Down
3 changes: 3 additions & 0 deletions internal/dhcpd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ type DHCPServer interface {
// RemoveStaticLease - remove a static lease
RemoveStaticLease(l *Lease) (err error)

// UpdateStaticLease updates IP, hostname of the lease.
UpdateStaticLease(l *Lease) (err error)

// FindMACbyIP returns a MAC address by the IP address of its lease, if
// there is one.
FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr)
Expand Down
Loading

0 comments on commit e305bd8

Please sign in to comment.