Well, given that I took that peep of session.inc out of my shoe, now I'd
like to go back to the auth problem, which was at the origin of all of
this.
There are a few 'user addressed' problems and a more 'designer
addressed' one with the auth->start method as it is today.
*First the user-addressed problems with auth.
1) auth[uid]='form'
The way auth was designed, it uses the auth[uid] variable to keep the
uid after a successful login, OR, before a user is logged, other values
that can be 'form', 'nobody', and I think 'deleted' too.
'form' has been obviously added first in the code, and later someone
thought to add 'nobody' as well.
The purpose of this flag is to set an overall status for your session,
that says 'this guy is being shown a login/reg form, and we all have to
wait until he completes that'. That's the reason why you have to have a
cancel_login button, and can't simply go back. Your auth class is
blocked. That's the reason why is so complicated to show a login box
everywhere.
But what about nobody? What about if I want to go back to a page that
has the default_user auth class, or open it in another browser window?
No way. Because once auth[uid] is 'form', it cannot be nobody unless you
do some tricks in the code. So the form status blocks all pages that
have default auth too.
But then, if I want to show 'a login box in every page', as usual, what
should I do? I have to set auth[uid]=form, but also it has to be
'nobody'... problem.
Even supposed I don't use default_auth (nobody), I have to set
auth[uid]=form before any form input is accepted for login. So if I want
to show a login box everywhere, auth[uid] is always 'form'. Better
initialize it to 'form' from the beginning, 'nobody' problem apart
(joke).
But what's the use of the auth[uid]=='form' status flag? Be assured that
input is coming after a form has been shown somewhere? Do those who
adopt their auth_preauth function (which doesn't need that 'form' value)
adopt a similar approach? I don't think so. Most probably they check for
a determinate form field (can be operation=login/register), which surely
doesn't assure that a form has been shown, but is ok.
Now that I (hope) have introduced a patch that prevents obtaining 'any'
user provided session, a check for a session while receiving the form
fields does exactly the same job as the auth[uid]=form value: prevent
that someone can register with a single http post (maybe done by a batch
script), without having really entered the site.
By eliminating the auth[uid]=form status we solve many problems: the
clash with nobody, the need of a cancel_login action, the mess that the
start method in auth has become, the handling of the interaction with
the client from deep inside such a complicate function, the problem of
showing a login form by yourself, not commanded by auth.
If you want that status flag, it can be moved outside of method
auth->start, and I think the best place, being it a 'page handling
problem', in page.inc. You may never know, one day you have clients that
interact differently than a web page (xml, SOAP, whatever), and you want
to use you auth service without entering in it to modify just the
interaction with the client.
2) mode = log/reg
This is similarly handled into method start of auth. And is now deeply
interlaced with the form/nobody cases. Read the actual code! Is a mess,
and a repetition of equal statements.
But why do we want the log/reg mode to be hardcoded in the class? This
prevents from showing what form, login/register, we really need at any
moment, and obliges to stick or mess with that auth->mode value from our
scripts.
Isn't this something we want to 'move out' of that method start? Isn't
this all related to 'interaction with the client' too? Cannot we be free
to decide case by case what form to show? What not just use a get value
to show the form we want? It all becomes more easy, clear, and gives
more freedom.
*Design-addressed problems with auth.
So now look at the method start of auth, take away all the mess
generated by the interlace of these two variables, and we can get a
quite clean method, that we can at least understand. In the end is
nothing complicate.
And a method we can reuse for different ways of interacting with
clients, as I said, because the interaction has been moved out of the
core method start, whose behavior should resemble that of a service,
that replies yes/no, logged_in_this_is_your_id/not_logged_in. Think it
as a three tier app. This is the inner tier, the outer tier (interaction
with the client) is moved out of the core method. And maybe one day you
can reuse it for a real three-tier architecture.
The same logic I'd apply to the perm class, where the 'Permission
denied' page should be handled out of the class, but that's a breeze in
comparison with auth.
Did I convince you?
If you are interested, please, please take a look at the patch I
published on the auth->start rationalization, try it, and tell me
something
Thanks
Gian
|