Dynamic Web Development with Seaside

18.3Customizing the Session for Login

We will now implement an extremely simple login facility to show how to use a custom session. We will enhance the miniInn application we developed in Chapter 13 and add a login facility.

When a user interacts with a Seaside application for the first time, an instance of the application’s session class is created. The class WASession is the default session class, but this can be changed for each application, allowing you to store key information on this class. Different parts of the system will then be able to take advantage of the information to offer different services to the user.

We will define our own session class and use it to store user login information. We will add login functionality to our existing component. The login functionality could also be supported by using a task and/or a specific login component. The principle is the same: you use the session to store some data that is accessible from everywhere within the current session.

In our application we want to store whether the user is logged in. Therefore we create a subclass called InnSession of the class WASession and we will associate such a new session class to our hotel application. We add the instance variable user to the session to hold the identity of the user who is currently logged in.

WASession subclass: #InnSession
instanceVariableNames: 'user'
classVariableNames: ''
poolDictionaries: ''
category: 'SeasideBook'

We define some utility methods to query the user login information.

InnSession>>login: aString
user := aString
user := nil
^ user isNil not
^ user

Now you need to associate the session we just created with your existing application; you can either use the configuration panel or register the new application setup programmatically.

Configuration Panel. To access the configuration panel of your application go to http://localhost:8080/config/. In the list select your application (probably called ‘miniinn’) and click on its associated configure link. You should get to the configuration panel which lists several things such as: the library your application uses (see Part V); and its general configuration such as its root component (see Chapter 23).

Click on the drop-down list by Session Class — if there is only text here, press the override link first . Among the choices you should find the class InnSession. Select it and you should get the result shown in Figure 127. Now Save your changes.

The session of miniInn is now InnSession

Configuring the application programmatically. To change the associated session of an application, we can set the preference #sessionClass using the message WASession>>preferencesAt:put:. We can do that by redefining the class initialize method of the application as follows. Since this method is invoked automatically only when the application is loaded, make sure that you evaluate it manually after changing it.

MiniInn class>>initialize
| application |
application := WAAdmin register: self asApplicationAt: 'miniInn'.
application preferenceAt: #sessionClass put: InnSession

To access the current session use the message WAComponent>>session. We define the methods login and logout in our component.

self session login: (self request: 'Enter your name:')
self session logout

Then we define the method renderLogin: which, depending on the session state, offers the possibility to either login or logout.

MiniInn>>renderLogin: html
self session isLoggedIn
ifTrue: [
html text: 'Logged in as: ' , self session user , ' '.
html anchor
callback: [ self logout ];
with: 'Logout' ]
ifFalse: [
html anchor
callback: [ self login ];
with: 'Login']

We define a dummy method renderSpecialPrice: to demonstrate behavior only available for users that are logged in.

MiniInn>>renderSpecialPrice: html
html text: 'Dear ' , self session user, ', you can benefit from our special prices!'

Then we redefine the method renderContentOn: to present the new functionality.

MiniInn>>renderContentOn: html
self renderLogin: html.
html heading: 'Starting date'.
html render: calendar1.
startDate isNil
ifFalse: [ html text: 'Selected start: ' , startDate asString ].
html heading: 'Ending date'.
html render: calendar2.
(startDate isNil not and: [ endDate isNil not ]) ifTrue: [
html text: (endDate - startDate) days asString ,
' days from ', startDate asString, ' to ', endDate asString, ' ' ].
self session isLoggedIn "<-- Added"
ifTrue: [ self renderSpecialPrice: html ]

Figure 128, Figure 129 and Figure 130 illustrate the behavior we just implemented. The user may log in using the top level link. Once logged in, extra information is available to the user.

With Session
With Session: Enter your name
With Session: Starting Date and Ending Date

Copyright © 23 April 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.