2 Replies Latest reply on Nov 8, 2009 1:49 PM by alexandre.roitman

    Client / admin system

    alexandre.roitman Level 1


      Hello,
      i am trying to develop a little web application for a website. It starts with a login screen and there are two other states: the admin page (in case the user that has logged in is the admin) and the other state is the clientView state -  it displays the username and shows updates inside a textarea component.
      The admin page has a combobox - the admin may chose the client and view his updates. If the admin wants to edit the updates, he can write and click on the update button (the update feature wasn't written yet).
      There is a database called testdb (local - xampp) and the flash builder 4 DB introspector has generated me the CRUD php when I selected the users table,

      Below my code in flex and the generated php.

      I don't manage to login, I receive the following alert:

      Channel disconnected
      Channel disconnected before an acknowledgement was received

      Can anyone help me or give me tips on how could I build this application?

      Thanks!

       

       

      Flash Builder 4 code:

      <?xml version="1.0" encoding="utf-8"?>
      <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" xmlns:userservice="services.userservice.*">
       <s:states>
        <s:State name="State1"/>
        <s:State name="clientView"/>
        <s:State name="adminView"/>
       </s:states>
       <fx:Declarations>
        <s:CallResponder id="getUserByIDResult"/>
        <userservice:UserService id="userService" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
        <s:CallResponder id="getUserByIDResult2"/>
        <s:CallResponder id="getAllUserResult"/>
        <s:CallResponder id="getUserByIDResult3"/>
        <s:CallResponder id="updateUserResult"/>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
       </fx:Declarations>
       <fx:Script>
        <![CDATA[
         import mx.controls.Alert;
         import mx.events.FlexEvent;
         
         private var clientID:int;
         
         
         
         [Bindable]
         private var currentClient:int;
         
         protected function verifyLogin():void
         {
          clientID = int(user_txt);
          getUserByIDResult.token = userService.getUserByID(clientID);
          if(getUserByIDResult.lastResult[0].LOGIN_PASSWORD == password_txt.text)
          {
           if(user_txt.text == "admin")
           {
            currentState = 'adminView';
           }
           else
           {
            currentState = 'clientView';
           }
          }
         }
      
         protected function clientLogin():void
         {
          getUserByIDResult2.token = userService.getUserByID(clientID);
          textArea.text = getUserByIDResult2.lastResult[0].DEPARTMENT;
         }
      
         protected function comboBox_creationCompleteHandler(event:FlexEvent):void
         {
          getAllUserResult.token = userService.getAllUser();
         }
         
         protected function changeClient():void
         {
          currentClient = int(comboBox.selectedLabel);
          getUserByIDResult3.token = userService.getUserByID(currentClient);
          adminClientText.text = getUserByIDResult3.lastResult[0].DEPARTMENT;
         }
      
         
      
         
        ]]>
       </fx:Script>
       <s:TextInput x="509" y="177" id="user_txt" includeIn="State1"/>
       <s:TextInput x="509" y="207" id="password_txt" displayAsPassword="true"  includeIn="State1"/>
       <s:Button x="540" y="237" label="Login" id="login_btn" click="verifyLogin()" includeIn="State1"/>
       <s:Label x="415" y="179" text="username:" fontSize="19" includeIn="State1"/>
       <s:Label x="416" y="210" text="password:" fontSize="19" includeIn="State1"/>
       <s:Label includeIn="adminView,clientView" text="hello" fontSize="18" right="297" top="36"/>
       <s:Label includeIn="adminView,clientView" text="{user_txt.text}" fontSize="18" right="340" top="36"/>
       <s:TextArea includeIn="clientView" right="293" top="105" id="textArea" editable="false"/>
       <s:Label includeIn="adminView,clientView" text="Label" right="297" top="80" text.adminView="updates:" text.clientView="last updates:" textAlign.adminView="right" top.adminView="159" right.adminView="296"/>
       <mx:ComboBox includeIn="adminView" x="934" y="81" editable="true" width="149" id="comboBox" creationComplete="comboBox_creationCompleteHandler(event)" dataProvider="{getAllUserResult.lastResult}" labelField="LOGIN_ID" change="changeClient()" selectedIndex="0"></mx:ComboBox>
       <s:TextArea includeIn="adminView" x="894" y="178" id="adminClientText" editable="true" />
       <s:Button includeIn="adminView" x="1013" y="343" label="update" id="button"/>
      </s:Application>
      

       

       

       

      The PHP generated:

       

      <?php
      /**
       *  README for sample service
       *
       *  This generated sample service contains functions that illustrate typical service operations.
       *  Use these functions as a starting point for creating your own service implementation. Modify the 
       *  function signatures, references to the database, and implementation according to your needs. 
       *  Delete the functions that you do not use.
       *
       *  Save your changes and return to Flash Builder. In Flash Builder Data/Services View, refresh 
       *  the service. Then drag service operations onto user interface components in Design View. For 
       *  example, drag the getAllItems() operation onto a DataGrid.
       *  
       *  This code is for prototyping only.
       *  
       *  Authenticate the user prior to allowing them to call these methods. You can find more 
       *  information at <link>
       *
       */
      class UserService {
       var $username = "root";
       var $password = "";
       var $server = "localhost";
       var $port = "";
       var $databasename = "testdb";
       var $tablename = "user";
       var $connection;
       /**
        * The constructor initializes the connection to database. Everytime a request is 
        * received by Zend AMF, an instance of the service class is created and then the
        * requested method is invoked.
        */
       public function __construct() {
          $this->connection = mysqli_connect(
                $this->server,  
                $this->username,  
                $this->password, 
                $this->databasename,
                $this->port
               );
        $this->throwExceptionOnError($this->connection);
       }
       /**
        * Returns all the rows from the table.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * @return array
        */
       public function getAllUser() {
        $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename");  
        $this->throwExceptionOnError();
        
        mysqli_stmt_execute($stmt);
        $this->throwExceptionOnError();
        
        $rows = array();
        
        mysqli_stmt_bind_result($stmt, $row->ID, $row->FIRST_NAME, $row->LAST_NAME, $row->DISPLAY_NAME, $row->COMPANY_ID, $row->LOGIN_ID, $row->LOGIN_PASSWORD, $row->DEPARTMENT);
        
           while (mysqli_stmt_fetch($stmt)) {
             $rows[] = $row;
             $row = new stdClass();
             mysqli_stmt_bind_result($stmt, $row->ID, $row->FIRST_NAME, $row->LAST_NAME, $row->DISPLAY_NAME, $row->COMPANY_ID, $row->LOGIN_ID, $row->LOGIN_PASSWORD, $row->DEPARTMENT);
           }
        
        mysqli_stmt_free_result($stmt);
           mysqli_close($this->connection);
       
           return $rows;
       }
       /**
        * Returns the item corresponding to the value specified for the primary key.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * 
        * @return stdClass
        */
       public function getUserByID($itemID) {
        
        $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename where ID=?");
        $this->throwExceptionOnError();
        
        mysqli_bind_param($stmt, 'i', $itemID);  
        $this->throwExceptionOnError();
        
        mysqli_stmt_execute($stmt);
        $this->throwExceptionOnError();
        
        mysqli_stmt_bind_result($stmt, $row->ID, $row->FIRST_NAME, $row->LAST_NAME, $row->DISPLAY_NAME, $row->COMPANY_ID, $row->LOGIN_ID, $row->LOGIN_PASSWORD, $row->DEPARTMENT);
        
        if(mysqli_stmt_fetch($stmt)) {
         return $row;
        } else {
         return null;
        }
       }
       /**
        * Returns the item corresponding to the value specified for the primary key.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * 
        * @return stdClass
        */
       public function createUser($item) {
       
        $stmt = mysqli_prepare($this->connection, "INSERT INTO $this->tablename (ID, FIRST_NAME, LAST_NAME, DISPLAY_NAME, COMPANY_ID, LOGIN_ID, LOGIN_PASSWORD, DEPARTMENT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");  
        $this->throwExceptionOnError();
        
        mysqli_bind_param($stmt, 'isssssss', $item->ID, $item->FIRST_NAME, $item->LAST_NAME, $item->DISPLAY_NAME, $item->COMPANY_ID, $item->LOGIN_ID, $item->LOGIN_PASSWORD, $item->DEPARTMENT);  
        $this->throwExceptionOnError();
        mysqli_stmt_execute($stmt);  
        $this->throwExceptionOnError();
        
        $autoid = mysqli_stmt_insert_id($stmt);
        
        mysqli_stmt_free_result($stmt);  
        mysqli_close($this->connection);
        
        return $autoid;
       }
       /**
        * Updates the passed item in the table.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * @param stdClass $item
        * @return void
        */
       public function updateUser($item) {
       
        $stmt = mysqli_prepare($this->connection, "UPDATE $this->tablename SET ID=?, FIRST_NAME=?, LAST_NAME=?, DISPLAY_NAME=?, COMPANY_ID=?, LOGIN_ID=?, LOGIN_PASSWORD=?, DEPARTMENT=? WHERE ID=?");  
        $this->throwExceptionOnError();
        
        mysqli_bind_param($stmt, 'isssssssi', $item->ID, $item->FIRST_NAME, $item->LAST_NAME, $item->DISPLAY_NAME, $item->COMPANY_ID, $item->LOGIN_ID, $item->LOGIN_PASSWORD, $item->DEPARTMENT, $item->ID);  
        $this->throwExceptionOnError();
        mysqli_stmt_execute($stmt);  
        $this->throwExceptionOnError();
        
        mysqli_stmt_free_result($stmt);  
        mysqli_close($this->connection);
       }
       /**
        * Deletes the item corresponding to the passed primary key value from 
        * the table.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * 
        * @return void
        */
       public function deleteUser($itemID) {
          
        $stmt = mysqli_prepare($this->connection, "DELETE FROM $this->tablename WHERE ID = ?");
        $this->throwExceptionOnError();
        
        mysqli_bind_param($stmt, 'i', $itemID);
        mysqli_stmt_execute($stmt);
        $this->throwExceptionOnError();
        
        mysqli_stmt_free_result($stmt);  
        mysqli_close($this->connection);
       }
      
       /**
        * Returns the number of rows in the table.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * 
        */
       public function count() {
        $stmt = mysqli_prepare($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename");
        $this->throwExceptionOnError();
        mysqli_stmt_execute($stmt);
        $this->throwExceptionOnError();
        
        mysqli_stmt_bind_result($stmt, $rec_count);
        $this->throwExceptionOnError();
        
        mysqli_stmt_fetch($stmt);
        $this->throwExceptionOnError();
        
        mysqli_stmt_free_result($stmt);
        mysqli_close($this->connection);
        
        return $rec_count;
       }
      
       /**
        * Returns $numItems rows starting from the $startIndex row from the 
        * table.
        *
        * Add authroization or any logical checks for secure access to your data 
        *
        * 
        * 
        * @return array
        */
       public function getUser_paged($startIndex, $numItems) {
        
        $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?");
        $this->throwExceptionOnError();
        
        mysqli_bind_param($stmt, 'ii', $startIndex, $numItems);
        mysqli_stmt_execute($stmt);
        $this->throwExceptionOnError();
        
        $rows = array();
        
        mysqli_stmt_bind_result($stmt, $row->ID, $row->FIRST_NAME, $row->LAST_NAME, $row->DISPLAY_NAME, $row->COMPANY_ID, $row->LOGIN_ID, $row->LOGIN_PASSWORD, $row->DEPARTMENT);
        
           while (mysqli_stmt_fetch($stmt)) {
             $rows[] = $row;
             $row = new stdClass();
             mysqli_stmt_bind_result($stmt, $row->ID, $row->FIRST_NAME, $row->LAST_NAME, $row->DISPLAY_NAME, $row->COMPANY_ID, $row->LOGIN_ID, $row->LOGIN_PASSWORD, $row->DEPARTMENT);
           }
        
        mysqli_stmt_free_result($stmt);  
        mysqli_close($this->connection);
        
        return $rows;
       }
       
       
       /**
        * Utitity function to throw an exception if an error occurs 
        * while running a mysql command.
        */
       private function throwExceptionOnError($link = null) {
        if($link == null) {
         $link = $this->connection;
        }
        if(mysqli_error($link)) {
         $msg = mysqli_errno($link) . ": " . mysqli_error($link);
         throw new Exception('MySQL Error - '. $msg);
        }  
       }
      }
      ?>
      
        • 1. Re: Client / admin system
          mewk Level 3

          A few things

          • I'm assuming you removed the db port/password because these fields are currently empty.
          • has the user table been pre-populated with user records?
          • despite what the form may imply, the code is expecting an integer value typed into the user name box.
          • you just can't follow
            getUserByIDResult.token = userService.getUserByID(clientID);
            

                with this:

          if(getUserByIDResult.lastResult[0].LOGIN_PASSWORD == password_txt.text)
          { ....
          

              the call is asynchronous and you need to treat it as such; place the if statement within a result handler.

           

          Lastly, a "channel disconnected" message usually indicates a failure with the mysql query. There are a number of ways to debug the code, the simplest way you could handle this is to figure out what query string the call is making (i.e. "SELECT * FROM $this->tablename where ID=?") and then manually try the query yourself and see if it was successful. Best o luck,

           

          - e

          1 person found this helpful
          • 2. Re: Client / admin system
            alexandre.roitman Level 1

            Thanks, I did it and worked. I have changed the code a little bit and added features.

            Now what do I have to change to run this on a webhosting? In my case it's hostmonster. I have to create a database on my server and the table that I access on that database. And I know I should upload the html, swf and php files. But do I have to change anything in Flash Builder 4 or PHP despite the user and password to my database on ht PHP class?

            Thank you very much.

            Below is the code:

            <?xml version="1.0" encoding="utf-8"?>
            <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                              xmlns:s="library://ns.adobe.com/flex/spark" 
                              xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" xmlns:userservice="services.userservice.*" minWidth.Client="800" minHeight.Client="600" minHeight.Admin="600" minWidth.Admin="800" xmlns:valueObjects="valueObjects.*">
                 <fx:Script>
                      <![CDATA[
                           import mx.collections.ArrayCollection;
                           import mx.controls.Alert;
                           
                           import valueObjects.User;
                           
                           private var userArr:ArrayCollection;
                           private var currUser:User;
                           
                           [Bindable]
                           private var loggedUser:User;
                           
                           protected function login_btn_clickHandler(event:MouseEvent):void
                           {
                                getAllUserResult.token = userService.getAllUser();
                           }
                           
                           private function verifyLogin():void
                           {
                                messageLabel.text = "";
                                //user = new User();
                                userArr = getAllUserResult.lastResult as ArrayCollection;
                                var userFound:Boolean = false;
                                for (var i:int; i<userArr.length; i++)
                                {
                                     loggedUser = userArr[i];
                                     if (loggedUser.LOGIN == user_txt.text)
                                     {
                                          userFound = true;
                                          if (verifyPassword(loggedUser.PASSWORD))
                                          {
                                               changeState(loggedUser.LOGIN);
                                          }
                                          else
                                          {
                                               messageLabel.text = "Wrong Password";
                                          }
                                          break;
                                     }
                                }
                                
                                if(!userFound)
                                {
                                     messageLabel.text = "Username not found";
                                }
                                
                           }
                           
                           private function verifyPassword(pword:String):Boolean
                           {
                                if(pword == password_txt.text)
                                {
                                     return true;
                                }
                                else
                                {
                                     return false;
                                }
                           }
                           
                           private function changeState(user:String):void
                           {
                                if(user == "admin")
                                {
                                     currentState = 'Admin';
                                }
                                else
                                {
                                     currentState = 'Client';
                                }
                           }
                           
                           private function changeClient():void
                           {
                                for (var i:int; i<userArr.length; i++)
                                {
                                     currUser = userArr[i];
                                     if (currUser.LOGIN == userComboBox.selectedLabel)
                                     {
                                          updatesText.text = currUser.UPDATES;
                                     }
                                }
                                
                                
                           }
                                
                           protected function update_btn_clickHandler(event:MouseEvent):void
                           {
                                currUser.UPDATES = updatesText.text;
                                updateUserResult.token = userService.updateUser(currUser);
                           }
            
            
                           protected function createUser():void
                           {
                                user.LOGIN = lOGINTextInput.text;
                                user.PASSWORD = pASSWORDTextInput.text;
                                user.UPDATES = uPDATESTextInput.text;
                                createUserResult.token = userService.createUser(user);
                                lOGINTextInput.text = "";
                                uPDATESTextInput.text = "";
                                pASSWORDTextInput.text = "";
                           }
                                
                           private function onLogoutClick():void
                           {
                                currentState='State1';
                                user_txt.text = "";
                                password_txt.text = "";
                           }
            
                      ]]>
                 </fx:Script>
                 <s:states>
                      <s:State name="State1"/>
                      <s:State name="Client"/>
                      <s:State name="Admin"/>
                 </s:states>
                 <fx:Declarations>
                      <s:CallResponder id="getAllUserResult" result="verifyLogin()"/>
                      <userservice:UserService id="userService" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
                      <s:CallResponder id="updateUserResult"/>
                      <valueObjects:User id="user" />
                      <!--LOGIN="{parseInt(lOGINTextInput.text)}"-->
                      <s:CallResponder id="createUserResult"/>
                      <!-- Place non-visual elements (e.g., services, value objects) here -->
                 </fx:Declarations>
                 <s:TextInput x="500" y="10" id="user_txt" includeIn="State1" />
                 <s:TextInput x="500" y="40" id="password_txt" includeIn="State1" displayAsPassword="true"/>
                 <s:Label x="460" y="10" text="user" includeIn="State1"/>
                 <s:Label x="432" y="40" text="password" includeIn="State1"/>
                 <s:Button x="528" y="70" label="Login" id="login_btn" click="login_btn_clickHandler(event)" includeIn="State1"/>
                 <s:Label x="547" y="160" id="messageLabel" text="" includeIn="State1"/>
                 <s:Label includeIn="Admin,Client" x="366" y="22" text="Hello"/>
                 <s:Label includeIn="Admin,Client" x="406" y="22" text="{loggedUser.LOGIN}"/>
                 <s:TextArea includeIn="Admin,Client" x="366" y="42" width="248" height="239" text="{loggedUser.UPDATES}" editable.Client="false" editable.Admin="true" id="updatesText"/>
                 <s:Button includeIn="Admin" x="366" y="299" label="Update" id="update_btn" click="update_btn_clickHandler(event)"/>
                 <mx:ComboBox includeIn="Admin" x="622" y="42" editable="true" id="userComboBox" dataProvider="{getAllUserResult.lastResult}" labelField="LOGIN" change="changeClient()"></mx:ComboBox>
                 <s:Button includeIn="Client,Admin" x="622" y="100" label="Log out" click="onLogoutClick()"/>
                 <mx:Form includeIn="Admin" defaultButton="{button}" x="366" y="350">
                      <mx:FormItem label="LOGIN">
                           <s:TextInput id="lOGINTextInput" />
                      </mx:FormItem>
                      <mx:FormItem label="PASSWORD">
                           <s:TextInput id="pASSWORDTextInput" />
                      </mx:FormItem>
                      <mx:FormItem label="UPDATES">
                           <s:TextInput id="uPDATESTextInput" />
                      </mx:FormItem>
                      <s:Button label="CreateUser" id="button" click="createUser()"/>
                 </mx:Form>
            </s:Application>