In this video from chapter 12 of Learning Web Development with Seaside we look at how Seaside can support user login. We start by launching the Seaside One-Click Experience and creating a new domain model class to represent a user. We use the class refactoring tool to add instance variable accessors. Note that the accessor for the ‘name’ instance variable is given the method name ‘name1’. This is because it overrides a method in Object named ‘name’. Since we want the override, we will add our method and remove the provided one.
Because it is a poor practice to save passwords, we will store a hash of the password. We provide a method to verify passwords by comparing the hash of a provided string. We add an initialize method to set reasonable default values and we add a comparing method to support sorting.
On the class side we define a class instance variable to hold a list of users and we define a class-side method to return the list. This method includes a lazy initializer to set up a default initial user. Finally, we add a class-side method to lookup a user based on an id and password.
Seaside provides a way to keep information about a web session. We subclass WASession to provide a class with a ‘user’ instance variable. We use the refactoring tool to create accessors. When we register our main component as a Seaside application, we can specify the class to be used for the session.
Now we will create a login component to collect the user ID and password. We define a render method that simply shows the class name so we can see that it is being called correctly. Now we need to use the new component. We will change the main page’s sidebar so that it supports the login/logout feature. To do this we will refactor the render sidebar method so that the code dealing with the home anchor is in a separate method.
Instead of using cut-and-paste, Smalltalk gives us an ‘extract method’ refactoring in which we can select lines of a method and define a new method to contain those lines. We give the new method a name #’renderHomeAnchorOn:’ and the refactoring tool shows us the proposed changes. Whe we accept the changes we see the changes. We can then extract the ‘Events’ anchor as well. I’ll change the formatting a bit.
Now we can create a new method to rendre a login link. We then refactor the render sidebar method to call our new login anchor. We can view the appliaction in a web browser and see that it shows the login link and when you click on the link it shows the login component. Now we will make the login component useful.
We will create a method to render the user ID and allow text input to edit the userID. When we try to save the method we discover that the instance variable is not properly named. After that is fixed, we can paste and save the edit method. We rename and modify this method to create a div to display and edit the password. We create a warning method to return a string describing the current state, logged in, need to log in, and login failed. When we try to save the method Smalltalk alerts us to a misspelled message send.
We add a render method to show the warning. We add a render method to render a submit button named ‘Login’ that calls the login method. We add a method to render a form with the user edit div, the password edit div, the warning div, and the login div. Finally, we edit the render content method to call the render form method.
When we view the login component in a web browser, we see that the various elements exist, but the layout is not very good. We modify our CSS so that all forms are displayed as a table. This fixes up the formatting of the login component. when we refresh the page we find that focus is set to the password element. We want it on the user ID element and see in the code that we copied the ‘setFocus’ message from the user method. After removing that message we return to the web browser and find that focus is properly set to the user field.
clicking the login button gives an error because the login method is not yet defined. We create a method to lookup the user based on the user and password entered. We call our earlier method to lookup among the defined users. When we try the application again we give a wrong user/password and see that it tells us that the login failed. Note also that the password is displayed in clear text. We fix this by going back to the render password method and changing the HTML element. When we refresh the browser we see that the password is obscured.
We can try the correct user ID (‘admin’) without a password and see that the login failed. When we try the correct user ID and password we are told that we are logged in as Site Administrator.
Now we will modify the render content method so that if no user exists, we will invite the login. If a user is logged in, then we show the user. This lets the user know that they are logged in.
Now we go back to our main application and add an anchor that has a callback that clears the session user and label it ‘Logout’. We modify the login anchor to remove the break element. Now we create a render user method that checks whether a user exists. If no user exists, then we offer the login option. If a user does exist, then we offer the logout option. Finally we modify the sidebar render method so that instead of rendering a login we render the user. We try the application in a web browser and see that when we are properly logged in we get a logout link.
Now we are going to limit some functionality to logged in users. We go to the schedule list component and make the add link limited to logged in users. We go back to the web browser and verify that the functionality works as expected. Next we modify the table initialization method so that the ‘action’ column (that supports the delete function) is available only to logged in users. We try the application and see that when we are not logged in we don’t see the delete anchor. When we are logged in we do see the delete anchor.
We save our code and quit the Seaside One-Click Experience.
For more information go to seaside.gemstone.com/tutorial.