Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Form is not populated when adding business logic to fetch method

    Hello,

    I am using Smart GWT Power, snapshot 13-12-2010.

    I have a form that shows the profile of the currently logged in user. In order to secure this, that is, the user can only see HIS OWN profile, even if he would edit the request data (substituting his username for someone else's), I created a custom check like this.

    Code:
    public class UpdateMyProfile {
        public DSResponse fetch(DSRequest req) throws Exception {
    
    
    		DSResponse res = new DSResponse();
    		Object principal = SecurityContextHolder.getContext()
    				.getAuthentication().getPrincipal();
    
    		SytematicSaltedUser currentUser = null;
    		if ("anonymousUser".equals(principal)) {
    			res.setFailure();
    			return res;
    		} else {
    			currentUser = (SytematicSaltedUser) principal;
    		}
    
    		final String username = currentUser.getUsername();
    		Map crits = req.getCriteria();
    		if (crits != null && crits.get("username") != null) {
    			String usernameFromClient = (String) crits.get("username");
    			if (!usernameFromClient.equals(username)) {
    				res.addError("username",
    						"You cannot get someone else's username");
    				return res;
    			} else {
    				res = req.execute();
    				return res;
    			}
    
    		} else {
    			res.setFailure();
    			return res;
    
    		}
    
    	}
    
    }
    So it just compares the username that was sent as primary key in the criteria, to the one in the session, and checks if they are the same.

    My Form code looks like this
    Code:
    private class UserForm extends DynamicForm {
    
            protected RadosMessages messages = (RadosMessages) GWT
    				.create(RadosMessages.class);
    
    	public UserForm(String username) {
    		setWidth(330);
    		setTitleWidth(200);
    		setDataSource(DataSource.get("users"));
    		setFetchOperation("myProfileRead");
    		setUpdateOperation("myProfileUpdate");
    		setNumCols(2);
    		setTitleOrientation(TitleOrientation.LEFT);
    
    		getField("surname").setTitle(messages.myProfileWindow_surname());
    		getField("username").setTitle(messages.myProfileWindow_username());
    		getField("email").setTitle(messages.myProfileWindow_email());
    		setValue("username", username);
    
    		getField("password").hide();
    		getField("list_groups").hide();
    		getField("account_enabled").hide();
    
    		saveProfileButton.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				userForm.saveData(new DSCallback() {
    					public void execute(DSResponse response,
    							Object rawData, DSRequest request) {
    						if (response.getStatus() == DSResponse.STATUS_SUCCESS) {
    							SC.say(messages.myProfileWindow_successfully_changed());
    						}
    
    					}
    				});
    
    			}
    		});
    			
    			
    		
    		Criteria criteria = new Criteria("username", username);
    		fetchData(criteria);
    
    
    	}
    }
    and this is my users.ds.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <DataSource ID="users" serverType="sql" tableName="users"> 
      <fields> 
        <field name="username" type="text" length="50" primaryKey="true" required="true"/>  
        <field name="email" type="text" required="true"> 
          <validators> 
            <validator type="serverCustom"> 
              <serverObject lookupStyle="new" className="nl.sytematic.projects.SytematicDemoApp.server.validators.EmailValidator"/> 
            </validator> 
          </validators> 
        </field>  
        <field name="password" type="text" length="50"/>  
        <field name="salt" type="hidden"/>  
        <field name="account_enabled" type="boolean" required="false"/>  
        <field name="list_groups" type="text" length="50" customSQL="true"/>  
        <field name="surname" title="surname" type="text" required="false" length="128" /> 
      </fields>  
      <operationBindings>   
        <operationBinding operationType="fetch" requiresRole="CAN_READ_MY_ACCOUNT" requiresAuthentication="true" operationId="myProfileRead" outputs="username,email,surname"> 
          <serverObject lookupStyle="new" className="nl.sytematic.projects.SytematicDemoApp.server.security.UpdateMyProfile"/> 
        </operationBinding>  
    <!-- rest of bindings omitted for clarity -->
    </DataSource>
    Now, as you can see, the form has setFetchOperation("myProfileRead");, and the debugger shows that my custom operation is called. Observing the return data, it DOES in fact return the username, email, and surname, as the binding has stated in its outputs. So , it ought to work, but the form is not populated.

    If I remove the setFetchOperation("myProfileRead") line, falling back to the built-in (insecure) fetch operation, the form IS getting populated.

    Is this a bug, or am I missing something? Any help appreciated!

    #2
    To be really sure whether correct data is returned, use the RPC tab of the Developer Console and compare the two responses.

    Comment


      #3
      Ok, indeed, the response does not show data:
      Code:
      data: {}
      If I remove the outputs-clause in the users.ds.xml, the form is populated! But now redundant data is sent back, like encoded pw and salt, not what I like. I've upgraded to Power 2.4, still happens.

      Any thoughts? Am I touching a bug with 'outputs' here?

      Also, just wanted to say that this whole declarative security business is quite brilliant. Good architectural job!

      Edit: accidentally posted with other account, but I am Sytematic

      Comment


        #4
        Are you sending back just one record? What if you instead send back the data as a List with one item in it?

        Comment

        Working...
        X