Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/adr/0038-a-group-grants-it-does-not-copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,11 @@ and the third is a deliberate departure from the units table.
default and `Group::appendSnapinSequence()` numbers them afterward -- the
same mechanism, for the same reason, as its host-side twin.

- **The imperative controls are marked deprecated, not removed.** Decision 10
- **The imperative controls are removed.** *(Updated: the deprecation shipped
in #1647 and the removal in unit F, once fog-plugins #36 gave `location` and
`ou` the same mass-edit seam the core fields use. Seven controls went, not
six -- the group Active Directory card pushed to member hosts too and was
missed when the notices were added.)* Decision 10
says the order is: mass edit ships, the imperative tabs are marked
deprecated in the UI and the docs, they are removed in a later release. The
units table entry for unit E said "removal of the imperative tabs", which
Expand Down
1 change: 1 addition & 0 deletions docs/development/group-split.md
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ serialize through conflicts anyway.
| D3 | Group list "grants" column | `Router/Route.php`, `Pages/GroupManagement.php`, JS | D1 | **merged** (#1643) |
| E | Group page rework: `Group::addSnapin`/`addPrinter`/`addModule` become grants, the tri-state coverage machinery goes, the imperative controls are marked deprecated | `Items/Group*Association.php`, `Items/Group.php`, `Pages/GroupManagement.php`, JS | **C5 proven** (Decision 10), D, M5 | **merged** (#1647) |
| E1 | UNKNOWN-4's server half simulated against the real endpoint: revoking a grant removes only the granted printers | `tests/printer-grants-reach-the-client.test.php` | E | **merged** (#1648) |
| F | Decision 10's last step: the group page's imperative controls REMOVED, after fog-plugins #36 gave `location` and `ou` the same seam | `Pages/GroupManagement.php`, `fog.group.edit.js`, fog-plugins | E, and fog-plugins #36 | **merged** (#PENDING) |
| E2 | `groups.groupOrder` made settable -- step 404 added the column and the resolver read it, but nothing could ever write it | `Items/Group.php`, `Pages/GroupManagement.php` | E | **merged** (#1649) |

**Two bugs in C5's own surface were found and fixed while D was landing**,
Expand Down
4 changes: 3 additions & 1 deletion docs/plugin-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,9 @@ neither covers: changing a value across a set. `HOST_MASSEDIT_*` is that seam

It is why `location` and `ou` each shipped a whole second hook file whose only
job was to set one value across a group's members — and those files always
clobbered, because there was no way to say *leave this host alone*.
clobbered, because there was no way to say *leave this host alone*. Both were
converted to this seam in fog-plugins #36 and are the worked example to copy:
`AddLocationHost::massEditFields()` / `massEditApply()`.

**Contribute a field** — fired when the Mass Edit form is built, and again
when it is applied, with the same arguments both times so the two can never
Expand Down
26 changes: 16 additions & 10 deletions docs/release/1.6.0-release-notes.DRAFT.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,18 +310,24 @@ pre-upgrade *dump* — it is not a schema rollback.
in that order. **Default printer** is one of the granted printers, and a
host that has chosen its own default keeps it.

- **The group page's push-to-all controls are deprecated and now say so.**
Setting an image, kernel, product key, AD details, printer level, screen
resolution, auto-logout or hostname enforcement from a group applies the
value **once**, to whichever hosts are members at that moment. A host added
afterward does not get it; a host removed keeps it. That has always been
true and was never visible. Each of those cards now carries a notice saying
so and pointing at **Edit selected hosts** on the Hosts list, which does the
same job over any selection and can be repeated. They still work exactly as
before in this release, and are removed in a later one.
- **The group page's push-to-all controls are gone.** Setting an image,
kernel, kernel arguments, init, primary disk, product key, BIOS/EFI exit
type, AD details, printer level, screen resolution, auto-logout or hostname
enforcement from a group applied the value **once**, to whichever hosts were
members at that moment. A host added afterward did not get it; a host
removed kept it. That was always true and was never visible.

Every one of those settings is now edited from **Edit selected hosts** on
the Hosts list, which does the same job over any selection you choose, can
be repeated, and can say *leave this host alone* -- a state the group cards
had no way to express. Nothing is lost: the mass edit covers all of them.

The `location` and `ou` plugins each shipped a group tab doing the same
thing, with the same two defects. Both now contribute to the host mass edit
instead, so **Location** and **OU** appear there beside the core fields.

Power Management is not affected -- it creates tasks rather than copying a
value.
value, so it stays on the group page.

- **The host list shows which groups a host is in, and you can search on
them.** A new Groups column carries one chip per group, each a link to that
Expand Down
266 changes: 0 additions & 266 deletions packages/web/management/js/fog/group/fog.group.edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,6 @@
});
});

