@@ -733,18 +733,20 @@ sub certificate_dns_names {
|
||
| 733 | 733 |
|
| 734 | 734 |
sub upsert_host {
|
| 735 | 735 |
my ($client, $payload) = @_; |
| 736 |
- my $id = clean_id($payload->{id} || '');
|
|
| 737 |
- return send_json($client, 400, { error => 'invalid_id' }) unless $id;
|
|
| 738 |
- |
|
| 739 | 736 |
my $ip = canonical_ip($payload); |
| 740 | 737 |
return send_json($client, 400, { error => 'missing_ip' }) unless $ip;
|
| 741 | 738 |
|
| 742 | 739 |
my $fqdn = canonical_host_fqdn($payload); |
| 743 | 740 |
return send_json($client, 400, { error => 'missing_fqdn' }) unless $fqdn;
|
| 741 |
+ my $id = clean_id($payload->{id} || '');
|
|
| 742 |
+ $id = clean_id($fqdn) unless length $id; |
|
| 744 | 743 |
my @aliases = clean_alias_names($payload); |
| 745 | 744 |
|
| 746 | 745 |
my $registry = load_registry(); |
| 747 |
- my ($existing_host) = grep { ($_->{id} || '') eq $id } @{ $registry->{hosts} || [] };
|
|
| 746 |
+ my ($existing_host) = grep {
|
|
| 747 |
+ (($_->{id} || '') eq $id) || (($_->{fqdn} || '') eq $fqdn)
|
|
| 748 |
+ } @{ $registry->{hosts} || [] };
|
|
| 749 |
+ $id = clean_id($existing_host->{id} || $fqdn) if $existing_host && !length($payload->{id} || '');
|
|
| 748 | 750 |
my @vhosts = defined $payload->{vhosts}
|
| 749 | 751 |
? clean_vhost_names($payload) |
| 750 | 752 |
: ($existing_host ? declared_vhost_names($existing_host) : ()); |
@@ -2606,7 +2608,7 @@ sub upsert_host_to_db {
|
||
| 2606 | 2608 |
my $now = iso_now(); |
| 2607 | 2609 |
my $fqdn = canonical_host_fqdn($host); |
| 2608 | 2610 |
return '' unless $fqdn; |
| 2609 |
- my $legacy_id = clean_id($host->{id} || legacy_id_from_fqdn($fqdn));
|
|
| 2611 |
+ my $legacy_id = clean_id($host->{id} || $fqdn);
|
|
| 2610 | 2612 |
my $status = clean_scalar($host->{status} || 'active');
|
| 2611 | 2613 |
my $ip = canonical_ip($host); |
| 2612 | 2614 |
my $monitoring = clean_scalar($host->{monitoring} || 'pending');
|
@@ -2994,7 +2996,12 @@ sub set_schema_meta {
|
||
| 2994 | 2996 |
sub fqdn_for_legacy_id {
|
| 2995 | 2997 |
my ($dbh, $legacy_id) = @_; |
| 2996 | 2998 |
return '' unless length($legacy_id || ''); |
| 2997 |
- my ($fqdn) = $dbh->selectrow_array('SELECT fqdn FROM hosts WHERE legacy_id = ?', undef, $legacy_id);
|
|
| 2999 |
+ my ($fqdn) = $dbh->selectrow_array( |
|
| 3000 |
+ 'SELECT fqdn FROM hosts WHERE legacy_id = ? OR fqdn = ?', |
|
| 3001 |
+ undef, |
|
| 3002 |
+ $legacy_id, |
|
| 3003 |
+ $legacy_id, |
|
| 3004 |
+ ); |
|
| 2998 | 3005 |
return $fqdn || ''; |
| 2999 | 3006 |
} |
| 3000 | 3007 |
|
@@ -3772,7 +3779,7 @@ sub app_html {
|
||
| 3772 | 3779 |
</div> |
| 3773 | 3780 |
</div> |
| 3774 | 3781 |
<form id="host-form" class="grid"> |
| 3775 |
- <label>Legacy ID<input name="id" required></label> |
|
| 3782 |
+ <input type="hidden" name="id"> |
|
| 3776 | 3783 |
<label>FQDN<input name="fqdn" required></label> |
| 3777 | 3784 |
<label>Status<select name="status"><option>active</option><option>planned</option><option>retired</option></select></label> |
| 3778 | 3785 |
<label>IP<input name="ip" required></label> |
@@ -4561,6 +4568,16 @@ sub app_html {
|
||
| 4561 | 4568 |
return name.endsWith(suffix) ? name.slice(0, -suffix.length) : ''; |
| 4562 | 4569 |
} |
| 4563 | 4570 |
|
| 4571 |
+ function normalizeHostFqdn(name) {
|
|
| 4572 |
+ return String(name || '').trim().toLowerCase().replace(/\.$/, ''); |
|
| 4573 |
+ } |
|
| 4574 |
+ |
|
| 4575 |
+ function syncHostFormId() {
|
|
| 4576 |
+ if (!hostField('id').value) {
|
|
| 4577 |
+ hostField('id').value = normalizeHostFqdn(hostField('fqdn').value || '');
|
|
| 4578 |
+ } |
|
| 4579 |
+ } |
|
| 4580 |
+ |
|
| 4564 | 4581 |
function hostByFqdn(fqdn) {
|
| 4565 | 4582 |
fqdn = String(fqdn || '').toLowerCase(); |
| 4566 | 4583 |
return state.hosts.find(host => String(host.fqdn || '').toLowerCase() === fqdn) || null; |
@@ -4858,10 +4875,11 @@ sub app_html {
|
||
| 4858 | 4875 |
if (!await ensureAuthenticated('Autentifica-te inainte de adaugarea unui host.')) return;
|
| 4859 | 4876 |
if (!canSwitchHostEditor('__new__')) return;
|
| 4860 | 4877 |
resetHostForm(true); |
| 4861 |
- activateHostForm('New host', 'new', '__new__', 'id');
|
|
| 4878 |
+ hostField('id').value = '';
|
|
| 4879 |
+ activateHostForm('New host', 'new', '__new__', 'fqdn');
|
|
| 4862 | 4880 |
} |
| 4863 | 4881 |
|
| 4864 |
- function activateHostForm(title, mode, target, focusField = 'id', scroll = true) {
|
|
| 4882 |
+ function activateHostForm(title, mode, target, focusField = 'fqdn', scroll = true) {
|
|
| 4865 | 4883 |
hostFormMode = mode || 'new'; |
| 4866 | 4884 |
hostEditorTarget = target || ''; |
| 4867 | 4885 |
hostFormTitle.textContent = title || 'New host'; |
@@ -5162,6 +5180,7 @@ sub app_html {
|
||
| 5162 | 5180 |
hostForm.addEventListener('submit', async (event) => {
|
| 5163 | 5181 |
event.preventDefault(); |
| 5164 | 5182 |
if (!await ensureAuthenticated('Autentifica-te inainte de salvare. Modificarile raman in formular.')) return;
|
| 5183 |
+ syncHostFormId(); |
|
| 5165 | 5184 |
setHostFormBusy(true); |
| 5166 | 5185 |
setHostFormMessage('Saving...');
|
| 5167 | 5186 |
try {
|
@@ -5182,12 +5201,13 @@ sub app_html {
|
||
| 5182 | 5201 |
setHostFormMessage('Complete the required host fields before saving.', true);
|
| 5183 | 5202 |
}, true); |
| 5184 | 5203 |
|
| 5185 |
- hostForm.addEventListener('input', () => {
|
|
| 5204 |
+ hostForm.addEventListener('input', (event) => {
|
|
| 5205 |
+ if (hostFormMode === 'new' && event.target && event.target.name === 'fqdn') syncHostFormId(); |
|
| 5186 | 5206 |
if (hostFormMessage.classList.contains('error')) clearHostFormMessage();
|
| 5187 | 5207 |
}); |
| 5188 | 5208 |
|
| 5189 | 5209 |
deleteHostButton.addEventListener('click', async () => {
|
| 5190 |
- const id = hostField('id').value;
|
|
| 5210 |
+ const id = hostField('id').value || normalizeHostFqdn(hostField('fqdn').value || '');
|
|
| 5191 | 5211 |
if (!id || !confirm(`Delete ${id}?`)) return;
|
| 5192 | 5212 |
setHostFormBusy(true); |
| 5193 | 5213 |
setHostFormMessage('Deleting...');
|