Skip to content

Commit

Permalink
Services: Captive Portal - code cleanup in session handling and prese…
Browse files Browse the repository at this point in the history
…ntation.
  • Loading branch information
AdSchellevis committed May 22, 2024
1 parent 00e3d6d commit 8ba454a
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ class AccessController extends ApiControllerBase
private function clientSession(string $zoneid)
{
$backend = new Backend();
$allClientsRaw = $backend->configdpRun(
"captiveportal list_clients",
[$zoneid, 'json']
);
$allClientsRaw = $backend->configdpRun("captiveportal list_clients", [$zoneid]);
$allClients = json_decode($allClientsRaw, true);
if ($allClients != null) {
// search for client by ip address
Expand Down Expand Up @@ -190,8 +187,7 @@ public function logonAction($zoneid = 0)
(string)$cpZone->zoneid,
$userName,
$clientIp,
$authServerName,
'json'
$authServerName
]
);
$CPsession = json_decode($CPsession, true);
Expand Down Expand Up @@ -248,10 +244,7 @@ public function logoffAction($zoneid = 0)
) {
// you can only disconnect a connected client
$backend = new Backend();
$statusRAW = $backend->configdpRun(
"captiveportal disconnect",
[$zoneid, $clientSession['sessionId'], 'json']
);
$statusRAW = $backend->configdpRun("captiveportal disconnect", [$zoneid, $clientSession['sessionId']]);
$status = json_decode($statusRAW, true);
if ($status != null) {
$this->getLogger("captiveportal")->info(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* Copyright (C) 2015 Deciso B.V.
* Copyright (C) 2015-2024 Deciso B.V.
*
* All rights reserved.
*
Expand Down Expand Up @@ -50,27 +50,37 @@ public function listAction($zoneid = 0)
$mdlCP = new CaptivePortal();
$cpZone = $mdlCP->getByZoneID($zoneid);
if ($cpZone != null) {
$backend = new Backend();
$allClientsRaw = $backend->configdpRun(
"captiveportal list_clients",
array($cpZone->zoneid, 'json')
);
$allClients = json_decode($allClientsRaw ?? '', true);

return $allClients;
$allClientsRaw = (new Backend())->configdpRun("captiveportal list_clients", [$cpZone->zoneid]);
return json_decode($allClientsRaw ?? '', true);
} else {
// illegal zone, return empty response
return array();
return [];
}
}

/**
* search through connected clients
*/
public function searchAction()
{
$this->sessionClose();
$selected_zones = $this->request->get('selected_zones');
$records = json_decode((new Backend())->configdRun("captiveportal list_clients") ?? '', true);

$response = $this->searchRecordsetBase($records, null, 'userName', function ($key) use ($selected_zones) {
return empty($selected_zones) || in_array($key['zoneid'], $selected_zones);
});

return $response;
}

/**
* return list of available zones
* @return array available zones
*/
public function zonesAction()
{
$response = array();
$response = [];
$mdlCP = new CaptivePortal();
foreach ($mdlCP->zones->zone->iterateItems() as $zone) {
$response[(string)$zone->zoneid] = (string)$zone->description;
Expand All @@ -81,25 +91,24 @@ public function zonesAction()

/**
* disconnect a client
* @param string|int $zoneid zoneid
* @param string|int $zoneid zoneid (deprecated)
* @return array|mixed
*/
public function disconnectAction($zoneid = 0)
public function disconnectAction($zoneid = '')
{
if ($this->request->isPost() && $this->request->hasPost('sessionId')) {
$backend = new Backend();
$statusRAW = $backend->configdpRun(
$statusRAW = (new Backend())->configdpRun(
"captiveportal disconnect",
array($zoneid, $this->request->getPost('sessionId'), 'json')
[$this->request->getPost('sessionId')]
);
$status = json_decode($statusRAW, true);
$status = json_decode($statusRAW ?? '', true);
if ($status != null) {
return $status;
} else {
return array("status" => "Illegal response");
return ["status" => "Illegal response"];
}
}
return array();
return [];
}

/**
Expand All @@ -109,7 +118,7 @@ public function disconnectAction($zoneid = 0)
*/
public function connectAction($zoneid = 0)
{
$response = array();
$response = [];

if ($this->request->isPost()) {
// Get details from POST request
Expand All @@ -136,13 +145,12 @@ public function connectAction($zoneid = 0)
$backend = new Backend();
$CPsession = $backend->configdpRun(
"captiveportal allow",
array(
[
(string)$cpZone->zoneid,
$userName,
$clientIp,
'API',
'json'
)
'API'
]
);

// Only return session if configd returned a valid json response
Expand Down
166 changes: 63 additions & 103 deletions src/opnsense/mvc/app/views/OPNsense/CaptivePortal/clients.volt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{#

OPNsense® is Copyright © 20142015 by Deciso B.V.
OPNsense® is Copyright © 20142024 by Deciso B.V.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
Expand Down Expand Up @@ -30,115 +30,75 @@ POSSIBILITY OF SUCH DAMAGE.
<script>

$( document ).ready(function() {
/**
* update zone list
*/
function updateZones() {
ajaxGet("/api/captiveportal/session/zones/", {}, function(data, status) {
if (status == "success") {
$('#cp-zones').html("");
$.each(data, function(key, value) {
$('#cp-zones').append($("<option></option>").attr("value", key).text(value));
});
$('.selectpicker').selectpicker('refresh');
// link on change event
$('#cp-zones').on('change', function(){
loadSessions();
});
// initial load sessions
loadSessions();
}
});
}

/**
* load sessions for selected zone, hook events
*/
function loadSessions() {
var zoneid = $('#cp-zones').find("option:selected").val();
var gridopt = {
ajax: false,
selection: true,
multiSelect: true,
formatters: {
"commands": function (column, row) {
return '<button type="button" class="btn btn-xs btn-default command-disconnect bootgrid-tooltip" title="{{ lang._('Disconnect') }}" data-row-id="' + row.sessionId + '"><span class="fa fa-trash-o fa-fw"></span></button>';
}
}
};
if ($("#grid-clients").hasClass('bootgrid-table')) {
$("#grid-clients").bootgrid('clear');
} else {
let grid_clients = $("#grid-clients").bootgrid(gridopt).on("loaded.rs.jquery.bootgrid", function(){
// hook disconnect button
grid_clients.find(".command-disconnect").on("click", function(e) {
var zoneid = $('#cp-zones').find("option:selected").val();
var sessionId=$(this).data("row-id");
stdDialogConfirm('{{ lang._('Confirm disconnect') }}',
'{{ lang._('Do you want to disconnect the selected client?') }}',
'{{ lang._('Yes') }}', '{{ lang._('Cancel') }}', function () {
ajaxCall("/api/captiveportal/session/disconnect/" + zoneid + '/',
{'sessionId': sessionId}, function(data,status){
// reload grid after delete
loadSessions();
});
});
});
$(this).find(".bootgrid-tooltip").each(function (index) {
$(this).tooltip();
});
ajaxGet("/api/captiveportal/session/zones/", {}, function(data, status) {
if (status == "success") {
$('#zone-selection').empty();
$.each(data, function(key, value) {
$('#zone-selection').append($("<option></option>").attr("value", key).text(value));
});
$('.selectpicker').selectpicker('refresh');
}
ajaxGet("/api/captiveportal/session/list/"+zoneid+"/", {}, function(data, status) {
if (status == "success") {
// format records (our bootgrid doesn't like null and expects moment for datetime)
let table = [];
for (var i = 0; i < data.length; i++) {
let record = {};
$.each(data[i], function(key, value) {
record[key] = value !== null ? value : "";
});

$("#zone-selection").on("changed.bs.select", function (e) {
$("#grid-clients").bootgrid('reload');
});
$("#grid-clients").UIBootgrid({
search:'/api/captiveportal/session/search/',
datakey: 'sessionId',
commands: {
disconnect: {
title: "{{ lang._('Disconnect') }}",
method: function() {
let sessid = $(this).data("row-id") !== undefined ? $(this).data("row-id") : '';
stdDialogConfirm(
"{{ lang._('Confirm disconnect') }}",
"{{ lang._('Do you want to disconnect the selected client?') }}",
"{{ lang._('Yes') }}",
"{{ lang._('Cancel') }}",
function () {
ajaxCall("/api/captiveportal/session/disconnect",{'sessionId': sessid}, function(data,status){
$("#grid-clients").bootgrid('reload');
});
});
table.push(record);
}
$("#grid-clients").bootgrid('append', table);
// hide actionBar on mobile
$('.actionBar').addClass('hidden-xs hidden-sm');
},
classname: 'fa fa-trash-o fa-fw',
sequence: 1,
}
},
options: {
selection: false,
multiSelect: false,
useRequestHandlerOnGet: true,
requestHandler: function(request) {
request['selected_zones'] = $("#zone-selection").val();
return request;
}
});
}
}
});

// init with first selected zone
updateZones();
$("#zone-selection-wrapper").detach().prependTo('#grid-clients-header > .row > .actionBar > .actions');
});
</script>

<div class="content-box">
<div class="content-box-main">
<div class="table-responsive">
<div class="col-sm-12">
<div class="pull-right">
<select id="cp-zones" class="selectpicker" data-width="200px"></select>
<hr/>
</div>
</div>
<div>
<table id="grid-clients" class="table table-condensed table-hover table-striped table-responsive">
<thead>
<tr>
<th data-column-id="sessionId" data-type="string" data-identifier="true" data-visible="false">{{ lang._('Session') }}</th>
<th data-column-id="userName" data-type="string">{{ lang._('Username') }}</th>
<th data-column-id="macAddress" data-type="string" data-css-class="hidden-xs hidden-sm" data-header-css-class="hidden-xs hidden-sm">{{ lang._('MAC address') }}</th>
<th data-column-id="ipAddress" data-type="string" data-css-class="hidden-xs hidden-sm" data-header-css-class="hidden-xs hidden-sm">{{ lang._('IP address') }}</th>
<th data-column-id="startTime" data-type="datetime">{{ lang._('Connected since') }}</th>
<th data-column-id="commands" data-searchable="false" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
</tfoot>
</table>
</div>
</div>
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs"></ul>
<div class="tab-content content-box col-xs-12 __mb">
<div class="btn-group" id="zone-selection-wrapper">
<select class="selectpicker" multiple="multiple" data-live-search="true" id="zone-selection" data-width="auto" title="{{ lang._('All Zones') }}">
</select>
</div>
<table id="grid-clients" class="table table-condensed table-hover table-striped table-responsive">
<thead>
<tr>
<th data-column-id="sessionId" data-type="string" data-identifier="true" data-visible="false">{{ lang._('Session') }}</th>
<th data-column-id="userName" data-type="string">{{ lang._('Username') }}</th>
<th data-column-id="macAddress" data-type="string" data-css-class="hidden-xs hidden-sm" data-header-css-class="hidden-xs hidden-sm">{{ lang._('MAC address') }}</th>
<th data-column-id="ipAddress" data-type="string" data-css-class="hidden-xs hidden-sm" data-header-css-class="hidden-xs hidden-sm">{{ lang._('IP address') }}</th>
<th data-column-id="startTime" data-type="datetime">{{ lang._('Connected since') }}</th>
<th data-column-id="commands" data-searchable="false" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
Loading

0 comments on commit 8ba454a

Please sign in to comment.