RADIUSdesk

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
technical_discussions:click_to_connect_extra [2021/10/24 17:49] – [pnlDynamicDetailClickToConnect.js] admintechnical_discussions:click_to_connect_extra [2021/10/24 19:28] (current) – [Modify the Login Pages for the Extra Options] admin
Line 184: Line 184:
 }, },
 </code> </code>
-  * Next we will see what we need to modify on the CakePHP3 App Side+  * Remember to run **Sencha Command** after these to generate the optimized JavaScript code. 
 +  * There is a dedicated Wiki Page in this site for it. 
 +  * Next we will see what we need to modify on the CakePHP3 App Side.
  
 ==== CakePHP3 App Side ==== ==== CakePHP3 App Side ====
 +  * We need to add extra fields to the **dynamic_details** sql table inside the **rd** database.
 +  * See the following SQL Patch snippet which add those fields if not present
 +<code sql>
 +if not exists (select * from information_schema.columns
 +    where column_name = 'ctc_require_phone' and table_name = 'dynamic_details' and table_schema = 'rd') then
 +    alter table dynamic_details add column `ctc_require_phone` tinyint(1) NOT NULL DEFAULT '0';
 +end if;
 +
 +if not exists (select * from information_schema.columns
 +    where column_name = 'ctc_resupply_phone_interval' and table_name = 'dynamic_details' and table_schema = 'rd') then
 +    alter table dynamic_details add column `ctc_resupply_phone_interval` int(4) NOT NULL DEFAULT '0';
 +end if;
 +
 +if not exists (select * from information_schema.columns
 +    where column_name = 'ctc_require_dn' and table_name = 'dynamic_details' and table_schema = 'rd') then
 +    alter table dynamic_details add column `ctc_require_dn` tinyint(1) NOT NULL DEFAULT '0';
 +end if;
 +
 +if not exists (select * from information_schema.columns
 +    where column_name = 'ctc_resupply_dn_interval' and table_name = 'dynamic_details' and table_schema = 'rd') then
 +    alter table dynamic_details add column `ctc_resupply_dn_interval` int(4) NOT NULL DEFAULT '0';
 +end if;
 +</code>
 +  * We also need to add extra field to the **data_collectors** sql table inside the **rd** database.
 +  * See the following SQL Patch snippet which add those fields if not present
 +<code sql>
 +if not exists (select * from information_schema.columns
 +    where column_name = 'phone' and table_name = 'data_collectors' and table_schema = 'rd') then
 +    alter table data_collectors add column `phone` varchar(36) NOT NULL DEFAULT '';
 +end if;
 +
 +if not exists (select * from information_schema.columns
 +    where column_name = 'dn' and table_name = 'data_collectors' and table_schema = 'rd') then
 +    alter table data_collectors add column `dn` varchar(36) NOT NULL DEFAULT '';
 +end if;
 +</code>
 +  * After taking care of the database lets see what needs to be modified to the CakePHP 3 controllers
 +  * Locate the file DynamicDetailsController.php.
 +  * It is typically under ///var/www/rdcore/cake3/rd_cake/src/Controller/DynamicDetailsController.php//
 +  * There is not much that needs modification since CakePHP takes care of most things behind the scenes.
 +  * Just locate the **editClickToConnect** method and modify **$check_items**
 +<code php>
 +$check_items = [
 + 'connect_check',
 + 'connect_only',
 + 'ctc_require_email',
 + 'ctc_require_phone',
 + 'ctc_require_dn',
 +];
 +</code>
 +  * Locate the file DataCollectorsController.php.
 +  * It is typically under ///var/www/rdcore/cake3/rd_cake/src/Controller/DataCollectorsController.php//
 +  * We will modify the login page eventually to have various options displayed in the Pop-Up for Click-To-Connect so we need to modify the DataCollectorsController to only check the email field **IF PRESENT**
 +  * See the following snippets 
 +<code php>
 +public function addMac(){
 +    if ($this->request->is('post')) { 
 +        if($this->request->getData('email')){
 +            if(!$this->_test_email($this->request->data['email'])){
 +                return;
 +            }
 +        }
 +        $dd = $this->_find_dynamic_detail_id();
 +</code>
 +  * And this one 
 +<code php>
 +private function _addOrEdit($user,$type= 'add') {
 +
 +    //__ Authentication + Authorization __
 +    
 +    $user_id    = $user['id'];
 +    
 +    if($this->request->getData('email')){
 +        if(!$this->_test_email($this->request->data['email'])){
 +            return;
 +        }
 +    }
 +    
 +    $this->request->data['public_ip'] = $this->request->clientIp();
 +</code>
 +  * Also the **macCheck** method need to give feedback on those new methods in order so we can determine which fields must be shown in the Pop-Up
 +<code php>
 +public function macCheck(){
 +
 +    $data   = $this->request->data;      
 +    $q_r    = $this->_find_dynamic_detail_id();
 +    
 +    $data['ctc_require_email'] = false; // By defaul don't ask for email;     
 +                       
 +    if($q_r){
 +
 +        //Once we found the Dynamic Login Page; We need to figure out if we need to ask for an email for this person
 +        //For that we need to look for a combo **dynamic_detail_id** and **mac**
 +        //IF found look at the modify timestamp and if it 'expired' ask for it again
 +        //If not found ask for it (ctc_require_email == true)
 +        //Else we set ctc_require_email == false since we found the combo and it has not expired yet  
 +        $dd_id          = $q_r->dynamic_detail_id;
 +        $dd_resuply_int = $q_r->dynamic_detail->ctc_resupply_email_interval;
 +        $dd_resuply_intP = $q_r->dynamic_detail->ctc_resupply_phone_interval;
 +        $data['dd_id' = $dd_id;
 +        
 +        if($q_r->dynamic_detail->ctc_require_email == true){
 +            $q_dd = $this->{$this->main_model}->find()
 +                ->where([$this->main_model.'.dynamic_detail_id' => $dd_id,$this->main_model.'.mac' => $this->request->data['mac']])
 +                ->first();
 +            if($q_dd){
 +                if($dd_resuply_int > 0){ //This has an expiry date lets compare
 +                
 +                    $expiry_time    = $q_dd->modified->toUnixString()+($dd_resuply_int * 24 * 60 *60);
 +                    $now            = new FrozenTime();
 +                    if($expiry_time < $now->toUnixString()){
 +                        //It already expired ask for a new one
 +                        $data['ctc_require_email'] = true; 
 +                    }   
 +                }
 +            }else{
 +                $data['ctc_require_email'] = true; //We did not found it so have to supply email
 +            }
 +        }
 +        
 +        if($q_r->dynamic_detail->ctc_require_phone == true){
 +            $q_dd = $this->{$this->main_model}->find()
 +                ->where([$this->main_model.'.dynamic_detail_id' => $dd_id,$this->main_model.'.mac' => $this->request->data['mac']])
 +                ->first();
 +            if($q_dd){
 +                if($dd_resuply_intP > 0){ //This has an expiry date lets compare                  
 +                    $expiry_time    = $q_dd->modified->toUnixString()+($dd_resuply_intP * 24 * 60 *60);
 +                    $now            = new FrozenTime();
 +                    if($expiry_time < $now->toUnixString()){
 +                        //It already expired ask for a new one
 +                        $data['ctc_require_email'] = true; 
 +                    }   
 +                }
 +            }else{
 +                $data['ctc_require_phone'] = true; //We did not found it so have to supply email
 +            }
 +        }
 +        
 +        if($q_r->dynamic_detail->ctc_require_dn == true){
 +            $q_dd = $this->{$this->main_model}->find()
 +                ->where([$this->main_model.'.dynamic_detail_id' => $dd_id,$this->main_model.'.mac' => $this->request->data['mac']])
 +                ->first();
 +            if($q_dd){
 +                if($dd_resuply_intP > 0){ //This has an expiry date lets compare                  
 +                    $expiry_time    = $q_dd->modified->toUnixString()+($dd_resuply_intP * 24 * 60 *60);
 +                    $now            = new FrozenTime();
 +                    if($expiry_time < $now->toUnixString()){
 +                        //It already expired ask for a new one
 +                        $data['ctc_require_dn'] = true; 
 +                    }   
 +                }
 +            }else{
 +                $data['ctc_require_dn'] = true; //We did not found it so have to supply dn
 +            }
 +        }      
 +                  
 +    } 
 +    
 +    $this->set(array(
 +        'data' => $data,
 +        'success' => true,
 +        '_serialize' => array('data','success')
 +    ));
 +    
 +}
 +</code>
 +
 +  * This brings us to the end of the CakePHP 3 modifications.
 +  * The only remaining part is the login page themselves.
 +
 +==== Modify the Login Pages for the Extra Options ====
 +  *  Locate the file rdConnect.js.
 +  * It is typically under ///var/www/login/cp/js/rdConnect.js//
 +  * We need to add a flag to set if we created the pop-up window (**ctcFormDone**)
 +<code javascript>
 +cMinWidth           = 240; //240 mobile 300 desktop
 +scrollHeight        = 1000;
 +
 +var ctcFormDone     = false;
 +
 +fDebug          = function(message){  
 +    if(cDebug){
 +        console.log(message)  
 +    }
 +};
 +
 +</code>
 +  * Next we have to add some **OR** coonditions when the user click on the **Click To Connect** button
 +<code javascript>
 +var email_check = location.protocol+'//'+document.location.hostname+"/cake3/rd_cake/data-collectors/mac-check.json";
 +
 +webix.ajax().timeout(3000).post(
 +    email_check,formData,
 +    error   : function(text, data, XmlHttpRequest){
 +        console.log("ERROR -> Getting Info for MAC");    
 +    },
 +    success : function(text, data, XmlHttpRequest){
 +        if(data.json().success == true){            
 +            if((data.json().data.ctc_require_email == true)||(data.json().data.ctc_require_phone == true)||(data.json().data.ctc_require_dn == true)){
 +                if(ctcFormDone == false){ //If not already done 
 +                    buildClickToConnectForm(data.json().data);
 +                }                       
 +                showForm("winEmail", b);
 +            }else{
 +                onBtnClickToConnectClick();
 +            } 
 +        }else{
 +            console.log("OTHER ERROR");   
 +        }
 +    }
 +});
 +</code>
 +  * Lets then see the function that is called **buildClickToConnectForm**. 
 +  * This is called only once.
 +  * We also include validation rules for those fields.
 +<code javascript>
 +var buildClickToConnectForm = function(data){
 +
 +    console.log("Click To Connect Form");
 +    console.log(data);
 +    var e1 = {
 +      view      : "template",
 +      template  : "Please supply to get <b>Guest Access</b>"
 +    };
 +    var e2 = { view:"text", label:'Email', name:"email" };
 +    var e3 = { view:"text", label:'Phone', name:"phone" };
 +    var e4 = { view:"text", label:'DN',    name:"dn" };
 +    var b1 = { view:"button", value: "Submit", click:function(){
 +     if (this.getParentView().validate()){ //validate form
 +         var button      = this;
 +         var formData    = new FormData();
 +         var mac_address = getParameterByName('mac');
 +            formData.append("mac", mac_address);
 +         
 +            var values      = this.getParentView().getValues();
 +            console.log(values);
 +            if(values.email){
 +                formData.append("email", values.email);  
 +            }
 +            if(values.phone){
 +                formData.append("phone", values.phone);  
 +            }
 +            if(values.dn){
 +                formData.append("dn", values.dn);  
 +            }
 +            
 +
 +            //We also add the following
 +            var called      = getParameterByName('called');
 +            formData.append("cp_mac", called);
 +
 +            var nasid       = getParameterByName('nasid');
 +            formData.append("nasid", nasid);
 +
 +            //This might not always be included
 +            var ssid        = getParameterByName('ssid');
 +            if(ssid !== ''){
 +                formData.append("ssid", ssid);
 +            }   
 +            
 +            var add_mac  = location.protocol+'//'+document.location.hostname+"/cake3/rd_cake/data-collectors/add-mac.json";
 +            webix.ajax().timeout(3000).post(
 +                add_mac,
 +                formData,
 +                { 
 +                error   : function(text, data, XmlHttpRequest){
 +                    console.log("ERROR -> Adding MAC");    
 +                },
 +                success : function(text, data, XmlHttpRequest){
 +                    if(data.json().success == true){
 +                      //console.log("ADDED MAC NOW TRY TO CONNECT");
 +                      webix.message("All is correct");
 +                      button.getTopParentView().hide(); //hide window
 +                      onBtnClickToConnectClick();
 +                        
 +                    }else{
 +                        //console.log("OTHER ERROR");
 +                        webix.message({ type:"error", text:data.json().message });   
 +                    }
 +                }
 +            });          
 +            
 +        }
 +     else
 +     webix.message({ type:"error", text:"Form data is invalid" });
 +    }};
 +    
 +    var elements = [e1];
 +    var height   = 140;
 +    var rules   = {};
 +        
 +    if(data.ctc_require_email == true){
 +        elements.push(e2);
 +        height = height+60;
 +        rules.email = webix.rules.isEmail;
 +    }
 +    if(data.ctc_require_phone == true){
 +        elements.push(e3);
 +        height      = height+60;
 +        rules.phone = function(value){
 +            if (! /^[0-9]{8}$/.test(value)) {
 +              webix.message("Phone number must be 8 digits long"); 
 +              return false;
 +            }
 +            return true;
 +        };
 +    }
 +    if(data.ctc_require_dn == true){
 +        elements.push(e4);
 +        height = height+60;
 +        rules.dn = function(value){
 +            if (! /^[0-9]{7}$/.test(value)) {
 +              webix.message("DN number must be 7 digits long"); 
 +              return false;
 +            }
 +            return true;
 +        };
 +    }
 +    elements.push(b1);
 +    
 +    frmEmail = {
 +     view        :"form",
 +     borderless  :true,
 +     elements    : elements,
 +     rules       :rules,
 +     elementsConfig:{
 +     labelPosition:"top",
 +     }
 +    };
 +     
 +     webix.ui({
 +        view    : "popup",
 +        id      : "winEmail",
 +        head    : false,
 +        height  : height,
 +        body    :webix.copy(frmEmail)
 +    });
 +    
 +    ctcFormDone = true;     
 +}
 +
 +</code>
 +  * That brings us to the totality of the changes required.
 +  * These login pages does not need any further optimization. (They are done using Webix) 
 +
 +
 +