// ---------------------------------------------------------------
// IMAGE TAB
var groupImageUpdateBtn = $('#group-image-send');

function disableImageButtons(disable) {
groupImageUpdateBtn.prop('disabled', disable);
}

groupImageUpdateBtn.on('click', function(e) {
e.preventDefault();
disableImageButtons(true);
var method = $(this).attr('method'),
action = $(this).attr('action'),
image = $('#image option:selected').val(),
opts = {
confirmimage: 1,
image: image
};
$.apiCall(method,action,opts,function(err) {
disableImageButtons(false);
if (err) {
return;
}
});
});

// ---------------------------------------------------------------
// TASKS TAB
var taskItem = $('.taskitem'),
Expand Down Expand Up @@ -302,26 +276,6 @@
});
});

// Config area
var groupPrinterConfigBtn = $('#printer-config-send');

groupPrinterConfigBtn.on('click', function(e) {
e.preventDefault();
groupPrinterConfigBtn.prop('disabled', true);
var method = $(this).attr('method'),
action = $(this).attr('action'),
opts = {
confirmlevelup: 1,
level: $('.checked input[name="level"]').val()
};
$.apiCall(method,action,opts,function(err) {
groupPrinterConfigBtn.prop('disabled', false);
if (err) {
return;
}
});
});

// ---------------------------------------------------------------
// SNAPINS TAB
// Association area
Expand Down Expand Up @@ -459,226 +413,6 @@
]
});

// Display manager area
var groupModuleDisplaymanBtn = $('#group-displayman-send'),
groupModuleDisplayForm = $('#group-displayman-form');

function disableModuleDisplayButtons(disable) {
groupModuleDisplaymanBtn.prop('disabled', disable);
}

groupModuleDisplayForm.on('submit', function(e) {
e.preventDefault();
});

groupModuleDisplaymanBtn.on('click', function(e) {
e.preventDefault();
var method = $(this).attr('method'),
action = $(this).attr('action'),
opts = {
confirmdisplaysend: 1,
x: $('#x').val(),
y: $('#y').val(),
r: $('#r').val()
};
disableModuleDisplayButtons(true);
$.apiCall(method,action,opts,function(err) {
disableModuleDisplayButtons(false);
});
});

// Auto log out area
var groupModuleAloBtn = $('#group-alo-send'),
groupModuleAloForm = $('#group-alo-form');

function disableModuleAloButtons(disable) {
groupModuleAloBtn.prop('disabled', disable);
}

groupModuleAloBtn.on('click', function(e) {
e.preventDefault();
disableModuleAloButtons(true);
var method = $(this).attr('method'),
action = $(this).attr('action'),
opts = {
confirmalosend: 1,
tme: $('#tme').val()
};
$.apiCall(method,action,opts,function(err) {
disableModuleAloButtons(false);
// Blank is a no-op server-side (no-clobber), and a failure left the
// members alone -- in neither case did anything move.
var raw = $.trim(String(opts.tme));
if (err || raw === '') {
return;
}
// Mirror groupModulePost(): (int) the value, and anything below the
// minimum saves as 0 (disabled). The threshold rides in on
// data-alo-min from GroupManagement::ALO_MIN_MINUTES rather than
// being repeated here, so the two cannot disagree.
var hint = $('#alo-shared-hint'),
mins = parseInt(raw, 10);
if (isNaN(mins) || mins < parseInt(hint.data('alo-min'), 10)) {
mins = 0;
}
hint.text(
hint.data('hosts-label') + ' ' + (
mins === 0 ?
hint.data('default-label') :
mins + ' ' + hint.data('min-label')
)
);
// Same reasoning as the enforce select: the field is a pending
// action (blank = leave alone), not a display of the current value,
// which the hint above now carries. Leaving the number in it reads
// as a change still queued.
$('#tme').val('');
});
});

// Host enforce ad join reboot and hostname changes area
var groupModuleEnforceBtn = $('#group-enforce-send'),
groupModuleEnforceForm = $('#group-enforce-form');

function disableModuleEnforceButtons(disable) {
groupModuleEnforceBtn.prop('disabled', disable);
}

groupModuleEnforceForm.on('submit', function(e) {
e.preventDefault();
});

