root/trunk/wifidog-auth/wifidog/classes/NodeGroup.php @ 1435

Revision 1435, 23.2 KB (checked in by gbastien, 3 years ago)

Merged branch 'gbastien' for node group with the trunk:
* Added the concept of node group and hierarchy (in a not too clean way to start with, I will refactor the code before adding new functionalities to nodes and groups) (#246)
* Login and signup and logout script now receive the mac address as parameter (#675)
* Initial abuse control verification now made with the mac address (#676)

Line 
1<?php
2
3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5// +-------------------------------------------------------------------+
6// | WiFiDog Authentication Server                                     |
7// | =============================                                     |
8// |                                                                   |
9// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
10// | portal suite.                                                     |
11// +-------------------------------------------------------------------+
12// | PHP version 5 required.                                           |
13// +-------------------------------------------------------------------+
14// | Homepage:     http://www.wifidog.org/                             |
15// | Source Forge: http://sourceforge.net/projects/wifidog/            |
16// +-------------------------------------------------------------------+
17// | This program is free software; you can redistribute it and/or     |
18// | modify it under the terms of the GNU General Public License as    |
19// | published by the Free Software Foundation; either version 2 of    |
20// | the License, or (at your option) any later version.               |
21// |                                                                   |
22// | This program is distributed in the hope that it will be useful,   |
23// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
24// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
25// | GNU General Public License for more details.                      |
26// |                                                                   |
27// | You should have received a copy of the GNU General Public License |
28// | along with this program; if not, contact:                         |
29// |                                                                   |
30// | Free Software Foundation           Voice:  +1-617-542-5942        |
31// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
32// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
33// |                                                                   |
34// +-------------------------------------------------------------------+
35
36/**
37 * @package    WiFiDogAuthServer
38 * @author     Geneviève Bastien <gbastien@versatic.net>
39 * @version    Subversion $Id: Node.php 1419 2009-09-18 21:51:29Z gbastien $
40 * @link       http://www.wifidog.org/
41 */
42
43/**
44 * Load required classes
45 */
46require_once('classes/User.php');
47require_once('classes/Utils.php');
48require_once('classes/DateTimeWD.php');
49require_once('classes/HotspotGraphElement.php');
50
51/**
52 * Abstract a NodeGroup.  A Node group is a virtual entity that corresond to no physical machine or hotspot
53 *  A NodeGroup can have its own content and can be the parent element of other Nodes and/or NodeGroups
54 *
55 *
56 * @package    WiFiDogAuthServer
57 * @author     Geneviève Bastien <gbastien@versatic.net>
58 * @copyright  2005 Benoit Grégoire, Technologies Coeus inc.
59 */
60class NodeGroup implements GenericObject
61{
62    /** Object cache for the object factory (getObject())*/
63    private static $instanceArray = array();
64    private $_row;
65    private $mdB; /**< An AbstractDb instance */
66    private $id;
67    protected $_hotspotGraphElement;
68   
69    /**
70     * Defines a warning message
71     *
72     * @var string
73     *
74     * @access private
75     */
76    private $_warningMessage;
77
78    /** Instantiate a nodeGroup object
79     * @param $id The id of the requested node group
80     * @return a NodeGroup object, or null if there was an error
81     */
82    public static function &getObject($id)
83    {
84        if(!isset(self::$instanceArray[$id]))
85        {
86            self::$instanceArray[$id] = new self($id);
87        }
88        return self::$instanceArray[$id];
89    }
90
91    /** Free an instanciated object
92     * @param $id The id to free
93     * Thanks and so long for all the ram.
94     */
95    public static function freeObject($id)
96    {
97        if(isset(self::$instanceArray[$id]))
98        {
99            unset(self::$instanceArray[$id]);
100        }
101    }
102   
103
104    /** Instantiate a node group object using its name
105     * @param $name The id of the requested node
106     * @return a Node Group object, or null if there was an error
107     */
108    static function getObjectByName($name)
109    {
110        $object = null;
111        $object = new self($name, 'NAME');
112        return $object;
113    }
114
115
116    public function delete(& $errmsg)
117    {
118        $retval = false;
119        Security::requirePermission(Permission::P('NODEGROUP_PERM_DELETE_NODEGROUP'), $this);
120       
121        $db = AbstractDb::getObject();
122        $id = $db->escapeString($this->getId());
123        if (!$db->execSqlUpdate("DELETE FROM node_groups WHERE node_group_id='{$id}'", false)) {
124            $errmsg = _('Could not delete node group!');
125        } else {
126            $retval = true;
127        }
128       
129
130        return $retval;
131    }
132
133    /**
134     * Create a new Node group in the database
135     *
136     * @param string $ng_name The name of the new node group to create.  If empty a dummy value will be set
137     * @param object $network Network object.  The node's network.  If not
138     *                        present, the current Network will be assigned
139     *
140     * @return mixed The newly created Node Group object, or null if there was
141     *               an error
142     *
143     * @static
144     * @access public
145     */
146    public static function createNewObject($ng_name = null, $network = null)
147    {
148        $db = AbstractDb::getObject();
149        if (empty ($ng_name)) {
150            $ng_name = $db->escapeString(_('New node group name'));
151        }
152        else
153        {
154            $ng_name = $db->escapeString($ng_name);
155        }
156        $node_group_id = get_guid();
157       
158        if (empty ($network)) {
159            $network = Network::getCurrentNetwork();
160        }
161
162        $network_id = $db->escapeString($network->getId());
163
164        $duplicate = null;
165        try{
166            $duplicate = NodeGroup::getObjectByName($ng_name);
167        }
168        catch (Exception $e)
169        {
170        }
171        if ($duplicate) {
172            throw new Exception(sprintf(_('Sorry, a node group with the name %s already exists.'),$ng_name));
173        }
174
175        $sql = "INSERT INTO node_groups (node_group_id, name) VALUES ('$node_group_id', '$ng_name')";
176
177        if (!$db->execSqlUpdate($sql, false)) {
178            throw new Exception(_('Unable to insert new node group into database!'));
179        }
180       
181        HotspotGraphElement::createNewObject($node_group_id, 'NodeGroup');
182
183        $object = self::getObject($node_group_id);
184
185        return $object;
186    }
187
188    /** Get an interface to pick a node group.
189     * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
190     *
191     * @param string $userData=null Array of contextual data optionally sent to the method.
192     *  The function must still function if none of it is present.
193     * This method understands:
194     *  $userData['preSelectedObject'] An optional object to pre-select.
195     *  $userData['additionalWhere'] Additional SQL conditions for the
196     *                                    objects to select
197     *  $userData['additionalJoin'] Additional SQL JOIN conditions for the
198     *                                    objects to select
199     *  $userData['preSelectedObjects'] An optional object or array of objects to pre-select. (not
200     * supported by type_interface=table)
201     *  $userData['typeInterface'] select, select_multiple or table.  Default is "select"
202     *
203     * * @return html markup
204     */
205    public static function getSelectUI($user_prefix, $userData=null)
206    {
207        $userData=$userData===null?array():$userData;
208        $html = '';
209        $name = $user_prefix;
210        //pretty_print_r($userData);
211        !empty($userData['additionalWhere'])?$additional_where=$userData['additionalWhere']:$additional_where=null;
212        !empty($userData['allowEmpty'])?$allow_empty=$userData['allowEmpty']:$allow_empty=false;
213        !empty($userData['nullCaptionString'])?$nullCaptionString=$userData['nullCaptionString']:$nullCaptionString=null;
214        !empty($userData['onChange'])?$onChangeString=$userData['onChange']:$onChangeString="";
215        !empty($userData['onlyNetwoksAllowingSignup'])?$onlyNetwoksAllowingSignup=$userData['onlyNetwoksAllowingSignup']:$onlyNetwoksAllowingSignup=false;
216
217        $db = AbstractDb::getObject();
218        $sql = "SELECT node_group_id, name FROM node_groups WHERE 1=1 $additional_where";
219        $ng_rows = array();
220        $db->execSql($sql, $ng_rows, false);
221        if ($ng_rows == null) {
222            $ng_rows = array();
223        }
224
225        $number_of_nodegroups = count($ng_rows);
226
227        $i = 0;
228        $tab = array();
229        foreach ($ng_rows as $ng_row) {
230           
231            $tab[$i][0] = $ng_row['node_group_id'];
232            $tab[$i][1] = $ng_row['name'];
233            $i ++;
234           
235        }
236        $html .= _("Node Group:")." \n";
237        $html .= FormSelectGenerator :: generateFromArray($tab, null, $name, null, $allow_empty, $nullCaptionString, "onchange='$onChangeString'");
238
239
240
241        return $html;
242    }
243
244
245    /** Get the selected Node Group object.
246     * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
247     * @return the node object
248     */
249    static function processSelectUI($user_prefix)
250    {
251        $object = null;
252        $name = "{$user_prefix}";
253        return self::getObject($_REQUEST[$name]);
254    }
255
256    /** Get an interface to create a new node group.
257     * @param $network Optional:  The network to which the new node will belong,
258     * if absent, the user will be prompted.
259     * @return html markup
260     */
261    public static function getCreateNewObjectUI($network = null)
262    {
263        $html = '';
264        $html .= _("Add a new node group with name ")." \n";
265        $name = "new_node_group_name";
266        $html .= "<input type='text' size='40' name='{$name}'>\n";
267        if ($network)
268        {
269            $name = "new_node_group_network_id";
270            $html .= "<input type='hidden' name='{$name}' value='{$network->getId()}'>\n";
271        }
272        else
273        {
274            $html .= " "._("in ")." \n";
275            $html .= Network :: getSelectUI('new_node_group');
276        }
277        return $html;
278
279    }
280
281    /**
282     * Process the new object interface.
283     *
284     * Will return the new object if the user has the credentials and the form was fully filled.
285     * @return the node object or null if no new node was created.
286     */
287    public static function processCreateNewObjectUI()
288    {
289        // Init values
290        $retval = null;
291        $name = "new_node_group_name";
292
293        if (!empty ($_REQUEST[$name])) {
294            $ng_name = $_REQUEST[$name];
295        }
296        else
297        {
298            $ng_name = null;
299        }
300        $name = "new_node_group_network_id";
301
302        if (!empty ($_REQUEST[$name])) {
303            $network = Network::getObject($_REQUEST[$name]);
304        } else {
305            $network = Network::processSelectUI('new_node_group');
306        }
307
308        if ($network) {
309            Security::requirePermission(Permission::P('NETWORK_PERM_ADD_NODEGROUP'), $network);
310            $retval = self::createNewObject($ng_name, $network);
311        }
312
313        return $retval;
314    }
315
316    /** @param $id The id of the node group
317     * @param $idType 'GROUP_ID' or 'NAME'*/
318    private function __construct($id, $idType='GROUP_ID')
319    {
320        $db = AbstractDb::getObject();
321        $this->mDb = & $db;
322
323        $id_str = $db->escapeString($id);
324        switch ($idType) {
325            case 'GROUP_ID': $sqlWhere = "node_group_id='$id_str'";
326            break;
327            case 'NAME': $sqlWhere = "name='$id_str'";
328            break;
329            default:
330                throw new exception('Unknown idType parameter');
331        }
332        $sqlWhere =
333        $sql = "SELECT * FROM node_groups WHERE $sqlWhere";
334        $row = null;
335        $db->execSqlUniqueRes($sql, $row, false);
336        if ($row == null)
337        {
338            throw new Exception(sprintf(_("The node group with %s: %s could not be found in the database!"), $idType, $id_str));
339        }
340
341        $this->_row = $row;
342        $this->id = $row['node_group_id'];
343       
344        $this->_hotspotGraphElement = HotspotGraphElement::getObject($this->id, 'NodeGroup');
345    }
346
347    function __toString() {
348        return $this->getName();
349    }
350
351    function getId()
352    {
353        return $this->id;
354    }
355
356    /** Return the name of the node
357     */
358    function getName()
359    {
360        return $this->_row['name'];
361    }
362
363    function setName($name)
364    {
365        $name = $this->mDb->escapeString($name);
366        $this->mDb->execSqlUpdate("UPDATE node_groups SET name = '{$name}' WHERE node_group_id = '{$this->getId()}'");
367        $this->refresh();
368    }
369
370    function getCreationDate()
371    {
372        return $this->_row['group_creation_date'];
373    }
374
375    function setCreationDate($creation_date)
376    {
377        $creation_date = $this->mDb->escapeString($creation_date);
378        $this->mDb->execSqlUpdate("UPDATE node_groups SET group_creation_date = '{$creation_date}' WHERE node_group_id = '{$this->getId()}'");
379        $this->refresh();
380    }
381
382    function getDescription()
383    {
384        return $this->_row['description'];
385    }
386
387    function setDescription($description)
388    {
389        $description = $this->mDb->escapeString($description);
390        $this->mDb->execSqlUpdate("UPDATE node_groups SET description = '{$description}' WHERE node_group_id = '{$this->getId()}'");
391        $this->refresh();
392    }
393
394    /**
395     * Retrieves the admin interface of this object
396     *
397     * @return string The HTML fragment for this interface
398     *
399     * @access public
400     *
401     * @todo Most of this code will be moved to Hotspot class when the
402     *       abtraction will be completed
403     */
404    public function getAdminUI()
405    {
406        $permArray=null;
407        /** @todo this should not be the default network here */
408        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODEGROUP_CONFIG'), Network::getDefaultNetwork());
409        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_ANY_NODEGROUP_CONFIG'), $this);
410        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_NODEGROUP_CONFIG'), $this);
411        Security::requireAnyPermission($permArray);
412        require_once('classes/InterfaceElements.php');
413        require_once('classes/Stakeholder.php');
414        // Init values
415        $html = '';
416
417        $ng_id = $this->getId();
418
419        /*
420         * Check for a warning message
421         */
422        if ($this->_warningMessage != "") {
423            $html .= "<div class='errormsg'>".$this->_warningMessage."</div>\n";
424        }
425
426        /*
427         * Begin with admin interface
428         */
429        $html .= "<fieldset class='admin_container ".get_class($this)."'>\n";
430        $html .= "<legend>"._("Edit a node group")."</legend>\n";
431        $html .= "<ul class='admin_element_list'>\n";
432
433        /*
434         * Information about the node group
435         */
436        $_html_node_information = array();
437
438     
439        // Name
440        $permArray = null;
441        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODEGROUP_CONFIG'), Network::getDefaultNetwork());
442        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_NODEGROUP_CONFIG'), $this);
443        if (Security::hasAnyPermission($permArray)) {
444            $_title = _("Name");
445            $_data = InterfaceElements::generateInputText("node_group_" . $ng_id . "_name", $this->getName(), "node_group_name_input");
446            $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_group_name", $_title, $_data);
447        }
448        else {
449            $_title = _("Name");
450            $_data = $this->getName();
451            $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_group_name", $_title, $_data);
452        }
453       
454        // Description
455        $_title = _("Description");
456        $name = "node_" . $ng_id . "_description";
457        $_data = "<textarea name='$name' cols=80 rows=5 id='node_description_textarea'>\n".$this->getDescription()."\n</textarea>\n";
458        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_description", $_title, $_data);
459       
460        // Creation date
461        $_title = _("Creation date");
462        $_data = DateTimeWD::getSelectDateTimeUI(new DateTimeWD($this->getCreationDate()), "node_group_" . $ng_id . "_creation_date", DateTimeWD::INTERFACE_DATETIME_FIELD, "node_group_creation_date_input");
463        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_creation_date", $_title, $_data);
464
465        //Node content
466        if (!is_null($this->_hotspotGraphElement))
467            $html .= $this->_hotspotGraphElement->getContentAdminUI();
468           
469        //Node hierarchy
470        if (!is_null($this->_hotspotGraphElement))
471            $html .= $this->_hotspotGraphElement->getGraphAdminUI();
472           
473        // Build section
474        $html .= InterfaceElements::generateAdminSectionContainer("node_group_information", _("Information about the node group"), implode(null, $_html_node_information));
475
476        /*
477         * Access rights
478         */
479        if (User::getCurrentUser()->DEPRECATEDisSuperAdmin()) {
480            require_once('classes/Stakeholder.php');
481            $html_access_rights = Stakeholder::getAssignStakeholdersUI($this);
482            $html .= InterfaceElements::generateAdminSectionContainer("access_rights", _("Access rights"), $html_access_rights);
483        }
484
485        $html .= "</ul>\n";
486        $html .= "</fieldset>";
487
488        return $html;
489    }
490
491    /**
492     * Process admin interface of this object.
493     *
494     * @return void
495     *
496     * @access public
497     */
498    public function processAdminUI()
499    {
500        require_once('classes/Stakeholder.php');
501        $user = User::getCurrentUser();
502        // Get information about the network
503        $network = Network::getDefaultNetwork();
504        //pretty_print_r($_REQUEST);
505        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODEGROUP_CONFIG'), Network::getDefaultNetwork());
506        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_ANY_NODEGROUP_CONFIG'), $this);
507        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_NODEGROUP_CONFIG'), $this);
508        Security::requireAnyPermission($permArray);
509        // Check if user is a admin
510        $_userIsAdmin = User::getCurrentUser()->DEPRECATEDisSuperAdmin();
511
512        // Information about the node
513
514        $ng_id = $this->getId();
515
516        // Content processing
517        if (!is_null($this->_hotspotGraphElement))
518            $this->_hotspotGraphElement->processContentAdminUI();
519
520        // Name
521        $permArray = null;
522        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODEGROUP_CONFIG'), Network::getDefaultNetwork());
523        $permArray[]=array(Permission::P('NODEGROUP_PERM_EDIT_NODEGROUP_CONFIG'), $this);
524        if (Security::hasAnyPermission($permArray)) {
525            $name = "node_group_" . $ng_id . "_name";
526            $this->setName($_REQUEST[$name]);
527        }
528
529        // Creation date
530        $name = "node_group_".$ng_id."_creation_date";
531        $this->setCreationDate(DateTimeWD::processSelectDateTimeUI($name, DateTimeWD :: INTERFACE_DATETIME_FIELD)->getIso8601FormattedString());
532     
533        // Description
534        $name = "node_".$ng_id."_description";
535        $this->setDescription($_REQUEST[$name]);
536
537        if (!is_null($this->_hotspotGraphElement))
538            $this->_hotspotGraphElement->processGraphAdminUI($errMsg);
539        if(!empty($errMsg)) {
540            echo $errMsg;
541            $errMsg = null;
542        }
543     
544        // End Node group configuration section
545
546        // Access rights
547        Stakeholder::processAssignStakeholdersUI($this, $errMsg);
548        if(!empty($errMsg)) {
549            echo $errMsg;
550        }
551    }
552
553    /** Add content to this node */
554    public function addContent(Content $content)
555    {
556        $db = AbstractDb::getObject();
557        $content_id = $db->escapeString($content->getId());
558        $sql = "INSERT INTO node_has_content (node_id, content_id) VALUES ('$this->id','$content_id')";
559        $db->execSqlUpdate($sql, false);
560        exit;
561    }
562
563    /** Remove content from this node */
564    public function removeContent(Content $content)
565    {
566        $db = AbstractDb::getObject();
567        $content_id = $db->escapeString($content->getId());
568        $sql = "DELETE FROM node_has_content WHERE node_id='$this->id' AND content_id='$content_id'";
569        $db->execSqlUpdate($sql, false);
570    }
571
572
573    /** Reloads the object from the database.  Should normally be called after a set operation */
574    protected function refresh()
575    {
576        $this->__construct($this->id);
577    }
578    /** Menu hook function */
579    static public function hookMenu() {
580        $items = array();
581       
582        if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_EDIT_ANY_NODEGROUP_CONFIG')))
583        {
584            $items[] = array('path' => 'node/node_group_edit',
585            'title' => _("Edit node groups"),
586            'url' => BASE_URL_PATH.htmlspecialchars("admin/generic_object_admin.php?object_class=NodeGroup&action=list")
587            );
588        }
589        else if($nodes = Security::getObjectsWithPermission(Permission::P('NODEGROUP_PERM_EDIT_NODEGROUP_CONFIG'))) {
590             
591            foreach ($nodes as $nodeId => $node) {
592                $items[] = array('path' => 'node/node_'.$nodeId.'edit',
593                'title' => sprintf(_("Edit %s"), $node->getName()),
594                'url' => BASE_URL_PATH.htmlspecialchars("admin/generic_object_admin.php?object_class=NodeGroup&action=edit&object_id=$nodeId")
595                );
596            }
597        }
598        if(Security::hasPermission(Permission::P('NETWORK_PERM_ADD_NODEGROUP'))){
599            $items[] = array('path' => 'node/node_group_add_new',
600                'title' => sprintf(_("Add a new node group")),
601                'url' => BASE_URL_PATH.htmlspecialchars("admin/generic_object_admin.php?object_class=NodeGroup&action=new_ui")
602            );
603        }
604        $items[] = array('path' => 'node',
605        'title' => _('Node administration'),
606        'type' => MENU_ITEM_GROUPING);
607       
608        return $items;
609    }
610    /**
611     * Assigns values about node to be processed by the Smarty engine.
612     *
613     * @param object $smarty Smarty object
614     * @param object $node    Node object, if unset, the current node will be used
615     *
616     * @return void
617     */
618    public static function assignSmartyValues($smarty, $node = null)
619    {
620        if (!$node) {
621            $node = self::getCurrentNode();
622        }
623
624        // Set node details
625        $smarty->assign('nodeId', $node ? $node->getId() : '');
626        $smarty->assign('nodeName', $node ? $node->getName() : '');
627        $smarty->assign('nodeLastHeartbeatIP', $node ? $node->getLastHeartbeatIP() : '');
628        $smarty->assign('nodeNumOnlineUsers', $node ? $node->getNumOnlineUsers() : '');
629        $smarty->assign('nodeWebSiteURL', $node ? $node->getWebSiteURL() : '');
630        $node = self::getCurrentRealNode();
631        // Set node details
632        $smarty->assign('realNodeId', $node ? $node->getId() : '');
633        $smarty->assign('realNodeName', $node ? $node->getName() : '');
634        $smarty->assign('realNodeLastHeartbeatIP', $node ? $node->getLastHeartbeatIP() : '');
635    }
636}
637
638/*
639 * Local variables:
640 * tab-width: 4
641 * c-basic-offset: 4
642 * c-hanging-comment-ender-p: nil
643 * End:
644 */
Note: See TracBrowser for help on using the browser.