May 25, 2011

CakePHP Auth Conventions

CakePHP is something new that I'm picking up. My first exposure to web frameworks was Ruby on Rails. Like Rails, the Cake mantra is convention over configuration. It's an awesome way to program. You can save hours of work if you know what the conventions are and follow them. Even bypassing the conventions is not a superhuman effort, usually a few lines of configuration.

One issue I had with Cake was implementing controller authorization. As you might expect it's because I didn't know and follow convention.

I set up my AppController class to use the Auth module and set the mode to 'controller' in beforeFilter. That meant that each controller had to have isAuthorized function defined.

I knew that most of my controllers were going to be uniform in the rights granted to anonymous users, so I coded the isAuthorized method in the AppController too.

class AppController extends Controller {
    var $components = array('Auth', 'Session');
    var $uses = array('Role');

    function beforeFilter() {
        $this->Auth->authorize = 'controller';
    }

    function isAuthorized() {
        if (strcmp($this->action, "index") == 0 || strcmp($this->action, "view") == 0) {
            return true;
        }
        $user = $this->Auth->user('role_id');
        $admin = $this->Role->findByName('Admin');
        $admin = $admin['Role']['id'];
        if ($user == $admin) {
            return true;
        }
        else {
            return false;
        }
    }
}

I thought I'd allowed access to any "index" and "view" action program wide by always returning true from isAuthorized if those actions were requested. Admins had all CRUD rights and regular users had no additional rights over the anonymous users. Sub classes would further refine these rights if necessary.

The scheme didn't work as I expected though because the anonymous users seemed to be getting blocked from all actions, while regular users had the expected rights. Admins were also behaving as expected.

I had to modify my controller to this

class AppController extends Controller {
    var $components = array('Auth', 'Session');
    var $uses = array('Role');

    function beforeFilter() {
        $this->Auth->authorize = 'controller';
        $this->Auth->allow('view', 'index');
    }

    # defaulting all controllers to allow user access to view and index
    # anonymous access to be allowed by subclasses
    function isAuthorized() {
        $user = $this->Auth->user('role_id');
        $admin = $this->Role->findByName('Admin');
        $admin = $admin['Role']['id'];
        if ($user == $admin) {
            return true;
        }
        else {
            return false;
        }
    }
}

In the beforeFilter I had to specifically enable the actions I wanted open to anonymous use. I guess the Auth component will default to not authorize before checking the isAuthorized function if the session does not contain a user.

Spent a few hours tracking that down using pr($this->Auth->user()) calls and die to trace program flow.

May 18, 2011

WPF Binding not working? Check the Output Window

Took me a long time and hours of frustration troubleshooting WPF binding failures to finally find a silver bullet. Actually, this stuff is all over the place on the net, but for whatever reason, not mentioned in many WPF books.

If you are expecting to see a binding when you start your WPF application, but the value never changes, or is default, or the bound listview is empty when it should have data, check the output window in Visual Studio while you debug.

Bindings in WPF are best-efforts only by the framework. Not really sure why. I sometimes wish a giant unhandled exception error would show up instead of silent failure. Nevertheless...

Here's a sample error message you might find there.

Let's say you have the following XAML layed out and you're trying to bind a listview to a 'Parameters' ObservableCollection member of the control data context. But when you filled out the XAML, it was misspelled.

<DockPanel>
  <Label DockPanel.Dock="Top" Style="{StaticResource LayoutLabel}">Parameter Selection</Label>
  <Border  Style="{StaticResource LayoutBorder}">
    <ScrollViewer DockPanel.Dock="Bottom">
      <ListView View="{DynamicResource ParameterView}" ItemsSource="{Binding Path=Parametrs}"/>
    </ScrollViewer>
  </Border>
</DockPanel>

Now when you debug, the members of the 'Parameters' ObservableCollection don't appear in the listview. Go and check the output window and you might see this in the output window
System.Windows.Data Error: 39 : BindingExpression path error: 'Parametrs' property not found on 'object' ''OrderedEnumerable`2' (HashCode=57007955)'. BindingExpression:Path=Parametrs; DataItem='OrderedEnumerable`2' (HashCode=57007955); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
Lots of gobbledygook, but clearly in this message WPF is complaining that binding cannot be made with a Parametr property. It shouldn't be too hard to find the trouble with this information.

More often than not, it's not a spelling mistake, but a plain mismatch between the object being searched by WPF and the binding path given.

Example being if the aforementioned control had a datacontext set to 'MyObject' but the class of 'MyObject' doesn't have a 'Parameters' property at all.

May 14, 2011

Cool Places to Build Stuff

A survey of Software developers finds very narrow focus in what motivates. Even the most hardened veteran still gets tingles when building something new and learning.

If you haven't read 'Drive' by Daniel Pink yet, you should get on that. His insights are very true for us software people. Just a fantastic book. If you are feeling unmotivated by your decent paying job, get this book for some possible explanations.

Bottom line, it's very cool to build stuff. Along that vein, I've been visiting this blog a lot in the past few days. It seems to be written directly for me. I'm a shutterbug, a product review addict, and software professional (which they seem to have a requirement for).

I found a job listing on the site and it sounds like a wicked cool place to work. Lots of building stuff, very few meetings.

But the most interesting part isn't the description of themselves in the job listing, but their use of coding challenge to evaluate new candidates. It doesn't appear to be one of those high pressure 'code while we watch' type deals. Rather, you download the challenge data and produce a solution. Email them a link and your resume when you're done.

I might just do that.