groupModuleEnforceBtn.on('click', function(e) {
e.preventDefault();
disableModuleEnforceButtons(true);
var method = $(this).attr('method'),
action = $(this).attr('action'),
opts = {
confirmenforcesend: 1,
// #enforce is a tri-state <select> here ('' = no change,
// '1'/'0' = force on every host), matching #adEnabled above.
// This read was left over from when it was a checkbox: .checked
// is undefined on a <select>, so the ternary posted 0 for every
// choice -- "Enable on all hosts" disabled them instead, and
// "No change" clobbered the whole group. Send the raw value and
// let groupModulePost() decide; it already ignores ''.
enforce: $('#enforce').val()
};
$.apiCall(method,action,opts,function(err) {
disableModuleEnforceButtons(false);
// '' was a no-op server-side, so nothing moved; a failure leaves the
// members as they were. Only a successful '1'/'0' changes state.
if (err || (opts.enforce !== '1' && opts.enforce !== '0')) {
return;
}
// Every member was just forced to the same value, so the readout is
// known -- no round trip needed. Translated text comes from the
// server via data-*; this only chooses between them.
var hint = $('#enforce-shared-hint');
hint.text(
hint.data('hosts-label') + ' ' + (
opts.enforce === '1' ?
hint.data('enabled-label') :
hint.data('disabled-label')
)
);
// The select is a pending action, not a value display. Leaving it
// armed makes the card claim a change is still queued when it has
// already been applied, so put it back to the no-clobber default.
$('#enforce').val('');
});
});

// ACTIVE DIRECTORY TAB
var ADForm = $('#active-directory-form'),
ADFormBtn = $('#ad-send'),
ADClearBtn = $('#ad-clear'),
ADJoinDomain = $('#adEnabled');

// #adEnabled is a tri-state <select> in group mode (No change/Enable/
// Disable). Populate the blank fields from the AD defaults only when the
// admin actively selects Enable -- never just from existing state.
ADJoinDomain.on('change', function(e) {
if ($(this).val() !== '1') {
return;
}
var indomain = $('#adDomain'),
inou = $('#adOU'),
inuser = $('#adUsername'),
inpass = $('#adPassword');
if (indomain.val() && inou.val() && inuser.val() && inpass.val()) {
return;
}
Pace.ignore(function() {
$.get('../management/index.php?sub=adInfo', function(data) {
if (!indomain.val()) {
indomain.val(data.domainname);
}
if (!inou.val()) {
inou.val(data.ou)
}
if (!inuser.val()) {
inuser.val(data.domainuser);
}
if (!inpass.val()) {
inpass.val(data.domainpass);
}
}, 'json');
});
});

ADForm.on('submit',function(e) {
e.preventDefault();
});
ADFormBtn.on('click',function() {
ADFormBtn.prop('disabled', true);
ADClearBtn.prop('disabled', true);
ADForm.processForm(function(err) {
ADFormBtn.prop('disabled', false);
ADClearBtn.prop('disabled', false);
});
});
ADClearBtn.on('click',function() {
ADClearBtn.prop('disabled', true);
ADFormBtn.prop('disabled', true);

var restoreMap = [];
ADForm.find('input[type="text"], input[type="password"], textarea').each(function(i, e) {
restoreMap.push({checkbox: false, e: e, val: $(e).val()});
$(e).val('');
$(e).prop('disabled', true);
});
ADForm.find('input[type=checkbox]').each(function(i, e) {
restoreMap.push({checkbox: true, e: e, val: $(e)[0].checked});
$(e).prop('checked', false).trigger('change');
$(e).prop('disabled', true);
});

ADForm.find('input[type=text], input[type=password], textarea').val('');
ADForm.find('input[type=checkbox]').prop('checked', false).trigger('change');
// Reset the tri-state Domain Joining select back to "No change".
$('#adEnabled').val('');

ADForm.processForm(function(err) {
ADClearBtn.prop('disabled', false);
ADFormBtn.prop('disabled', false);
for (var i = 0; i < restoreMap.length; i++) {
field = restoreMap[i];
if (field.checkbox) {
if (err) {
$(field.e).prop('checked', !!field.val).trigger('change');
}
$(field.e).prop('disabled', false);
} else {
if (err) {
$(field.e).val(field.val);
}
$(field.e).prop('disabled', false);
}
}
});
});

// ---------------------------------------------------------------
// POWER MANAGEMENT TAB
var powermanagementForm = $('#group-powermanagement-cron-form'),
Expand Down
Loading
Loading