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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The plugins that ship with [FOG Project](https://github.com/FOGProject/fogproject).
One repository, one release, per-plugin versions in each manifest.

This is the source of truth for the 15 bundled plugins. The FOG build pins a
This is the source of truth for the 16 bundled plugins. The FOG build pins a
revision of this repository and lays its contents into
`packages/web/lib/plugins/` in the tarball.

Expand Down Expand Up @@ -87,6 +87,7 @@ the rest.
| Plugin | Version | What it does |
|---|---|---|
| `capone` | 1.6.0 | Automation plugin — image a host straight from PXE without registering it |
| `directorygroups` | 1.6.0 | Group hosts by Active Directory OU, across one or more domains |
| `helloworld` | 1.6.0 | Skeleton example: config, model, manager, page, hooks, JS |
| `ldap` | 1.6.0 | Authenticate FOG users against an LDAP or AD directory |
| `location` | 1.6.0 | Serve images from the storage node nearest a host — multi-site installs |
Expand Down
32 changes: 32 additions & 0 deletions directorygroups/config/plugin.config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/**
* Plugin configuration file.
*
* PHP version 5
*
* @category Config
* @package FOGProject
* @author Tom Elliott <tommygunsster@gmail.com>
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link https://fogproject.org
*/
/**
* Plugin configuration file.
*
* @category Config
* @package FOGProject
* @author Tom Elliott <tommygunsster@gmail.com>
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link https://fogproject.org
*/
$fog_plugin = [];
$fog_plugin['name'] = 'directorygroups';
$fog_plugin['description'] = _(
'Directory Groups: group hosts by Active Directory OU, across one or '
. 'more domains.'
);
$fog_plugin['menuicon'] = 'fas fa-folder-tree fa-fw';
$fog_plugin['version'] = '1.6.0';
$fog_plugin['fog_min'] = '1.6.0';
$fog_plugin['author'] = 'Tom Elliott';
$fog_plugin['homepage'] = 'https://fogproject.org';
3 changes: 3 additions & 0 deletions directorygroups/js/fog.directorydomain.add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(function($) {
$('#directorydomain-create-form').wireCreateForm();
})(jQuery);
109 changes: 109 additions & 0 deletions directorygroups/js/fog.directorydomain.edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
$(function() {
// ---------------------------------------------------------------
// GENERAL TAB
$.registerGeneralTab({
nameInputSel: '#name',
formSel: '#directorydomain-general-form'
});

// ---------------------------------------------------------------
// ORGANIZATIONAL UNITS TAB
//
// The whole tree, client side: listOUs() already read every page of it,
// so search and scroll need no further round trip. Indented by depth
// and kept in the server's root-first order, so it reads as a tree.
var table = $('#directorydomain-ous-table'),
sendBtn = $('#directorydomain-ous-send'),
loaded = false,
dt;

function load() {
if (loaded || !table.length) {
return;
}
loaded = true;
$.get(
'../management/index.php?node=directorydomain&sub=getOUs&id='
+ table.data('domain-id'),
function(res) {
dt = table.DataTable({
data: res.data,
ordering: false,
pageLength: 25,
columns: [
{data: 'dn'},
{data: 'name'},
{data: 'dn'},
{data: 'groupID'}
],
columnDefs: [
{
targets: 0,
searchable: false,
render: function(data, type, row) {
if (row.groupID) {
return '';
}
return '<input type="checkbox" class="ou-pick" value="'
+ $.escapeHtml(data) + '"/>';
}
},
{
targets: 1,
render: function(data, type, row) {
if (type !== 'display') {
return data;
}
return '<span style="padding-left:' + (row.depth * 1.5)
+ 'em"><i class="fas fa-folder"></i> '
+ $.escapeHtml(data) + '</span>';
}
},
{
targets: 3,
searchable: false,
render: function(data) {
if (!data) {
return '';
}
return '<a href="../management/index.php?node=directorygroups&sub=edit&id='
+ data + '">' + $.escapeHtml(String(data)) + '</a>';
}
}
]
});
},
'json'
).fail(function(jqXHR) {
loaded = false;
$.notifyFromAPI(jqXHR.responseJSON, jqXHR);
});
}

// Fetched when the tab is first shown, not with the page: a slow or
// unreachable directory must not hold up the General tab.
$('a[href="#directorydomain-ous"]').on('shown.bs.tab', load);
if (window.location.hash === '#directorydomain-ous') {
load();
}

sendBtn.on('click', function() {
if (!dt) {
return;
}
var ous = dt.$('input.ou-pick:checked').map(function() {
return this.value;
}).get();
sendBtn.prop('disabled', true);
$.apiCall('POST', table.data('update-url'), {ous: ous}, function(err) {
sendBtn.prop('disabled', false);
if (err) {
return;
}
dt.destroy();
table.find('tbody').remove();
loaded = false;
load();
});
});
});
14 changes: 14 additions & 0 deletions directorygroups/js/fog.directorydomain.export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(function($) {
// No bindPwd column: the export strips it (AddDirectoryGroupsAPI).
$('#directorydomain-export-table').registerExportTable([
{data: 'name'},
{data: 'description', visible: false},
{data: 'createdBy', visible: false},
{data: 'createdTime', visible: false},
{data: 'uri'},
{data: 'bindDN'},
{data: 'caCert', visible: false},
{data: 'baseDN'},
{data: 'ouBase', visible: false}
]);
})(jQuery);
18 changes: 18 additions & 0 deletions directorygroups/js/fog.directorydomain.list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(function($) {
$.registerListPage({
order: [
[0, 'asc']
],
columns: [
{data: 'mainlink'},
{data: 'uri'}
],
rowId: 'id',
columnDefs: [
{
responsivePriority: -1,
targets: 0
}
]
});
})(jQuery);
3 changes: 3 additions & 0 deletions directorygroups/js/fog.directorygroups.add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(function($) {
$('#directorygroups-create-form').wireCreateForm();
})(jQuery);
42 changes: 42 additions & 0 deletions directorygroups/js/fog.directorygroups.edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
$(function() {
// ---------------------------------------------------------------
// GENERAL TAB
$.registerGeneralTab({
nameInputSel: '#ou',
formSel: '#directorygroups-general-form'
});

// ---------------------------------------------------------------
// HOST TAB
var directorygroupsHostsTable = $.registerAssociationTab({
slug: 'directorygroups-host',
item: 'host',
sub: 'getHostsList',
columns: [
{data: 'name'},
{data: 'association'}
],
columnDefs: [
{
responsivePriority: -1,
// Aisle 097: this tab supplies its own column-0 render, so it
// bypasses the server-side escape in FOGController's mainLink
// formatter and concatenated the name in raw. Mitigated today
// only by isHostnameSafe() on the write side -- do not rely on
// that staying the sole gate.
render: function(data, type, row) {
return '<a href="../management/index.php?node=host&sub=edit&id='
+ row.id
+ '">'
+ $.escapeHtml(data)
+ '</a>';
},
targets: 0
}
]
});

if (Common.search && Common.search.length > 0) {
directorygroupsHostsTable.search(Common.search).draw();
}
});
9 changes: 9 additions & 0 deletions directorygroups/js/fog.directorygroups.export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(function($) {
$('#directorygroups-export-table').registerExportTable([
{data: 'name'},
{data: 'description', visible: false},
{data: 'createdBy', visible: false},
{data: 'createdTime', visible: false},
{data: 'ou'}
]);
})(jQuery);
112 changes: 112 additions & 0 deletions directorygroups/js/fog.directorygroups.host.edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
(function($) {
// The whole tab -- Update wiring plus the create-and-associate button and
// modal -- is one shared helper (fog.common.js). These nine plugin tabs are
// the same card with a different noun, and each used to carry its own copy
// of the submit wiring.
$.registerSelectTab({
slug: 'host-directorygroups',
send: 'directorygroups-send',
node: 'directorygroups'
});
})(jQuery);
(function($) {
// ---------------------------------------------------------------
// ACTIVE DIRECTORY TAB: Browse Directory
//
// Lists a domain's OUs; a click on one fills the tab's Domain Name and
// Organizational Unit fields. The admin still clicks Update to save.
var browseBtn = $('#directorygroups-browse'),
modal = $('#directorygroups-browse-modal'),
domainSel = $('#directorygroups-browse-domain'),
table = $('#directorygroups-browse-table'),
domains = {},
dt;

if (!browseBtn.length) {
return;
}

function showDomain(id) {
if (dt) {
dt.destroy();
table.find('tbody').remove();
dt = null;
}
$.get(
'../management/index.php?node=directorydomain&sub=getOUs&id=' + id,
function(res) {
dt = table.DataTable({
data: res.data,
ordering: false,
pageLength: 25,
columns: [
{data: 'name'},
{data: 'dn'}
],
columnDefs: [
{
targets: 0,
render: function(data, type, row) {
if (type !== 'display') {
return data;
}
return '<span style="padding-left:' + (row.depth * 1.5)
+ 'em"><i class="fas fa-folder"></i> '
+ $.escapeHtml(data) + '</span>';
}
}
]
});
},
'json'
).fail(function(jqXHR) {
$.notifyFromAPI(jqXHR.responseJSON, jqXHR);
});
}

table.on('click', 'tbody tr', function() {
if (!dt) {
return;
}
var row = dt.row(this).data();
if (!row) {
return;
}
$('#adDomain').val(domains[domainSel.val()]);
$('#adOU').val(row.dn);
modal.modal('hide');
});

domainSel.on('change', function() {
showDomain(this.value);
});

browseBtn.on('click', function(e) {
e.preventDefault();
modal.modal('show');
if (domainSel.children().length) {
return;
}
$.get(
'../management/index.php?node=directorydomain&sub=getDomains',
function(res) {
var current = ($('#adDomain').val() || '').toLowerCase(),
pick = null;
$.each(res.data, function(i, d) {
domains[d.id] = d.name;
domainSel.append($('<option/>').val(d.id).text(d.name));
if (d.name.toLowerCase() === current) {
pick = d.id;
}
});
if (pick) {
domainSel.val(pick);
}
if (domainSel.val()) {
showDomain(domainSel.val());
}
},
'json'
);
});
})(jQuery);
3 changes: 3 additions & 0 deletions directorygroups/js/fog.directorygroups.import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Import form wiring is shared: wireImportForm() in fog.common.js activates for
// any page rendering #import-form/#import-send. Kept as a stub so the JS loader
// serves this file rather than falling back to fog.ou.list.js.
18 changes: 18 additions & 0 deletions directorygroups/js/fog.directorygroups.list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(function($) {
$.registerListPage({
order: [
[0, 'asc']
],
columns: [
{data: 'mainlink'},
{data: 'ou'}
],
rowId: 'id',
columnDefs: [
{
responsivePriority: -1,
targets: 0
}
]
});
})(jQuery);
Loading
Loading