From peterspeltz@yahoo.com Sat Jan 1 20:17:48 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Sat, 1 Jan 2005 12:17:48 -0800 (PST) Subject: [Maypole] additional_data and template_args Message-ID: <20050101201748.10574.qmail@web52101.mail.yahoo.com> $r->addtional_data is called before model processes request. I have only ever used additional_data to add some template args. I would like to use it to add object specific template args except I can't because of where this method is called. ( The model class process fetches the objects. ) An example is my menu. The menu data is different when I'm listing Customers (working with the customer class) than it is if i'm viewing a Customer (working with a specific object). I'm wondering if people use additional_data in a way that it has an effect on their model class processing . If not maybe the call to $r->additional_data should happen after model processing and before view processing. thanks ===== pjs __________________________________ Do you Yahoo!? Read only the mail you want - Yahoo! Mail SpamGuard. http://promotions.yahoo.com/new_mail From brian@glassbrian.com Sun Jan 2 00:57:14 2005 From: brian@glassbrian.com (Brian Glass) Date: Sat, 01 Jan 2005 19:57:14 -0500 Subject: [Maypole] 2.05 bug in Maypole::View::Base? In-Reply-To: <20041230095331.GC17084@soto.kasei.com> References: <20041229225858.24200.qmail@web52102.mail.yahoo.com> <20041229232232.GB3886@soto.kasei.com> <41D35B8C.8030707@acm.org> <20041230095331.GC17084@soto.kasei.com> Message-ID: <41D746EA.6070503@glassbrian.com> I just ran into this in a bad way. I upgraded to 2.06 and whamo, a number of pages no longer worked for me. I finally tracked it down to this 'description' bug. Now I've got 2 lines I have to regularly comment out of Maypole::View::Base::vars - 'description' and 'cgi'. It would be really nice to be able to have column named 'description' without having to hack Maypole... Tony Bowden wrote: >On Thu, Dec 30, 2004 at 01:36:12AM +0000, Dave Howorth wrote: > > >>I believe the only complete solution is to separate the namespaces. >> >> > >This is a long term goal of Class::DBI. But it's probably at least 2 >years away. > >Doing it without breaking backwards compatibility isn't the easiest >thing in the world. > > > >>or all non-column-name methods should have a prefix (e.g. >>cdbi_retrieve). >> >> > >That's just not going to happen as far as CDBI is concerned. > >What Maypole does is up to other people. > > > >>Or just possibly we could agree to the age-old convention that method >>names are verb phrases and column names are noun phrases? >> >> > >This doesn't really work for methods which return data, rather than >methods which do something. > >Tony > >_______________________________________________ >maypole mailing list >maypole@lists.netthink.co.uk >http://lists.netthink.co.uk/listinfo/maypole > > > From Dave.Howorth@acm.org Sun Jan 2 17:36:51 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Sun, 02 Jan 2005 17:36:51 +0000 Subject: [Maypole] additional_data and template_args In-Reply-To: <20050101201748.10574.qmail@web52101.mail.yahoo.com> References: <20050101201748.10574.qmail@web52101.mail.yahoo.com> Message-ID: <41D83133.2030605@acm.org> Peter Speltz wrote: > $r->addtional_data is called before model processes request. I have > only ever used additional_data to add some template args. I would > like to use it to add object specific template args except I can't > because of where this method is called. ( The model class process > fetches the objects. ) An example is my menu. The menu data is > different when I'm listing Customers (working with the customer > class) than it is if i'm viewing a Customer (working with a specific > object). > > I'm wondering if people use additional_data in a way that it has an > effect on their model class processing . If not maybe the call to > $r->additional_data should happen after model processing and before > view processing. Hi Peter, For myself, I don't think I care where additional_data gets called but I'm not sure why you want to use it. If you want additional model-related data in the template, can't you just add it in the action ($r->template_vars->{whatever} = xxx)? Or just add it directly to the object (sub whatever { return xxx })? Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.298 / Virus Database: 265.6.7 - Release Date: 30/12/04 From peterspeltz@yahoo.com Mon Jan 3 03:25:56 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Sun, 2 Jan 2005 19:25:56 -0800 (PST) Subject: [Maypole] additional_data and template_args In-Reply-To: <41D83133.2030605@acm.org> Message-ID: <20050103032556.41510.qmail@web52102.mail.yahoo.com> --- Dave Howorth wrote: > Peter Speltz wrote: > > $r->addtional_data is called before model processes request. I have > > only ever used additional_data to add some template args. I would > > like to use it to add object specific template args except I can't > > because of where this method is called. ( The model class process > > fetches the objects. ) An example is my menu. The menu data is > > different when I'm listing Customers (working with the customer > > class) than it is if i'm viewing a Customer (working with a specific > > object). > > > > I'm wondering if people use additional_data in a way that it has an > > effect on their model class processing . If not maybe the call to > > $r->additional_data should happen after model processing and before > > view processing. > > Hi Peter, > > For myself, I don't think I care where additional_data gets called but > I'm not sure why you want to use it. > > If you want additional model-related data in the template, can't you > just add it in the action ($r->template_vars->{whatever} = xxx)? > Well yeah. But .... I want it in EVERY action. The additional_data sub is good for generating dynamic template args that you want for every single request. Like a menu. Here is the general problem: In general the additional_data sub only allows you to generate class specific data for your templates. This is because of where it is called. It is called before the objects are generated. So if you go to "customer/view/21" additional_data is called before customer 21 is even retrieved from the database and object is created. This means you cant generate template args based on customer 21 object in additional_data. Here's a specific scenario: I have a generic menu. The actions displayed on the menu depend on what class/table you're looking at. So if you are at "customer/list" you will get a different menu than if you are at "repair/list". Lets say the same method generates the menu data for the template: "sub menu_data". Ok. So in Customer.pm and Repair.pm classes I define a "menu_data" sub and thus specify my menu. OK. Remember every page has a menu so I have to call that sub for every page. I do not want to put "$self->menu_data;" in every single model action. So I put it in additional_data like so: "$r->model_class->menu_data;" Follow me? Ok. That works great when I want menus solely based on classes ie the general customer and repair menus : "addnew, search, list". But *** I want menus based on objects as well. ie: "edit, delete, add a repiar to John Smith, Look at John Smiths 15 late payments, Email John Smith" . . . You see -- menu based on my objects. The difference to me is simply calling menu_data as a class or object method. However, since I have no objects when additional_data is called I can't call it as an object method there. If I COULD, my additional_data would look like this: sub additional_data { ... # get object menu if we have only one object: if (@{$r->objects} eq 1) { $r=>objects->[0]->menu_data; } # else class menu else { $r->model_class->menu_data; } Lacking this capability, I'm left with having to put the line: "$self->menu_data;" IN EVERY LAST ONE OF MY EXPORTED SUBS IN EVERY LAST CLASS IN EVERY LAST MAYPOLE APPLICATION. That's just unacceptable and i hope this gets changed unless there's good reason to leave it as it is. ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - now with 250MB free storage. Learn more. http://info.mail.yahoo.com/mail_250 From Dave.Howorth@acm.org Mon Jan 3 11:51:50 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Mon, 03 Jan 2005 11:51:50 +0000 Subject: [Maypole] additional_data and template_args In-Reply-To: <20050103032556.41510.qmail@web52102.mail.yahoo.com> References: <20050103032556.41510.qmail@web52102.mail.yahoo.com> Message-ID: <41D931D6.6010900@acm.org> Peter Speltz wrote: > In general the additional_data sub only allows you to generate class > specific data for your templates. This is because of where it is > called. It is called before the objects are generated. So if you go > to "customer/view/21" additional_data is called before customer 21 is > even retrieved from the database and object is created. This means > you cant generate template args based on customer 21 object in > additional_data. ... > So in Customer.pm and Repair.pm classes I define a "menu_data" sub > and thus specify my menu. ... > That works great when I want menus solely based on classes ie the > general customer and repair menus : "addnew, search, list". But *** > I want menus based on objects as well. ie: "edit, delete, add a > repiar to John Smith, Look at John Smiths 15 late payments, Email > John Smith" . . . You see -- menu based on my objects. The > difference to me is simply calling menu_data as a class or object > method. ... > my additional_data would look like this: > sub additional_data { > ... > # get object menu if we have only one object: > if (@{$r->objects} eq 1) { > $r=>objects->[0]->menu_data; > } > # else class menu > else { > $r->model_class->menu_data; > } If I've understood you properly, you have, or would have, a method called menu_data in your model subclasses. When it's called it generates some object-specific data structure or text string and attaches it to the template_args hash so it is made available as a template variable. If that's so, I think there's a simpler solution. Delete the last line of menu_data! Don't attach the data structure to a template variable, just return the data structure directly. Then change where it's called. Instead of calling it in additional_data, call it directly as an object method in the template: [% menu = customer.menu_data %] Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.298 / Virus Database: 265.6.7 - Release Date: 30/12/04 From Dave.Howorth@acm.org Mon Jan 3 18:27:05 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Mon, 03 Jan 2005 18:27:05 +0000 Subject: [Maypole] listing Maypole actions in a template Message-ID: <41D98E79.5010103@acm.org> I needed to get a list of the available actions for a class to put into a template. In case that's of use to anyone else, here's what I did. First, I wrote a function to identify all the actions in a model class: sub actions { my ($model_class_name) = @_; use Class::Inspector; my @actions; for my $method (@{Class::Inspector->methods($model_class_name)}) { push @actions, $method if $model_class_name->is_public($method); } return \@actions; } I put it in my driver class and added this line to my additional_data() function: $r->template_args->{actions} = \&actions; Now in my templates I can say: [% list_of_actions = actions("BeerDB::Brewery") %] which suits my use case. An alternative would be to make the function be a method of the base model class and change its first line to extract the class of its invoker. Then you could invoke it as an object method in the template. Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.298 / Virus Database: 265.6.7 - Release Date: 30/12/04 From sf@flacks.net Tue Jan 4 03:00:10 2005 From: sf@flacks.net (Simon Flack) Date: Tue, 04 Jan 2005 03:00:10 +0000 Subject: [Maypole] additional_data and template_args In-Reply-To: <20050101201748.10574.qmail@web52101.mail.yahoo.com> References: <20050101201748.10574.qmail@web52101.mail.yahoo.com> Message-ID: <41DA06BA.40105@flacks.net> Peter Speltz wrote: > $r->addtional_data is called before model processes request. I have only ever > used additional_data to add some template args. I would like to use it to add > object specific template args except I can't because of where this method is > called. ( The model class process fetches the objects. ) An example is my menu. > The menu data is different when I'm listing Customers (working with the > customer class) than it is if i'm viewing a Customer (working with a specific > object). > > I'm wondering if people use additional_data in a way that it has an effect on > their model class processing . If not maybe the call to $r->additional_data > should happen after model processing and before view processing. I've been thinking of adding another method like additional_data which would be called before the view is processed. I'll bear this in mind when I look at refactoring the Maypole handler. Thanks Simon From peterspeltz@yahoo.com Tue Jan 4 04:55:26 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Mon, 3 Jan 2005 20:55:26 -0800 (PST) Subject: [Maypole] additional_data and template_args In-Reply-To: <41D931D6.6010900@acm.org> Message-ID: <20050104045526.46526.qmail@web52102.mail.yahoo.com> > If I've understood you properly, you have, or would have, a method > called menu_data in your model subclasses. When it's called it generates > some object-specific data structure or text string and attaches it to > the template_args hash so it is made available as a template variable. > object-specific or class-specific depending on if its called how it's called. > If that's so, I think there's a simpler solution. Delete the last line > of menu_data! Don't attach the data structure to a template variable, > just return the data structure directly. Then change where it's called. > Instead of calling it in additional_data, call it directly as an object > method in the template: [% menu = customer.menu_data %] > Still really the same problem though. You need to put that in every template you want menu data or put it in a template that it is included in every template. It'd be something like: [% IF objects.size == 1; obj = objects.0; ELSE; USE obj = Class("$classmetadata.name"); END; menu = obj.menu_data; %] Truth is though, i have a single wrapper I use all my pages within so I only need to put that in there and that's a fine solution for now. But i'd much rather just put it in additional_data once and be done with it. Aslo, maybe someone else's templating system isn't as cool as TT and they don't have wrappers or includes. It may be a problem. thanks ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - Easier than ever with enhanced search. Learn more. http://info.mail.yahoo.com/mail_250 From dhoworth@mrc-lmb.cam.ac.uk Tue Jan 4 11:07:28 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Tue, 04 Jan 2005 11:07:28 +0000 Subject: [Maypole] additional_data and template_args In-Reply-To: <20050104045526.46526.qmail@web52102.mail.yahoo.com> References: <20050104045526.46526.qmail@web52102.mail.yahoo.com> Message-ID: <41DA78F0.8020800@mrc-lmb.cam.ac.uk> Hi Peter > Still really the same problem though. You need to put that in every template > you want menu data or put it in a template that it is included in every > template. It'd be something like: > [% IF objects.size == 1; obj = objects.0; > ELSE; USE obj = Class("$classmetadata.name"); > END; > menu = obj.menu_data; > %] > > Truth is though, i have a single wrapper I use all my pages within so I only > need to put that in there and that's a fine solution for now. But i'd much > rather just put it in additional_data once and be done with it. Aslo, maybe > someone else's templating system isn't as cool as TT and they don't have > wrappers or includes. It may be a problem. Ah, OK, I see a little more clearly what you're saying. In that case just delay calling menu_data. Take your additional_data code and make it into a method of the request class: sub get_menu_data { my $r = shift; # get object menu if we have only one object: if (@{$r->objects} eq 1) { $r=>objects->[0]->menu_data; } # else class menu else { $r->model_class->menu_data; } } Then in your template you write [% menu = request.get_menu_data %] I hope :) Cheers, Dave From dhoworth@mrc-lmb.cam.ac.uk Tue Jan 4 14:44:58 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Tue, 04 Jan 2005 14:44:58 +0000 Subject: [Maypole] 2.05 bug in Maypole::View::Base? In-Reply-To: <41D746EA.6070503@glassbrian.com> References: <20041229225858.24200.qmail@web52102.mail.yahoo.com> <20041229232232.GB3886@soto.kasei.com> <41D35B8C.8030707@acm.org> <20041230095331.GC17084@soto.kasei.com> <41D746EA.6070503@glassbrian.com> Message-ID: <41DAABEA.2010105@mrc-lmb.cam.ac.uk> Brian Glass wrote: > I just ran into this in a bad way. I upgraded to 2.06 and whamo, a > number of pages no longer worked for me. I finally tracked it down to > this 'description' bug. Now I've got 2 lines I have to regularly comment > out of Maypole::View::Base::vars - 'description' and 'cgi'. > > It would be really nice to be able to have column named 'description' > without having to hack Maypole... I just ran into this too :( I would also vote that being able to have a column called description is the priority. Perhaps the class method can be renamed something less likely to conflict, like maypole_model_class_description()? That can't cause backwards compatibility problems since in previous releases it wasn't implemented properly anyway! I must offer my apologies to Peter for sidetracking his initial report - sorry. Also, while checking the code in M-V-Base I noticed an oddity: my %args = ( request => $r, objects => $r->objects, base => $base, config => $r->config # ... ); if ($class) { my $classmeta = $args{classmetadata} ||= {}; $classmeta->{name} ||= $class; I think that my $classmeta = $args{classmetadata} ||= {}; should be my $classmeta = $r->template_args->{classmetadata} ||= {}; to allow people to override the classmetadata (even to work around the description problem!). Cheers, Dave From peterspeltz@yahoo.com Tue Jan 4 15:33:57 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Tue, 4 Jan 2005 07:33:57 -0800 (PST) Subject: [Maypole] additional_data and template_args In-Reply-To: <41DA78F0.8020800@mrc-lmb.cam.ac.uk> Message-ID: <20050104153357.46599.qmail@web52110.mail.yahoo.com> --- Dave Howorth wrote: > Hi Peter > > > Still really the same problem though. You need to put that in every > template > > you want menu data or put it in a template that it is included in every > > template. It'd be something like: > > [% IF objects.size == 1; obj = objects.0; > > ELSE; USE obj = Class("$classmetadata.name"); > > END; > > menu = obj.menu_data; > > %] > > > > Truth is though, i have a single wrapper I use all my pages within so I > only > > need to put that in there and that's a fine solution for now. But i'd much > > rather just put it in additional_data once and be done with it. Aslo, maybe > > someone else's templating system isn't as cool as TT and they don't have > > wrappers or includes. It may be a problem. > > Ah, OK, I see a little more clearly what you're saying. In that case > just delay calling menu_data. Take your additional_data code and make it > into a method of the request class: > > sub get_menu_data { > my $r = shift; > # get object menu if we have only one object: > if (@{$r->objects} eq 1) { > $r=>objects->[0]->menu_data; > } > # else class menu > else { > $r->model_class->menu_data; > } > } > > Then in your template you write [% menu = request.get_menu_data %] > > I hope :) > Yeah. I like this better. Then if maypole gets patched as Simon's thinking of doing, I can just move the call to additional_args, or whatever sub . thanks Dave. ===== pjs __________________________________ Do you Yahoo!? Read only the mail you want - Yahoo! Mail SpamGuard. http://promotions.yahoo.com/new_mail From dhoworth@mrc-lmb.cam.ac.uk Tue Jan 4 15:55:18 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Tue, 04 Jan 2005 15:55:18 +0000 Subject: [Maypole] 2.05 bug in Maypole::View::Base? In-Reply-To: <41DAABEA.2010105@mrc-lmb.cam.ac.uk> References: <20041229225858.24200.qmail@web52102.mail.yahoo.com> <20041229232232.GB3886@soto.kasei.com> <41D35B8C.8030707@acm.org> <20041230095331.GC17084@soto.kasei.com> <41D746EA.6070503@glassbrian.com> <41DAABEA.2010105@mrc-lmb.cam.ac.uk> Message-ID: <41DABC66.8010700@mrc-lmb.cam.ac.uk> > Also, while checking the code in M-V-Base I noticed an oddity: > > my %args = ( > request => $r, > objects => $r->objects, > base => $base, > config => $r->config > > # ... > ); > if ($class) { > my $classmeta = $args{classmetadata} ||= {}; > $classmeta->{name} ||= $class; > > I think that > my $classmeta = $args{classmetadata} ||= {}; > should be > my $classmeta = $r->template_args->{classmetadata} ||= {}; > to allow people to override the classmetadata (even to work around the > description problem!). Doh, shoot first; ask questions later ... If you make the change I suggested above, then you also need to add: $args{ classmetadata } = $classmeta; at the end of the list of classmeta assignments. Then it does appear to work. Cheers, Dave From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 5 09:57:53 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 05 Jan 2005 09:57:53 +0000 Subject: [Maypole] 2.05 bug in Maypole::View::Base? In-Reply-To: <41DAABEA.2010105@mrc-lmb.cam.ac.uk> References: <20041229225858.24200.qmail@web52102.mail.yahoo.com> <20041229232232.GB3886@soto.kasei.com> <41D35B8C.8030707@acm.org> <20041230095331.GC17084@soto.kasei.com> <41D746EA.6070503@glassbrian.com> <41DAABEA.2010105@mrc-lmb.cam.ac.uk> Message-ID: <41DBBA21.3090008@mrc-lmb.cam.ac.uk> >> I just ran into this in a bad way. I upgraded to 2.06 and whamo, a >> number of pages no longer worked for me. I finally tracked it down to >> this 'description' bug. Now I've got 2 lines I have to regularly >> comment out of Maypole::View::Base::vars - 'description' and 'cgi'. >> >> It would be really nice to be able to have column named 'description' >> without having to hack Maypole... I wrote: > I would also vote that being able to have a column called description is > the priority. Perhaps the class method can be renamed something less > likely to conflict, like maypole_model_class_description()? That can't > cause backwards compatibility problems since in previous releases it > wasn't implemented properly anyway! I thought about this overnight and would like to change my vote. Instead of renaming the class description method, I suggest we trash it! There are two reasons: 1/ Unnecessary complexity Nobody is using this feature. The implementation has been broken for quite a while and nobody has complained, whereas several people have been using columns called 'description'. So it's just a pointless burden to maintain the code and documentation. It's also one more function point that newcomers have to learn and remember. 2/ Separation of concerns The purpose of this method is to return a text string for display on web pages. Such text should be written by a web designer, not a Perl programmer. That way it can be easily changed when the site is redesigned or translated into another language. Equivalent functionality can easily be provided directly in TT templates. Clear separation of concerns is one of Maypole's primary design goals. So I believe the best solution is just to remove the description method from the interface. Cheers, Dave From marcus@thefeed.no Wed Jan 5 12:05:55 2005 From: marcus@thefeed.no (Marcus Ramberg) Date: Wed, 05 Jan 2005 13:05:55 +0100 Subject: [Maypole] [Fwd: CPAN Upload: M/MR/MRAMBERG/Maypole-Plugin-Upload-0.01.tar.gz] Message-ID: <41DBD823.50101@thefeed.no> This is a multi-part message in MIME format. --------------010802070501020705090301 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit --------------010802070501020705090301 Content-Type: message/rfc822; name="CPAN Upload: M/MR/MRAMBERG/Maypole-Plugin-Upload-0.01.tar.gz" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="CPAN Upload: M/MR/MRAMBERG/Maypole-Plugin-Upload-0.01.tar.gz" Return-Path: Delivered-To: marcus@thefeed.no Received: (qmail 3565 invoked by uid 64020); 5 Jan 2005 11:56:54 -0000 Received: from unknown (HELO pause.perl.org) (195.149.117.110) by 0 with SMTP; 5 Jan 2005 11:56:54 -0000 Received: from pause.perl.org (localhost [127.0.0.1]) by pause.perl.org (8.12.3/8.12.3/Debian-7.1) with ESMTP id j05Bvv64008694 for ; Wed, 5 Jan 2005 12:57:57 +0100 Received: (from root@localhost) by pause.perl.org (8.12.3/8.12.3/Debian-7.1) id j05BvvNK008692; Wed, 5 Jan 2005 12:57:57 +0100 Date: Wed, 5 Jan 2005 12:57:57 +0100 Message-Id: <200501051157.j05BvvNK008692@pause.perl.org> MIME-Version: 1.0 Subject: CPAN Upload: M/MR/MRAMBERG/Maypole-Plugin-Upload-0.01.tar.gz Content-Type: Text/Plain; Charset=UTF-8 Reply-To: cpan-testers@perl.org To: "Marcus Ramberg" From: PAUSE Content-Transfer-Encoding: quoted-printable The uploaded file Maypole-Plugin-Upload-0.01.tar.gz has entered CPAN as file: $CPAN/authors/id/M/MR/MRAMBERG/Maypole-Plugin-Upload-0.01.tar.gz size: 2294 bytes md5: 0acc05104f6ec2642f8b5007a0651edb No action is required on your part Request entered by: MRAMBERG (Marcus Ramberg) Request entered on: Wed, 05 Jan 2005 11:56:17 GMT Request completed: Wed, 05 Jan 2005 11:57:56 GMT Thanks, --=20 paused, v460 --------------010802070501020705090301-- From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 5 15:04:14 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 05 Jan 2005 15:04:14 +0000 Subject: [Maypole] template-based loader In-Reply-To: <41D167A2.9080308@acm.org> References: <20041227234251.GB3022@soto.kasei.com> <20041228034424.34441.qmail@web52106.mail.yahoo.com> <20041228102901.GA16903@soto.kasei.com> <41D167A2.9080308@acm.org> Message-ID: <41DC01EE.1080502@mrc-lmb.cam.ac.uk> > To answer Peter's question from another mail in this thread, yes I have > continued developing my loader. It can generate display strings as I > describe above that work for me. It's not finished and I'm not convinced > that the method it uses is the best approach to the problem even for me > let alone anyone else. But it has nailed that issue for me sufficiently > that I can move on to other issues for now and get on with developing my > application. I'll post another snapshot of it next week when I get back > to work. I've just posted the new snapshot. It's at: There's an updated template and plugin and a consequent new BeerDB.pm Cheers, Dave From peterspeltz@yahoo.com Fri Jan 7 02:54:30 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Thu, 6 Jan 2005 18:54:30 -0800 (PST) Subject: [Maypole] listing Maypole actions in a template In-Reply-To: <41D98E79.5010103@acm.org> Message-ID: <20050107025431.86011.qmail@web52106.mail.yahoo.com> --- Dave Howorth wrote: > I needed to get a list of the available actions for a class to put into > a template. In case that's of use to anyone else, here's what I did. > > First, I wrote a function to identify all the actions in a model class: > > sub actions > { > my ($model_class_name) = @_; > use Class::Inspector; > my @actions; > for my $method (@{Class::Inspector->methods($model_class_name)}) { > push @actions, $method if $model_class_name->is_public($method); > } > > return \@actions; > } > > I put it in my driver class and added this line to my additional_data() > function: > > $r->template_args->{actions} = \&actions; > > Now in my templates I can say: > > [% list_of_actions = actions("BeerDB::Brewery") %] > > which suits my use case. An alternative would be to make the function be > a method of the base model class and change its first line to extract > the class of its invoker. Then you could invoke it as an object method > in the template. > > Cheers, Dave > This is cool Dave. It got me thinking Maybe a Maypole::Plugin::Menu would be feasible. Also a simple menu template should ship with Maypole. It would be great for just starting with Maypole and throughout production to have links to all possible actions handy. I probably shouldn't admit this but I debugged for a half hour once before i realized I hadn't "Exported" my action. A simple menu template would just take your action sub and make html links out of em. Maybe have a sub, "action_names" in the model equivalent to column_names but for methods. A more complex system could be put in a Maypole::Plugin::Menu . It be cool to have: -- A way to distinguish object actions and class actions. -- A way for model to customize and add additional actions from other model classes to their menus -- A "action_names" sub to specify what to call these -- Maybe different menu headings. thanks. ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - Easier than ever with enhanced search. Learn more. http://info.mail.yahoo.com/mail_250 From dhoworth@mrc-lmb.cam.ac.uk Fri Jan 7 09:57:11 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Fri, 07 Jan 2005 09:57:11 +0000 Subject: [Maypole] listing Maypole actions in a template In-Reply-To: <20050107025431.86011.qmail@web52106.mail.yahoo.com> References: <20050107025431.86011.qmail@web52106.mail.yahoo.com> Message-ID: <41DE5CF7.40302@mrc-lmb.cam.ac.uk> Peter Speltz wrote: > This is cool Dave. Thanks! > It got me thinking Maybe a Maypole::Plugin::Menu would be feasible. Sounds a good idea. > -- A way to distinguish object actions and class actions. AFAIK, the only way in general to tell is to read the code, so this would have to be indicated explicitly, perhaps by an extra attribute. > -- A way for model to customize and add additional actions from other > model classes to their menus I think it would be very useful to have a general way to plug in additional functionality to models (rather than the list of use this; use that; that you see at the start of Maypole::Model::CDBI). I think Sebastian has added code to Class::DBI::Loader to help with this and I think Simon's considering the best way to handle it in Maypole. > -- A "action_names" sub to specify what to call these I'd suggest an alternative here. The names you want are text strings for display, so IMHO they should NOT be generated in code. They should be generated by web-designers, marketroids or localisers. The actions themselves have valid identifiers so the simplest scheme is just to write an action_names.tt and PROCESS that: [%- action_names = { view = 'View Item' register = 'Register for a Subscription' etc = 'Whatever You Want' } -%] Or maybe use the magical 'global' template variable. [% global.action_names = { ...} %] Hmm, now if I generalize that argument, do I believe that column and table display names should be generated the same way? I wonder. I'll think about that for a bit but there could be another revision of my loader-generator on the way! Cheers, Dave From peterspeltz@yahoo.com Sat Jan 8 05:21:51 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Fri, 7 Jan 2005 21:21:51 -0800 (PST) Subject: [Maypole] listing Maypole actions in a template In-Reply-To: <41DE5CF7.40302@mrc-lmb.cam.ac.uk> Message-ID: <20050108052151.18661.qmail@web52108.mail.yahoo.com> --- Dave Howorth wrote: > Peter Speltz wrote: > > This is cool Dave. > > Thanks! > > > It got me thinking Maybe a Maypole::Plugin::Menu would be feasible. > > Sounds a good idea. > > > -- A way to distinguish object actions and class actions. > > AFAIK, the only way in general to tell is to read the code, so this > would have to be indicated explicitly, perhaps by an extra attribute. > The attributes package is pretty cool and would work nicely I think. But what attributes do we need? Class or Object seems essential. What about an attr to declare whether it should show up on the menu? Or maybe if you declare it as Object or Class it means you want it on the menu? sub edit : Exported : Object { . . . } sub list : Exported : Class { . . . } With this Maypole::Plugin::Menu could automatically make URLS like : /beerdb/view/21 > > -- A way for model to customize and add additional actions from other > > model classes to their menus > I think it would be very useful to have a general way to plug in > additional functionality to models (rather than the list of use this; > use that; that you see at the start of Maypole::Model::CDBI). I think > Sebastian has added code to Class::DBI::Loader to help with this and I > think Simon's considering the best way to handle it in Maypole. > I think I wasn't thinking that deeply. IN my prototype of this Plugin, model classes customize their menus by simply making action links for whatever Classes and Actions they want and putting them in template args. Some background info: Originally, I was thinking a method like $r->menu would return a hashref of HTML::Element links for all the actions in the model_class. However maybe just the URL, and a human readable action name would be sufficient and the templates can DWTW. NOW all the work from $r->menu is done in an "action_links" sub. the action_links by default just uses $r->model_class and $r->model_class->actions (you're actions sub) to make links. However it can optionally take a model_class and a list of actions plus additional query params. This way it can make any combination of Class/Action links. Example: Assume a Beer has a brewery_id. You go to the "brewery/view/1" page. Then in Brewery::view you can say: sub view : Exported : Object { # Object has nothing to do with this example . . . my $brewery = $r->objects->[0]; my $links = $r->action_links(model_class => 'Beer', actions => [ 'create_new', 'list'], brewery_id => $brewery->id); # This would return links with URL's: #/beerdb/beer/create_new/?brewery_id=1 # create new beer at that brewery #/beerdb/beer/list/?brewery_id=1 # list all beers at that brewery # obviously the list and create_new subs are custom (but not very). # add menu to template $r->template_args->{menu_items} = $r->menu; # all brewery actions $r->template_args->{additional_menu_items} = $links; # perhaps merge hashes somehow. Easy in TT but not in perl # that i've found. } That's how my prototype allows model classes to customize there menus. What do you think? > > -- A "action_names" sub to specify what to call these > > I'd suggest an alternative here. The names you want are text strings for > display, so IMHO they should NOT be generated in code. They should be > generated by web-designers, marketroids or localisers. The actions > themselves have valid identifiers so the simplest scheme is just to > write an action_names.tt and PROCESS that: > > [%- action_names = { > view = 'View Item' > register = 'Register for a Subscription' > etc = 'Whatever You Want' > } > -%] > > Or maybe use the magical 'global' template variable. > [% global.action_names = { ...} %] > > Hmm, now if I generalize that argument, do I believe that column and > table display names should be generated the same way? I wonder. I'll > think about that for a bit but there could be another revision of my > loader-generator on the way! > Exactly my reasoning. Consistency is crucial. However i was deluded about how column_names is used. It's used in FOR loops in templates but Template authors don't have to use them. Similaryly "action_names" could be used just to give a starting point. Also, as I said above, I was wanting to generate html::element links and needed content between . I used "action_names" for that. However, i think just making $r->menu return a hash of { url => action_name => action => } rather than HTML::Element links made from that data may be a better approach. Then menu template can make links or whatever it wants. However I also like the HTML::Element approach cause it is efficient in that you don't look up data again to make links when you wanted them all along in the first place (when the data was generated). follow me? Maybe an option to think about. thanks. ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - 250MB free storage. Do more. Manage less. http://info.mail.yahoo.com/mail_250 From simonf@cshl.edu Sun Jan 9 00:33:14 2005 From: simonf@cshl.edu (Vsevolod (Simon) Ilyushchenko) Date: Sat, 08 Jan 2005 19:33:14 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks Message-ID: <41E07BCA.6070103@cshl.edu> Hi, I develop simple Perl database-driven web applications at work. Over the last 2-3 years I've come up with a framework that is similar to Maypole (though much simpler and less neat, of course). My goal is to stabilize my code on a fairly standard framework. I don't want my employer be stuck with a non-standard code that is solving rather standard problems if I am run over by a commuter train (or, less probably, we hire more developers). I'd like a not-very-experienced Joe Developer from the street be able to come in and find an intuitive, familiar system. The upside of my situation is that I develop alone, the code base is not large and can easily swap one component for another. The downside is that I develop alone and my time is limited. I don't expect to get definitive advice here, but I'd like to find out if I've missed some important considerations. So far I can see these choices: 1. Release my code as yet another framework and promote it. 2. Go with Maypole. 3. Go with the future Catalyst. 4. Go with something else Perl-based: Apache::AxKit? 5. Switch to Java. 1 is wonderful for the ego, but not quite realistic given the time constraints. And I don't think I am as good as Maypole developers. Plus, I HATE duplicating effort. I'd rather pick an industry standard and go with it. (If I were writing in Java, it'd be much easier. :) I'd just use Struts or Spring.) 2 and 3: I've read some recent threads on this list and AFAIU, Maypole is fairly actively maintained, though not by Simon Cozens, and Sebastian Riedel is developing Catalyst. My problem with Maypole is that it's using Class::DBI and TT (I use SPOPS and Mason), but this is more aesthetical than practical. Class::DBI lacks a few features that I like in SPOPS, and I am more used to Mason, but I can switch if I have a business case to do so. However, I've read arguments here about being component-independent vs being tightly coupled to one good component set, as well as other arguments. Is there a certain direction where things are going now, or is the existence/viability of Maypole up in the air? When is Catalyst expected to appear? 4. I don't know of anything else that is comparable to Maypole. Most other similar Perl projects are too simplistic (CGI::Application) or too abstract (Apache::AxKit). OpenInteract, much as I respect Chris Winters, is an overkill too. Am I missing something else? 5. Java. I am not very optimistic about the rates of development of Perl web frameworks, but at least the situation is slowly improving. However, Java is far ahead of Perl in terms of standard approaches to web apps (Spring, Hibernate) and available expertise. If I were starting a mid-sized project with several developers now, I'd go with Java in an eyeblink, though Perl is still closer to my heart as a language. However, I am just a single developer on small projects. OTOH, if a year or two down the road I'm forced to port my code either to Perl 6 or to Java, I would have a very hard choice to make. I would appreciate any information and/or advice. Thanks, Simon -- Simon (Vsevolod ILyushchenko) simonf@cshl.edu http://www.simonf.com Terrorism is a tactic and so to declare war on terrorism is equivalent to Roosevelt's declaring war on blitzkrieg. Zbigniew Brzezinski, U.S. national security advisor, 1977-81 From peterspeltz@yahoo.com Sun Jan 9 04:05:15 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Sat, 8 Jan 2005 20:05:15 -0800 (PST) Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E07BCA.6070103@cshl.edu> Message-ID: <20050109040515.33247.qmail@web52110.mail.yahoo.com> Hi. Others will probably have more useful info for you but I'm happy to give you my two cents on Maypole. I LOVE it. I'm in a similar situation as you -- I'm a solo developer for a small business. And like you, i have a better chance of getting hit by a train than getting a coworker. I started out writing my own system but a few weeks into it found Maypole thanks to my laziness. My boss and I looked at it and decided to go with it. It was the best decision we've ever made. I think Maypole has a loyal following and isn't going anywhere. I love it because it is powerful, yet simple and intuitive and fun to use once you get the hang of it. I'm a complete beginner and it took me about two months from downloading it to get the hang of it and be productive. For some it didn't suit their style but for this beginning perl programmer, it was perfect. Pluses Maypole has for beginners are : User session management plugin There is no need to know the modperl api to use modperl. You pretty much just write the business logic functions and HTML Templates and Maypole does the rest. It is easy to customize. I'd say, your time wouldn't be wasted learning Maypole and making a SPOPS model class for it. That be a good benefit to the community. HTH --- "Vsevolod (Simon) Ilyushchenko" wrote: > Hi, > > I develop simple Perl database-driven web applications at work. Over the > last 2-3 years I've come up with a framework that is similar to Maypole > (though much simpler and less neat, of course). > > My goal is to stabilize my code on a fairly standard framework. I don't > want my employer be stuck with a non-standard code that is solving > rather standard problems if I am run over by a commuter train (or, less > probably, we hire more developers). I'd like a not-very-experienced Joe > Developer from the street be able to come in and find an intuitive, > familiar system. > > The upside of my situation is that I develop alone, the code base is not > large and can easily swap one component for another. The downside is > that I develop alone and my time is limited. > > I don't expect to get definitive advice here, but I'd like to find out > if I've missed some important considerations. > > So far I can see these choices: > > 1. Release my code as yet another framework and promote it. > 2. Go with Maypole. > 3. Go with the future Catalyst. > 4. Go with something else Perl-based: Apache::AxKit? > 5. Switch to Java. > > 1 is wonderful for the ego, but not quite realistic given the time > constraints. And I don't think I am as good as Maypole developers. Plus, > I HATE duplicating effort. I'd rather pick an industry standard and go > with it. (If I were writing in Java, it'd be much easier. :) I'd just > use Struts or Spring.) > > 2 and 3: I've read some recent threads on this list and AFAIU, Maypole > is fairly actively maintained, though not by Simon Cozens, and Sebastian > Riedel is developing Catalyst. My problem with Maypole is that it's > using Class::DBI and TT (I use SPOPS and Mason), but this is more > aesthetical than practical. Class::DBI lacks a few features that > I like in SPOPS, and I am more used to Mason, but I can switch if I have > a business case to do so. > > However, I've read arguments here about being component-independent vs > being tightly coupled to one good component set, as well as other > arguments. Is there a certain direction where things are going now, or > is the existence/viability of Maypole up in the air? > > When is Catalyst expected to appear? > > 4. I don't know of anything else that is comparable to Maypole. Most > other similar Perl projects are too simplistic (CGI::Application) or too > abstract (Apache::AxKit). OpenInteract, much as I respect Chris Winters, > is an overkill too. Am I missing something else? > > 5. Java. I am not very optimistic about the rates of development of Perl > web frameworks, but at least the situation is slowly improving. However, > Java is far ahead of Perl in terms of standard approaches to web apps > (Spring, Hibernate) and available expertise. If I were starting a > mid-sized project with several developers now, I'd go with Java in an > eyeblink, though Perl is still closer to my heart as a language. > However, I am just a single developer on small projects. OTOH, if a year > or two down the road I'm forced to port my code either to Perl 6 or to > Java, I would have a very hard choice to make. > > I would appreciate any information and/or advice. > > Thanks, > Simon > -- > > Simon (Vsevolod ILyushchenko) simonf@cshl.edu > http://www.simonf.com > > Terrorism is a tactic and so to declare war on terrorism > is equivalent to Roosevelt's declaring war on blitzkrieg. > > Zbigniew Brzezinski, U.S. national security advisor, 1977-81 > > _______________________________________________ > maypole mailing list > maypole@lists.netthink.co.uk > http://lists.netthink.co.uk/listinfo/maypole > ===== pjs __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com From Dave.Howorth@acm.org Sun Jan 9 14:32:36 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Sun, 09 Jan 2005 14:32:36 +0000 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E07BCA.6070103@cshl.edu> References: <41E07BCA.6070103@cshl.edu> Message-ID: <41E14084.5020405@acm.org> Vsevolod (Simon) Ilyushchenko wrote: > My goal is to stabilize my code on a fairly standard framework. > 2 and 3: I've read some recent threads on this list and AFAIU, > Maypole is fairly actively maintained, though not by Simon Cozens, > and Sebastian Riedel is developing Catalyst. My problem with Maypole > is that it's using Class::DBI and TT (I use SPOPS and Mason), but > this is more aesthetical than practical. Class::DBI lacks a few > features that I like in SPOPS, and I am more used to Mason, but I can > switch if I have a business case to do so. Maypole already supports Mason via MasonX::Maypole so you should look at that as regards templates. David Baird is on this list if you need any advice. You can use alternative models with Maypole, though the facilities could still use some more improvement. Simon Flack is looking at writing alternative models and that is also one of Sebastian's concerns, so I'm sure anybody who wants to add an additional model will be supported. Another alternative would be to see whether it is possible to add the features to Class::DBI, perhaps as a plugin. I feel sure Tony would support well thought-out proposals to fill gaps in CDBI's functionality. I guess it's also possible that the features already exist somewhere and you haven't yet found them; what are the main issues? > However, I've read arguments here about being component-independent > vs being tightly coupled to one good component set, as well as other > arguments. Is there a certain direction where things are going now, > or is the existence/viability of Maypole up in the air? I don't think its continued existence is in any doubt. It is still young and there are still many improvements and additions to make, but being in a position to help with those is one of its attractions to me. > If I were starting a mid-sized project with several developers now, > I'd go with Java in an eyeblink, though Perl is still closer to my > heart as a language. However, I am just a single developer on small > projects. OTOH, if a year or two down the road I'm forced to port my > code either to Perl 6 or to Java, I would have a very hard choice to > make. I'd agree with that assessment. I've only been working with Perl for a couple of years, so I'm no expert, but it does seem to me to be a community of individuals. Java always has had more of a corporate team feel to it for me. Both environments have produced some great results and there are always exceptions to the categories for both languages. As far as the future goes, I don't think there's too much point in trying to predict where to go. Perl 5 will be supported for a very long time after Perl 6 is introduced and the lists of both the available technical choices and your business evaluation criteria are likely to change before it's time to make another decision. Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.9 - Release Date: 06/01/05 From perrin@elem.com Mon Jan 10 04:06:43 2005 From: perrin@elem.com (Perrin Harkins) Date: Sun, 09 Jan 2005 23:06:43 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E07BCA.6070103@cshl.edu> References: <41E07BCA.6070103@cshl.edu> Message-ID: <41E1FF53.2020304@elem.com> Vsevolod (Simon) Ilyushchenko wrote: > Class::DBI lacks a few features that > I like in SPOPS Would you mind sharing what they are? > 4. I don't know of anything else that is comparable to Maypole. Most > other similar Perl projects are too simplistic (CGI::Application) or too > abstract (Apache::AxKit). CGI::Application has a number of plugins now that make it more interesting. Apache::PageKit might be interesting to you as well. > OpenInteract, much as I respect Chris Winters, > is an overkill too. It's a whole lot simpler than Struts or Spring... > 5. Java. I am not very optimistic about the rates of development of Perl > web frameworks, but at least the situation is slowly improving. However, > Java is far ahead of Perl in terms of standard approaches to web apps > (Spring, Hibernate) and available expertise. I like Hibernate too, but you kind of sound like you're seeking an impossible middle ground. How can something provide more than the current perl web frameworks and yet be simpler than OpenInteract? Is there something specific you're not finding in the perl frameworks, other than a huge user community and the commercial documentation that goes along with that? - Perrin -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.9 - Release Date: 1/6/2005 From marcus@thefeed.no Mon Jan 10 10:09:30 2005 From: marcus@thefeed.no (Marcus Ramberg) Date: Mon, 10 Jan 2005 11:09:30 +0100 Subject: [Maypole] Last night's CPAN releases. Message-ID: <41E2545A.3090208@thefeed.no> Hey guys. Last night I uploaded Maypole-View-Mason 0.3 and Maypole-HTTPD 0.1 to CPAN. I've been procrastenating somewhat on the Mason view, because I felt it's function was covered by MasonX::Maypole , however, after trying to use that last night, I found some limitations I couldn't live with, and some design choices I disagreed with. The limitations was mostly that it can only run on Apache. I didn't like the fact that it needs to be a base class for your maypole application, and that it overrides driver methods such as parse_args and parse_location and I didn't like the dhandler to dispatch the template names. So, Maypole::View::Mason is somewhat different, and it has a right to live. I've changed so that vars like $config $base and $request now are available to all components as global variables. %ARGS now represent the request arguments, like one is used to. I've also changed the error mode to fatal, to act more similar to Maypole::View::TT . Finally, the factory templates are updated to be similar to the latest maypole factory templates. Maypole-HTTPD was originally posted to this list by Simon Cozens, in a form not releasable to CPAN. I've cleaned it up, and submitted patches back to HTTP::Server::Simple, as well as uploaded HTTP::Server::Simple::Static to CPAN. Now Maypole-HTTPD is updated to be based on these modules, and works with Maypole-2.06. I find it a very useful tool when developing my applications, as error messages are spit directly to stdout, and it's much easier to restart your web-server. I'm also planning on using it for allowing users to run mitiki on their own computers once I release that. Note that it also works fine with recently released versions of Maypole-Plugin-Authentication-UsersSessionCookie, and Maypole-Plugin-Upload Marcus From simonf@cshl.edu Mon Jan 10 15:24:20 2005 From: simonf@cshl.edu (Vsevolod (Simon) Ilyushchenko) Date: Mon, 10 Jan 2005 10:24:20 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E1FF53.2020304@elem.com> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> Message-ID: <41E29E24.4070809@cshl.edu> Perrin Harkins wrote: > Vsevolod (Simon) Ilyushchenko wrote: > >> Class::DBI lacks a few features that >> I like in SPOPS > > > Would you mind sharing what they are? They are auto-creation of instance variables based on column names (so that I don't have to specify them in configs), many_to_many relationships (though maybe has_many can be tweaked to support that) and lack of auto-save for child objects in relationships. >> 4. I don't know of anything else that is comparable to Maypole. Most >> other similar Perl projects are too simplistic (CGI::Application) or >> too abstract (Apache::AxKit). > > > CGI::Application has a number of plugins now that make it more > interesting. Apache::PageKit might be interesting to you as well. AFAIU it does not have fetching objects from the database by class name and id as a defining feature. Ditto about CGI::Application. Plugins to the latter may help, but I'd rather go with a single comprehensive package. >> OpenInteract, much as I respect Chris Winters, is an overkill too. > > > It's a whole lot simpler than Struts or Spring... Right, but the latter have the benefit of a lot more developer input, as well as documentation and books. >> 5. Java. I am not very optimistic about the rates of development of >> Perl web frameworks, but at least the situation is slowly improving. >> However, Java is far ahead of Perl in terms of standard approaches to >> web apps (Spring, Hibernate) and available expertise. > > > I like Hibernate too, but you kind of sound like you're seeking an > impossible middle ground. Well, if my question was simple, I'd figured it out myself. :) > How can something provide more than the > current perl web frameworks and yet be simpler than OpenInteract? Is > there something specific you're not finding in the perl frameworks, > other than a huge user community and the commercial documentation that > goes along with that? I guess the promise that it will be around and not abandoned for a good while. Maypole looks good in this regard, but I wanted to check. Thanks, Simon -- Simon (Vsevolod ILyushchenko) simonf@cshl.edu http://www.simonf.com Terrorism is a tactic and so to declare war on terrorism is equivalent to Roosevelt's declaring war on blitzkrieg. Zbigniew Brzezinski, U.S. national security advisor, 1977-81 From sethg@ropine.com Mon Jan 10 16:35:59 2005 From: sethg@ropine.com (Seth Gordon) Date: Mon, 10 Jan 2005 11:35:59 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E07BCA.6070103@cshl.edu> References: <41E07BCA.6070103@cshl.edu> Message-ID: <41E2AEEF.1050507@ropine.com> > 5. Java. I am not very optimistic about the rates of development of Perl > web frameworks, but at least the situation is slowly improving. However, > Java is far ahead of Perl in terms of standard approaches to web apps > (Spring, Hibernate) and available expertise. If I were starting a > mid-sized project with several developers now, I'd go with Java in an > eyeblink, though Perl is still closer to my heart as a language. > However, I am just a single developer on small projects. OTOH, if a year > or two down the road I'm forced to port my code either to Perl 6 or to > Java, I would have a very hard choice to make. As someone who works with J2EE for a living, I would strongly advise *against* Java. With Class::DBI::Loader (and, from what I can tell, SPOPS::DBI), you can define a class to be based on a certain database table, and objects in the class will, by default, have getters and setters named for the fields in the table; Class::DBI::Loader will look at the database schema and generate the appropriate methods for you. The only thing you need to provide is the is-a/has-a relationships. This kind of flexibility is simply not possible in Java, because Java requires the names for all of your methods to be available at compile time. So you essentially need to maintain three parallel versions of your database schema: one in the actual database, one in the Java classes or interfaces that model the database, and one for the framework to use to map between them. (To be fair, Hibernate appears to have tools that can generate the class from the schema or vice versa ... but I generally distrust code-generation tools.) I don't know enough to take sides in the religious war between static and dynamic languages, but I think once you have a program that spends a significant amount of time interacting with a system outside its own language framework (e.g., querying and updating a database), that program should be written in a dynamic language. -- "If John Kerry was the last best hope for the Republic ... then maybe it wasn't worth saving in the first place. I don't believe that, though. And neither do you." --Dan Layman-Kennedy // seth gordon // sethg@ropine.com // http://dynamic.ropine.com/yo/ // From rs@plusw.de Mon Jan 10 16:39:25 2005 From: rs@plusw.de (Rolf Schaufelberger) Date: Mon, 10 Jan 2005 17:39:25 +0100 Subject: [Maypole] Where do I place actions without a model ? Message-ID: <200501101739.25640.rs@plusw.de> Hi, I'm just evaluating Maypole and I didn't find any hint where I can place actions which don't relate to a model. For instance : I use Plugin::I18N and want to place some links on my page like : /setLang?lang=en in order to switch the language. Now how does a URL look like if I have no and where can I place a method which calls the lang method ? Wouldn't it make sense to fall back BeerDB ? Right now nothing at all happens when is_applicable returns 0 ? Greetings Rolf Schaufelberger rs@plusw.de From tony@kasei.com Mon Jan 10 17:04:25 2005 From: tony@kasei.com (Tony Bowden) Date: Mon, 10 Jan 2005 17:04:25 +0000 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E29E24.4070809@cshl.edu> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> Message-ID: <20050110170425.GA1188@soto.kasei.com> On Mon, Jan 10, 2005 at 10:24:20AM -0500, Vsevolod (Simon) Ilyushchenko wrote: > They are auto-creation of instance variables based on column names (so > that I don't have to specify them in configs), There are numerous Class::DBI plugins to do this. > many_to_many relationships (though maybe has_many can be tweaked to > support that) Class::DBI already supports many to many. It's not the most efficient thing in the world, but it's there. There's also scope for someone to write a proper relationship plugin for this. The main reasons I haven't done so yet is that I haven't needed it enough, and I can't come up with a nice enough interface. > lack of auto-save for child objects in relationships. What does this mean? Tony From simonf@cshl.edu Mon Jan 10 18:03:30 2005 From: simonf@cshl.edu (Vsevolod (Simon) Ilyushchenko) Date: Mon, 10 Jan 2005 13:03:30 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <20050110170425.GA1188@soto.kasei.com> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> <20050110170425.GA1188@soto.kasei.com> Message-ID: <41E2C372.1080105@cshl.edu> Tony Bowden wrote: > On Mon, Jan 10, 2005 at 10:24:20AM -0500, Vsevolod (Simon) Ilyushchenko wrote: > >>They are auto-creation of instance variables based on column names (so >>that I don't have to specify them in configs), > > > There are numerous Class::DBI plugins to do this. Oh, good, thanks. >>lack of auto-save for child objects in relationships. > > > What does this mean? Suppose I have an author object that I retrieve together with the object representing books that the author wrote. Then I add some books, remove others, and modify information for some of the books. Then I want to call author.save() and have all the relationships and book objects also saved. Simon -- Simon (Vsevolod ILyushchenko) simonf@cshl.edu http://www.simonf.com Terrorism is a tactic and so to declare war on terrorism is equivalent to Roosevelt's declaring war on blitzkrieg. Zbigniew Brzezinski, U.S. national security advisor, 1977-81 From sri@oook.de Mon Jan 10 18:38:30 2005 From: sri@oook.de (Sebastian Riedel) Date: Mon, 10 Jan 2005 19:38:30 +0100 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E2AEEF.1050507@ropine.com> References: <41E07BCA.6070103@cshl.edu> <41E2AEEF.1050507@ropine.com> Message-ID: <1105382310.13212.2.camel@localhost> Seth Gordon: > With Class::DBI::Loader (and, from what I can tell, SPOPS::DBI), you can > define a class to be based on a certain database table, and objects in > the class will, by default, have getters and setters named for the > fields in the table; Class::DBI::Loader will look at the database schema > and generate the appropriate methods for you. The only thing you need > to provide is the is-a/has-a relationships. Newer versions of Class::DBI::Loader can even generate relationships based on foreign keys for PostgreSQL and MySQL. -- sebastian From peterspeltz@yahoo.com Mon Jan 10 19:04:56 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Mon, 10 Jan 2005 11:04:56 -0800 (PST) Subject: [Maypole] Where do I place actions without a model ? In-Reply-To: <200501101739.25640.rs@plusw.de> Message-ID: <20050110190456.36169.qmail@web52105.mail.yahoo.com> --- Rolf Schaufelberger wrote: > Hi, I'm just evaluating Maypole and I didn't find any hint where I can place > actions which don't relate to a model. > > For instance : > I use Plugin::I18N and want to place some links on my page like : > /setLang?lang=en in order to switch the language. > Now how does a URL look like if I have no
and where can I place a > method which calls the lang method ? > Wouldn't it make sense to fall back > BeerDB ? Right now nothing at all happens when is_applicable returns 0 ? > This is an excellent question. I don't believe I'd want to fall back on BeerDB as that IS Maypole, the holy $r. Also i think this is true : /plain_templates_can_go_here, so it would be confusing. What would ideal solution be? Would it do to be able to have plain Models that don't relate to tables and put actions in them. so display_tables or config->ok_tables (iether will work as all display_tables get put in ok_tables ) so that it will pass the is_applicable test. That should do it for you. In Maypole, the model class is determined by the Maypole::Model::XXX::class_of method. It takes the table part of url and returns a class. If model is CDBI than it must be a real table and have a class associated with it or you don't get a class. In M::M::CDBI.pm this method looks like: sub class_of { my ( $self, $r, $table ) = @_; return $r->config->loader->_table2class($table); } so you could make it something like: sub class_of { my ( $self, $r, $table ) = @_; my $class = $r->config->loader->_table2class($table); unless ($class) { $class = "BeerDB::" . ucfirst($table); $class = undef unless $class->isa("AppropriateClass"); } return $class; } I'd be interested in a good general override for this if you come up with one. ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - Find what you need with new enhanced search. http://info.mail.yahoo.com/mail_250 From tony@kasei.com Mon Jan 10 19:07:45 2005 From: tony@kasei.com (Tony Bowden) Date: Mon, 10 Jan 2005 19:07:45 +0000 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E2C372.1080105@cshl.edu> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> <20050110170425.GA1188@soto.kasei.com> <41E2C372.1080105@cshl.edu> Message-ID: <20050110190744.GA4925@soto.kasei.com> On Mon, Jan 10, 2005 at 01:03:30PM -0500, Vsevolod (Simon) Ilyushchenko wrote: > Suppose I have an author object that I retrieve together with the object > representing books that the author wrote. Then I add some books, remove > others, and modify information for some of the books. Then I want to > call author.save() and have all the relationships and book objects also > saved. That would be fairly simple to write, unless I'm missing something. I need to ponder it a little more ... Tony From Dave.Howorth@acm.org Mon Jan 10 19:52:29 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Mon, 10 Jan 2005 19:52:29 +0000 Subject: [Maypole] Where do I place actions without a model ? In-Reply-To: <20050110190456.36169.qmail@web52105.mail.yahoo.com> References: <20050110190456.36169.qmail@web52105.mail.yahoo.com> Message-ID: <41E2DCFD.1020302@acm.org> Peter Speltz wrote: > --- Rolf Schaufelberger wrote: >> Hi, I'm just evaluating Maypole and I didn't find any hint where I >> can place actions which don't relate to a model. >> >> For instance : I use Plugin::I18N and want to place some links on >> my page like : /setLang?lang=en in order to switch the >> language. Now how does a URL look like if I have no
and >> where can I place a method which calls the lang method ? Wouldn't >> it make sense to fall back BeerDB ? Right now nothing at all >> happens when is_applicable returns 0 ? > > This is an excellent question. I don't believe I'd want to fall back > on BeerDB as that IS Maypole, the holy $r. Also i think this is true > : /plain_templates_can_go_here, so it would be confusing. > > What would ideal solution be? Would it do to be able to have plain > Models that don't relate to tables and put actions in them. so > call. I think this is all good. IIRC, making models more flexible is something Simon Flack is pondering on. I suspect he's on holiday at the moment since we haven't heard from him since the new year, so perhaps he'll give an answer when he returns. There may be another possible answer to Rolf's original question. To make the language setting mean anything, I think you need the concept of a session, yes? If you're using Maypole::Plugin::Authentication::UserSessionCookie to provide sessions, then you can add the setLang action to the BeerDB::User class. The UserSessionCookie pod also has a brief discussion of sessions without users but I suspect it would need fleshing out a bit. Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.9 - Release Date: 06/01/05 From sri@oook.de Mon Jan 10 20:22:05 2005 From: sri@oook.de (Sebastian Riedel) Date: Mon, 10 Jan 2005 21:22:05 +0100 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E07BCA.6070103@cshl.edu> References: <41E07BCA.6070103@cshl.edu> Message-ID: <1105388525.13212.58.camel@localhost> Vsevolod (Simon) Ilyushchenko: > 1 is wonderful for the ego, but not quite realistic given the time > constraints. And I don't think I am as good as Maypole developers. Plus, > I HATE duplicating effort. I'd rather pick an industry standard and go > with it. (If I were writing in Java, it'd be much easier. :) I'd just > use Struts or Spring.) All those frameworks have their strengths, but you still have to deal with that unflexible mess called Java... The only framework that really impressed me was Ruby-on-Rails. (I've stolen lots of ideas for Catalyst from it) ;) > When is Catalyst expected to appear? It should've been released for a few weeks, but my health problems slowed everything down a bit. :( Currently it looks quite finished, only missing pieces are documentation, examples and tests... You can grab regular snapshots containing a "work in progress" PetStore application, session/authentication/i18n/formvalidator plugins, tt2/yaml-rest views and cdbi/plucene models from http://files.oook.de/Catalyst.tar.gz (testers, reviewers, helpers welcome!) It even has a logo! (feel free to make eyecandy buttons of it) =) http://files.oook.de/catalyst.png > 4. I don't know of anything else that is comparable to Maypole. Most > other similar Perl projects are too simplistic (CGI::Application) or too > abstract (Apache::AxKit). OpenInteract, much as I respect Chris Winters, > is an overkill too. Am I missing something else? Well, AxKit inherits all the bloat related to XML and OpenInteract is IMHO too huge/complex/unflexible. -- sebastian From rs@plusw.de Mon Jan 10 21:45:09 2005 From: rs@plusw.de (Rolf Schaufelberger) Date: Mon, 10 Jan 2005 22:45:09 +0100 Subject: [Maypole] Where do I place actions without a model ? In-Reply-To: <41E2DCFD.1020302@acm.org> References: <20050110190456.36169.qmail@web52105.mail.yahoo.com> <41E2DCFD.1020302@acm.org> Message-ID: <200501102245.09548.rs@plusw.de> Am Montag 10 Januar 2005 20:52 schrieb Dave Howorth: > Peter Speltz wrote: > > --- Rolf Schaufelberger wrote: > >> Hi, I'm just evaluating Maypole and I didn't find any hint where I > >> can place actions which don't relate to a model. > >> > >> For instance : I use Plugin::I18N and want to place some links on > >> my page like : /setLang?lang=en in order to switch the > >> language. Now how does a URL look like if I have no
and > >> where can I place a method which calls the lang method ? Wouldn't > >> it make sense to fall back BeerDB ? Right now nothing at all > >> happens when is_applicable returns 0 ? > > > > This is an excellent question. I don't believe I'd want to fall back > > on BeerDB as that IS Maypole, the holy $r. Also i think this is true > > > > : /plain_templates_can_go_here, so it would be confusing. > > > > What would ideal solution be? Would it do to be able to have plain > > Models that don't relate to tables and put actions in them. so > > > call. > > I think this is all good. IIRC, making models more flexible is something > Simon Flack is pondering on. I suspect he's on holiday at the moment > since we haven't heard from him since the new year, so perhaps he'll > give an answer when he returns. > > There may be another possible answer to Rolf's original question. To > make the language setting mean anything, I think you need the concept of > a session, yes? If you're using > Maypole::Plugin::Authentication::UserSessionCookie to provide sessions, > then you can add the setLang action to the BeerDB::User class. The > UserSessionCookie pod also has a brief discussion of sessions without > users but I suspect it would need fleshing out a bit. > Yes, concerning the language setting you are right with the session, this would be the next problem, since M::P::A::U creates a session only when an authentication takes place, yet I need the language selection also in my "public" part of the website, so I must simulate a login here or create a session outside the Authetication (and reuse it there). But the general question with non-model related actions is still there, and Peters solution with a dummy table may be a solution, but it's just not "clean" (don't know how to express is in english, I mean it's a workaround an no proper conceptual solution). I 've thought about a solution like starting the table part in the URL with an underscore like /_settings/setLang?lang=en and handler_guts calls Settings::setlang without checking for table existance. But this is more ore less the same than Peters solution. Greetings Rolf From peterspeltz@yahoo.com Mon Jan 10 22:16:19 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Mon, 10 Jan 2005 14:16:19 -0800 (PST) Subject: [Maypole] Where do I place actions without a model ? In-Reply-To: <200501102245.09548.rs@plusw.de> Message-ID: <20050110221619.38436.qmail@web52104.mail.yahoo.com> --- Rolf Schaufelberger wrote: > > > Yes, concerning the language setting you are right with the session, this > would be the next problem, since M::P::A::U creates a session only when an > authentication takes place, yet I need the language selection also in my > "public" part of the website, so I must simulate a login here or create a > session outside the Authetication (and reuse it there). User::set_lang() could still be used here but the user is anonymous. Just store the language setting in the session like : $r->{session}{lang} rather than in user like $r->{session}{user}{lang}. > But the general question with non-model related actions is still there, and > Peters solution with a dummy table may be a solution, but it's just not > "clean" (don't know how to express is in english, I mean it's a workaround an > > no proper conceptual solution). > I 've thought about a solution like starting the table part in the URL with > an underscore like /_settings/setLang?lang=en and handler_guts calls > Settings::setlang without checking for table existance. But this is more ore > less the same than Peters solution. > Technically the fact that maypole uses an actually table name in the url to map to a class is supposed to change. See maypole.perl.org roadmap. It will change to something more related to the Class because a single table could be the base of several different classes. There was way to long a discussion on this in a thread a few weeks ago called something like "Why does maypole use moniker to determine template directories". Anyway, when this happens the table part of the url won't really be a table part but a class part. So my solution won't be unclean then. Now, i don't really see it as unclean because it is perfectly ok to override the class_of method. Also, the name "table" given to the part of the URL to determine the class is completely arbitrary and not a very fitting name it turns out unless you are limited to all classes having a distinct table. With that in mind a better name would be "class_hint" or just "class" since all it is used for anyway is to get the class that you want to call your action with. At any rate making model classes to put general cgi scripts in may not be the best idea but it is something maypole should support and does support all beit you have to override the class_of method. Afterall, Maypole just maps a url to a class method call with args. Why should it matter whether the class is associated with a table in a database or not? Perhaps another solution may be to put general actions in the base model class? My base model class could be My::Global.pm so a url "/global/set_en?lang=en" wouldn't be so bad. > Greetings Rolf > > _______________________________________________ > maypole mailing list > maypole@lists.netthink.co.uk > http://lists.netthink.co.uk/listinfo/maypole > ===== pjs __________________________________ Do you Yahoo!? Yahoo! Mail - 250MB free storage. Do more. Manage less. http://info.mail.yahoo.com/mail_250 From perrin@elem.com Mon Jan 10 23:21:48 2005 From: perrin@elem.com (Perrin Harkins) Date: Mon, 10 Jan 2005 18:21:48 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E29E24.4070809@cshl.edu> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> Message-ID: <41E30E0C.6030900@elem.com> Vsevolod (Simon) Ilyushchenko wrote: > They are auto-creation of instance variables based on column names (so > that I don't have to specify them in configs), many_to_many > relationships (though maybe has_many can be tweaked to support that) and > lack of auto-save for child objects in relationships. Most of this was addressed by others. SPOPS definitely has better many-to-many support right now. It would be nice to improve that in Class::DBI. I currently use custom SQL methods when I have many-to-many relationships. >> CGI::Application has a number of plugins now that make it more >> interesting. Apache::PageKit might be interesting to you as well. > > > AFAIU it does not have fetching objects from the database by class name > and id as a defining feature. Ditto about CGI::Application. Are you referring to generating automatic editing forms? Struts, and Spring don't do that either AFAIK. OpenInteract does some of it. It's a relatively simple piece of glue code to map URIs to method calls. Doing a good job at auto-generating forms can be tough though. - Perrin -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.9 - Release Date: 1/6/2005 From Dave.Howorth@acm.org Mon Jan 10 23:21:35 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Mon, 10 Jan 2005 23:21:35 +0000 Subject: [Maypole] Where do I place actions without a model ? In-Reply-To: <200501102245.09548.rs@plusw.de> References: <20050110190456.36169.qmail@web52105.mail.yahoo.com> <41E2DCFD.1020302@acm.org> <200501102245.09548.rs@plusw.de> Message-ID: <41E30DFF.1000209@acm.org> Rolf Schaufelberger wrote: > But the general question with non-model related actions is still > there, and Peters solution with a dummy table may be a solution, but In the abstract, what you want to do is manipulate state, and that's what models are for. The issue is that at present Maypole supports just one model at a time and that is a collection of classes built around a database. When all you've got is a hammer, everything looks like a nail. Hopefully, there'll be the possibility of multiple models of different types sometime in the not-too-distant future. > it's just not "clean" (don't know how to express is in english, I > mean it's a workaround an no proper conceptual solution). Well it's one meaning of the much-overused 'hack', but in British English I'd be more inclined to say it's a 'fudge' or 'bodge'. Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.9 - Release Date: 06/01/05 From simonf@cshl.edu Mon Jan 10 23:30:38 2005 From: simonf@cshl.edu (Vsevolod (Simon) Ilyushchenko) Date: Mon, 10 Jan 2005 18:30:38 -0500 Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <41E30E0C.6030900@elem.com> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> <41E30E0C.6030900@elem.com> Message-ID: <41E3101E.7010006@cshl.edu> >>> CGI::Application has a number of plugins now that make it more >>> interesting. Apache::PageKit might be interesting to you as well. >> >> >> >> AFAIU it does not have fetching objects from the database by class >> name and id as a defining feature. Ditto about CGI::Application. > > > Are you referring to generating automatic editing forms? Struts, and > Spring don't do that either AFAIK. OpenInteract does some of it. > > It's a relatively simple piece of glue code to map URIs to method calls. > Doing a good job at auto-generating forms can be tough though. I am not necessarily going as far as auto-generating forms (people like to customize them anyway), but both Maypole and my framework always suppose you are dealing with an object of class A with id X, not with just arbitrary URLs. (ID can be null, of course.) Plus, I also have an application name as a required parameter, which lets me use one script as a front-end for all my applications. I wonder how I would separate applications in Maypole. Simon -- Simon (Vsevolod ILyushchenko) simonf@cshl.edu http://www.simonf.com Terrorism is a tactic and so to declare war on terrorism is equivalent to Roosevelt's declaring war on blitzkrieg. Zbigniew Brzezinski, U.S. national security advisor, 1977-81 From spencer@spencerogden.com Tue Jan 11 05:42:39 2005 From: spencer@spencerogden.com (Spencer Ogden) Date: Tue, 11 Jan 2005 00:42:39 -0500 Subject: [Maypole] Taint mode Message-ID: <41E3674F.6060900@spencerogden.com> I haven't seen a mention of this on the list yet, so I thought I would throw it out there. When I first set up Maypole under CGI::Maypole, my initial thought, like a good little boy, was to start my beer.cgi with "#!/usr/bin/perl -T". And soon found out Maypole does not like taint mode. The most basic problem is that the path is never untainted, causing some calls in Class::DBI::AsForm to fail when there $self, which comes straight from the path, is tainted. I'm not sure if this is worth fixing, and I'm sure there are are many other issues I haven't hit yet, but I think the right place to fix this is in Maypole::parse_path. Here's my thought: --- /usr/lib/perl5/site_perl/5.8.5/Maypole.pm 2004-12-25 03:07:50.000000000 +0000 +++ Maypole.pm 2005-01-11 05:38:09.907182616 +0000 @@ -187,4 +187,7 @@ my $self = shift; $self->{path} ||= "frontpage"; + $self->{path} =~ /((\w\/?)+)/; + $self->{path} = $1; + my @pi = split /\//, $self->{path}; shift @pi while @pi and !$pi[0]; Regards, Spencer Ogden From teejay@droogs.org Tue Jan 11 15:30:08 2005 From: teejay@droogs.org (Aaron Trevena) Date: Tue, 11 Jan 2005 15:30:08 +0000 (GMT) Subject: [Maypole] Maypole's direction and Perl web frameworks In-Reply-To: <20050110170425.GA1188@soto.kasei.com> References: <41E07BCA.6070103@cshl.edu> <41E1FF53.2020304@elem.com> <41E29E24.4070809@cshl.edu> <20050110170425.GA1188@soto.kasei.com> Message-ID: On Mon, 10 Jan 2005, Tony Bowden wrote: > On Mon, Jan 10, 2005 at 10:24:20AM -0500, Vsevolod (Simon) Ilyushchenko wrote: >> They are auto-creation of instance variables based on column names (so >> that I don't have to specify them in configs), > > There are numerous Class::DBI plugins to do this. > >> many_to_many relationships (though maybe has_many can be tweaked to >> support that) > > Class::DBI already supports many to many. It's not the most efficient > thing in the world, but it's there. > > There's also scope for someone to write a proper relationship plugin for > this. The main reasons I haven't done so yet is that I haven't needed it > enough, and I can't come up with a nice enough interface. I have been working on many-to-many relationships as part of PINT, but there is at least one on CPAN, together with the Is-A relationship. Both are currently at the proof of concept stage, as is PINT. PINT itself is a subclass/wrapper for CDBI that provides stuff I like (or is suggested and seems like a good idea) on top of the simplicity and extensability of CDBI so that you can use PINT or CDBI or the underlying SQL::Abstract and Ima::DB features directly. On of the key things I like about CDBI is that unlike Tangram and other OOPF it doesn't get in my way when I need to do something relationial or some feature isn't doing what I need. I have a couple more Many-to-Many relationships I want to work on, as well as the complex attributes that PINT implements (arrays, hashes, vectors,boolean). I don't think PINT or the new non-core CDBI relationships are mature enough for use or inclusion with Maypole yet. Hopefully we can get some dialogue started. I know that what I want from CDBI includes most of what Tony wants and a lot more so I have built it myself (and thanks to tony and others who built CDBI to be nice and simple and extensible, its been rather successful) >> lack of auto-save for child objects in relationships. > > What does this mean? I would imagine a has_a_child or has_a_parent that would support cascade deletes, referential integrity and updates the child when the parent is updated. Would be simple to implement based on the code available and triggers, failing that you could just specify that the children autosave anyway. Cheers, A. -- Aaron J Trevena - Perl Hacker, Kung Fu Geek, Internet Consultant AutoDia --- Automatic UML and HTML Specifications from Perl, C++ and Any Datasource with a Handler. http://droogs.org/autodia From toddrw69@excite.com Tue Jan 11 16:07:20 2005 From: toddrw69@excite.com (Todd W) Date: Tue, 11 Jan 2005 11:07:20 -0500 Subject: [Maypole] maypole design questions Message-ID: I don't know where to start, exactly. Like I read in another thread, web platform designs are much more philosophical than technical. I need several things. Apache 1/mod_perl 1 centric with the ability/extensibility to run even from the command line. runs on *nix and windows cored to Class::DBI and Template::Toolkit easily handle multiple applications connecting to different datasources Feature specific logic stays out of the platform and is implemented as plugins. This is Maypole. My search for a web app platform started out about 3 years ago. What I have found myself always doing is researching CPAN to find modules in the target problem space. Installing them, tinkering, seeing who is best documented/supported/actively maintained. Then I set about writing my own implementation just to see how I would do it. After I code myself into a corner, I go back to CPAN and see who best addressed the corner I just coded myself into. First was configuration. I ended up using XML formatted config files using XML::XPath/XML::Writer/XML::LibXSLT to interface. Then, I worked with templating. It was easy to decide right away to go with the template toolkit. Then was relational/oo mapping. Alzabo/Tangram/SPOPS/Class::DBI. Then I wrote what boiled down to a code generator that queried database schema and generated source files for the relational/oo mapping. The corner I eventually coded myself into was how to make foreign keys map to records in other databases. Bingo, Class::DBI. Then, logging. Here, I'm still stuck with an implementation of my own. Logging calls to the logger boil down to XML::Writer calls. At the beginning of a HTTP request the logger is instantiated. As the interpreter traverses my code, calls to the logger maintain a stack of function calls and messages. At the end of the request, the document is written out to disk. Then I wrote a Log::Reader that applies an xslt stylesheet to the log file, and out comes a treeview looking html document of user sessions. Which brings me to the application server itself. I researched poop.sourceforge.net and took a look at what was out there. Installed OI/AxKit/Apache::ASP/Maypole. The most important feature to me that I haven't found simplistically supported in an application server is multiple views. So I start hacking away on an application server. Here's what I ended up with: To achieve device independence (multiple views) the client must specify what format it would like. For example: Request: /BeerDB/index.html The code in a PerlFixupHandler checks to see if BeerDB::index.pm is in %INC. If it is, the file residing at /BeerDB/index.html is a template to be processed. To accomplish this, the logic then calls: $r->handler( 'perl-script' ); $r->push_handlers( PerlHandler => \&Apache::Template::handler ); And then a custom Template::Service::Apache module adds a "page" object to the data hash. Very simple. very clean. If a customer wants to see the BeerDB on their T-Mobile SideKick, I just create a new wrapper template and a template called /BeerDB/index.tsk, and tell the user to bookmark it on their device. Another benefit is templates and static files can live next to eachother anywhere in the document_root. This is something I have been annoyed by for years. To further accommodate this, If the request does NOT map to a file but DOES map to an entry in %INC, it is assumed to be a PerlHandler. This eliminates the need for mucking about with httpd.conf, and the ->handler function gets passed the application object, complete with session, log, user, and request objects. I have achieved filesystem location independence and file extension independence along with device interface independence. So, to the corner I'm now coded in: A standard way to authorize, accept, validate, and store data from the user. >From what I have seen from the demo apps I installed from the docs, maypole has this. Can someone offer some discussion on this? How well could my methodology above integrate with maypole? Could I implement it via subclasses, or would I have to modify maypole source? Can I use existing Class::DBI classes? I already have many Class::DBI classes set up. How would I go about, for example, making them work with the default templates? Looking at http://maypole.perl.org/?About, it looks like I can just inherit from Apache::MVC in my Application::DBI class that all table specific Class::DBI classes inherit from, and leave the ->connection() call instead of calling ->setup()? If someone could tell me how to start reusing existing Class::DBI classes, I'm sure I'll figure the rest of the system out as a side effect. If this works out, I hope to become a member of the Maypole development team, or at least develop distributable custom plugins. I believe I have a lot to offer. My next goal after the input mechanism: role based authorization. Thanks for any input. Todd W. From sri@oook.de Tue Jan 11 20:11:14 2005 From: sri@oook.de (Sebastian Riedel) Date: Tue, 11 Jan 2005 21:11:14 +0100 Subject: [Maypole] maypole design questions In-Reply-To: References: Message-ID: <1105474274.23537.7.camel@localhost> Todd W: > Installed OI/AxKit/Apache::ASP/Maypole. Maybe you should also try Catalyst. It's beta but seems to already support everything you want. http://files.oook.de/Catalyst.tar.gz > Can I use existing Class::DBI classes? Maypole::Model::CDBI::Plain -- sebastian From perrin@elem.com Tue Jan 11 21:56:37 2005 From: perrin@elem.com (Perrin Harkins) Date: Tue, 11 Jan 2005 16:56:37 -0500 Subject: [Maypole] maypole design questions In-Reply-To: References: Message-ID: <1105480597.6513.535.camel@localhost.localdomain> On Tue, 2005-01-11 at 11:07 -0500, Todd W wrote: > The most important feature to me that I > haven't found simplistically supported in an application server is multiple > views. All of the MVC ones (Maypole, OI, PageKit, AxKit) support multiple views, and so do lower-level things like CGI::Application. > To further accommodate this, If the request does NOT map to a file but DOES > map to an entry in %INC, it is assumed to be a PerlHandler. This eliminates > the need for mucking about with httpd.conf, and the ->handler function gets > passed the application object, complete with session, log, user, and > request objects. I hope you have some security on that. There might be some PerlHandlers in %INC that you don't want just anyone to call. - Perrin From ghaverla@materialisations.com Tue Jan 11 23:27:11 2005 From: ghaverla@materialisations.com (Gordon Haverland) Date: Tue, 11 Jan 2005 16:27:11 -0700 Subject: [Maypole] User Validation (eventually) Message-ID: <200501111627.11921.ghaverla@materialisations.com> [ I sent from wrong address first, and is being held up by moderator. This note adds to original posting. ] I'm still stumbling along in trying to get this going. But, maybe=20 some of this is of interest. Or maybe people can clear things=20 up. It's a CGI version I am setting up, but for now I am using=20 maypole_test.pl to work with using perldb in emacs. SQLite is=20 the database backend. When looking at the mailing list archives, I seen a few posts=20 about performance. So, my first thing is an observation on that.=20 I have half a dozen tables inside a database, most of the tables=20 only have 3 or 4 columns. To get to the point in my module (ElugRev.pm) where I call=20 =2D>setup("dbi:...") is about 28k single steps. Which is a lot of=20 setup! All of the tables are in a single database, but for every=20 table the system initializes itself which the expected dialect of=20 SQL being used (same for all of them, so shouldn't that only be=20 done once?). Then it reads the CREATE statement for the various=20 tables from the database, and analyses that SQL statement for=20 being valid. While this is good in the case of SQL statements=20 provided by a user, is this really necessary for the SQL=20 statement which successfully made the table in the database you=20 are connecting to? The current debug session of Maypole is going to die sooner or=20 later as well, because in the handler() function of Maypole.pm, a=20 call to $r->get_request( $req ) is made. It isn't really CGI=20 inside emacs, and I am not using the CLI version of Maypole=20 either. So, a 400 Unknown method No REQUEST_METHOD received was generated (before headers printed). But, I'll see if anything=20 else gets tripped up on this pass through emacs. :-) =46rom some readings in the PHP world talking about cookies and=20 session variables, I am expecting that something to do with=20 cookies needs to get called early on with Maypole as well. Is=20 this the case, or does something else happen? From what I have=20 read, cookies never even get tickled until an authorisation is=20 required. So, I am wondering how these fit into things. It would REALLY be nice if someone wrote something about the=20 "advanced" perl programming which ends up in modules. There are=20 quite a few statements which have been surprising to see (but can=20 be understood easily once seen), and some statements which just=20 seem strange. One example, is debugging help. I suspect the=20 easiest to understand is to set some global variable to some=20 value to activate various levels of debugging. Maypole allows=20 one to define a subroutine to control debugging, but in practice=20 this seems to do almost nothing.. Thanks, Gord From Dave.Howorth@acm.org Tue Jan 11 23:30:09 2005 From: Dave.Howorth@acm.org (Dave Howorth) Date: Tue, 11 Jan 2005 23:30:09 +0000 Subject: [Maypole] maypole design questions In-Reply-To: References: Message-ID: <41E46181.3000609@acm.org> Hi Todd, Todd W wrote: > To achieve device independence (multiple views) the client must > specify what format it would like. For example: There's a bit about this in the Request Cookbook at http://search.cpan.org/~simonflk/Maypole-2.06/lib/Maypole/Manual/Request.pod#Maypole_for_mobile_devices It's also worth looking at iBuySpy http://search.cpan.org/~simonflk/Maypole-2.06/lib/Maypole/Manual/BuySpy.pod for more information about ways to rewrite URLs in Maypole. I haven't used any of these techniques so I can't speak for them. > So, to the corner I'm now coded in: A standard way to authorize, see below > accept, validate, and store data from the user. Yes in Maypole via CDBI and plugins. > How well could my methodology above integrate with maypole? Could I > implement it via subclasses, or would I have to modify maypole > source? You can subclass most things but it may help to agree some changes to Maypole to make it easier. I expect other people share at least some of these needs. > Can I use existing Class::DBI classes? I already have many Class::DBI > classes set up. How would I go about, for example, making them work > with the default templates? Look at Maypole::Model::CDBI::Plain. > Looking at http://maypole.perl.org/?About, Best to look at the docs on CPAN as in the links I gave above, because they match the current release. > My next goal after the input mechanism: role based authorization. This has been mentioned a couple of times. I've just written a module for it. I'll post an initial version for discussion tomorrow. Cheers, Dave -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.300 / Virus Database: 265.6.10 - Release Date: 10/01/05 From peterspeltz@yahoo.com Wed Jan 12 09:40:32 2005 From: peterspeltz@yahoo.com (Peter Speltz) Date: Wed, 12 Jan 2005 01:40:32 -0800 (PST) Subject: [Maypole] User Validation (eventually) In-Reply-To: <200501111627.11921.ghaverla@materialisations.com> Message-ID: <20050112094032.96270.qmail@web52102.mail.yahoo.com> --- Gordon Haverland wrote: > From some readings in the PHP world talking about cookies and > session variables, I am expecting that something to do with > cookies needs to get called early on with Maypole as well. Is > this the case, or does something else happen? From what I have > read, cookies never even get tickled until an authorisation is > required. So, I am wondering how these fit into things. > Maypole doesn't use any cookies at all. It really just provides a convenient place, the authenticate sub, for you to use them to authenticate and checks there automatically to see if a user gets authenticated (ie it calls the authenticate sub early in every request) . By default authenticate just returns OK so you app is wide open. Maypole::Plugin:Authentication::UserSessionCookie is a good user session system for maypole. That's all i can help you with. One more thing, maypole-test.pl that Dave wrote uses Maypole::CLI and works great in VI with the perl debugger. Why not use it like that? Also, i had to disable my authentication to get it to run thru (just made it return OK again) but don't know why. HTH ===== pjs __________________________________ Do you Yahoo!? The all-new My Yahoo! - Get yours free! http://my.yahoo.com From m.romani@spinsoft.it Wed Jan 12 13:56:00 2005 From: m.romani@spinsoft.it (Marcello) Date: Wed, 12 Jan 2005 14:56:00 +0100 Subject: [Maypole] role based authentication Message-ID: <41E52C70.2000806@spinsoft.it> Hi everyone, I am developing and application using maypole, and I would like to discuss role based authentication. The main uses I see for roles in maypole are: 1) Check if the current user is allowed to call a particular tagle/action couple. For example, we could have a "role" table and a "user" table which should be visible to "administrators" (i.e. users who belong to role "administrator") but not to "customers" (i.e. users who belong to role "customer"); or, we could limit customers' access to their data to be read-only, so a user with role "customer" could call customerdata/list but not customerdata/delete; and so on. 2.a) Build a menu template which displays only the allowed actions for the current user. 2.b) Each button, hyperlink or form pointing to a particular table/action combination should be displayed only if the current user is allowed to call that combination. In other words, the templates should hide all the elements that would point to an action the user is not allowed to perform. Ideally, the user should never see a "not allowed" page, unless she tries to perform a particular action by typing a specific URL direcly into the address-bar. 3) Write role-specific templates. This could allow the developer to customize the interface on a per-role basis. Though I did not implement this feature, I think one possible solution would be to add two search paths before the ones TT currenlty searches templates in: $template_root/maypole_roles/$role/$table/$action $template_root/maypole_roles/$role/default/$action where: maypole_roles is a name which should never be used for a table name in the application; $role is the role of the current user $table and $action are the usual request slots (e.g. "beer", "list"). What do you think ? Marcello From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 12 15:12:17 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 12 Jan 2005 15:12:17 +0000 Subject: [Maypole] Maypole::Plugin::Authorization Message-ID: <41E53E51.5030106@mrc-lmb.cam.ac.uk> This is a multi-part message in MIME format. --------------070606000503000104010500 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit I've been writing a role-based authorization plugin for Maypole. I've attached an initial version of this. It should help to stimulate the discussion and people may find they are able to use it, though there are no warranties. I'm open to any questions or suggestions for improvement. I'll try to post some auxiliary files later (database dump, my actual BeerDB.pm, anything else?). Cheers, Dave --------------070606000503000104010500 Content-Type: application/x-perl; name="Authorization.pm" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Authorization.pm" package Maypole::Plugin::Authorization; use strict; use warnings; # This module provides role-based authorization for Maypole our $VERSION = '0.02'; # We can determine whether a given user_id is authorized to invoke a # particular method in a model_class using the following SQL query: my $check_auth_sql = <model_class; my $method = $r->action; my $userid = $r->user->id; # The caller needs to deal with requests with no model class before # calling us because the response is application-specific. If such a # request gets this far, we just turn it down return undef unless $class; # Find a class that can run SQL queries for us and make sure the SQL # query has been prepared my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(check_authorization => $check_auth_sql) unless $cdbi_class->can('sql_check_authorization'); # Check the permissions return $cdbi_class->sql_check_authorization ->select_val($userid, $class, $method); } # Auxiliary methods for finding lists of authorized classes and methods my $get_auth_classes_sql = <user->id; my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(get_authorized_classes => $get_auth_classes_sql) unless $cdbi_class->can('sql_get_authorized_classes'); return $cdbi_class->sql_get_authorized_classes->execute($userid); } my $get_auth_methods_sql = <model_class; my $userid = $r->user->id; my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(get_authorized_methods => $get_auth_methods_sql) unless $cdbi_class->can('sql_get_authorized_methods'); return $cdbi_class->sql_get_authorized_methods->execute($userid, $class); } 1; #__END__ =head1 NAME Maypole::Plugin::Authorization - Provide role-based authorization for Maypole applications =head1 SYNOPSIS package BeerDB; use Maypole::Application qw(Authentication::UserSessionCookie Authorization); =cut sub authenticate { my ($self, $r) = @_; ... if $self->authorize($r) { return OK; } else { # take application-specific authorization failure action ... } ... } =head1 DESCRIPTION This module provides simple role-based authorization for Maypole. It uses the database to store permissions, which fits well with Maypole. It determines whether I are authorized to invoke specific I in I. Normally these will be I in model classes. Permission to invoke methods is not granted directly; it is assigned to I, and each user may be assigned one or more roles. =head1 Database structure The module depends on four database tables to store the necessary data. =over =item users The C table records details of each individual who has an account on the system. It is also used by L to do user authentication and session management. Additional columns can be added to suit whatever other needs you have. =item auth_roles Users are not given permissions directly because that causes an explosion in the table size and an administrative headache. Instead roles are given permissions and users acquire those permissions by being assigned to roles. The C table just records the name of the role. You could add things like a description if you wish. The table is not called C so that the name is left free for your application to use. =item role_assignments C is a classic many-many link table. Records contain the id of a user and of a role which the user has been assigned. =item permissions The C table authorizes a specific role to execute a particular method in a particular class. The classes are expected to be the model subclasses and the methods will be the actions, but the scheme will also work in other situations. To reduce administrative burden and table size, it is allowed to use a '*' wildcard instead of a method name; this grants permission to all methods in the class. It would be possible to add a similar wildcard for classes but there's probably no action that you want to allow on B classes! =back The table definitions to implement this scheme look like this: CREATE TABLE users ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, UID VARCHAR(20) NOT NULL, password VARCHAR(20) NOT NULL, PRIMARY KEY (id), UNIQUE (UID), ) TYPE=InnoDB; CREATE TABLE auth_roles ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(40) NOT NULL, PRIMARY KEY (id), ) TYPE=InnoDB; CREATE TABLE role_assignments ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, auth_role_id INT NOT NULL, PRIMARY KEY (id), UNIQUE (user_id, auth_role_id), INDEX (auth_role_id), FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (auth_role_id) REFERENCES auth_roles (id), ) TYPE=InnoDB; CREATE TABLE permissions ( id INT NOT NULL AUTO_INCREMENT, auth_role_id INT NOT NULL, model_class VARCHAR(100) NOT NULL, method VARCHAR(100) NOT NULL, PRIMARY KEY (id), UNIQUE (auth_role_id, model_class, method), INDEX (model_class(20)), INDEX (method(20)), FOREIGN KEY (auth_role_id) REFERENCES auth_roles (id), ) TYPE=InnoDB; =head1 Processing We can determine whether a given C is authorized to invoke a particular C in a C using the following SQL query: SELECT p.id FROM permissions AS p, role_assignments AS r WHERE r.user_id = ? AND p.model_class = ? AND (p.method = ? OR p.method = '*') AND p.auth_role_id = r.auth_role_id LIMIT 1 This query is executed in the C method which is called from the driver's C method. (Maypole's terminology is a little confused about authentication and authorization but the code works the same either way!) =head2 authorize The C method is called in the driver's authenticate method, though it is explicitly passed the request object and so can in be called from elsewhere if desired. package BeerDB; sub authenticate { my ($self, $r) = @_; ... if $self->authorize($r) { return OK; } else { # take application-specific auth failure action } ... } It returns a true value if authorization is granted and C if not. =head2 administration The permissions database can be maintained by any person who is assigned to the I role. Most administration is performed using normal Maypole actions and templates such as list, search, addnew, view, edit and delete. User administration is separated out to a I role. I don't yet know whether this will prove beneficial but these people are the only ones who can access passwords and personal details. There needs to be special code to allow users to edit their own passwords, since that is a data-dependent permission as opposed to the metadata-dependent nature of the authorizations scheme. Such code is part of the application's authentication scheme. There is a I role that should be assigned to every user. Perhaps it should be hardwired in the SQL so that users don't have to be actually added to the role? =head1 Use Cases =over =item Create new user User administration mechanisms belong in the domain of the authentication system, though this authorization modules imposes a few additional requirements. This action should be permitted to the user-admin role. Newly created users should automatically be assigned to the 'default' role. =item User changes password Should be permitted to the individual user only and perhaps to the user-admin role. =item Grant/change/revoke user privileges =item Create/delete role =item Alter actions permitted to role People assigned to the admin role can edit the role_assignments table and the auth_roles table in the normal Maypole way. =item Update list of classes =item Update list of methods Presently, administrators need to type in the names of the model subclasses and the actions. The methods C and C could be used to build a specialized template to populate the relevant form elements. =item Determine list of classes This is the C method. Given a user ID, find the list of classes for which s/he has some permissions. This can be used to build the list of tabs in the navbar. =item Determine list of methods This is the C method. Given a user ID and class name, find the list of methods that the user is entitled to invoke. This can be used to build a menu of permitted actions. =back =head1 Alternatives and futures There are several alternative possibilities for authorizable entities and permission checking in addition to the example implementation provided: 1/ Authorize all actions (i.e. methods with the Exported attribute). Permission could be enforced in the model's process method just before calling the action. PRO: simple to implement, uniform and easy-to-understand CON: not as flexible as alternatives 2/ Explicit call to authorize() at the beginning of every method that needs to be authorized. PRO: Flexible. Very simple to implement initially. Obvious in code where auth occurs. Auth can be done at points other than method entry if needed. CON: Error-prone and awkward to maintain. Increases code complexity. 3/ Provide some other attribute that can be attached to methods to require them to be authorized, or perhaps in combination with Exported. For example, the Exported attribute could automatically invoke authorization as would a new 'Auth' attribute, while a new 'NoAuth' attribute would declare that the action could proceed without authorization. =cut --------------070606000503000104010500-- From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 12 15:19:20 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 12 Jan 2005 15:19:20 +0000 Subject: [Maypole] role based authorization In-Reply-To: <41E52C70.2000806@spinsoft.it> References: <41E52C70.2000806@spinsoft.it> Message-ID: <41E53FF8.9040503@mrc-lmb.cam.ac.uk> Marcello wrote: > 1) Check if the current user is allowed to call a particular > tagle/action couple. > For example, we could have a "role" table and a "user" table which > should be visible to "administrators" (i.e. users who belong to role > "administrator") but not to "customers" (i.e. users who belong to role > "customer"); or, we could limit customers' access to their data to be > read-only, so a user with role "customer" could call customerdata/list > but not customerdata/delete; and so on. I've just posted a plugin that does this. > 2.a) Build a menu template which displays only the allowed actions for > the current user. There are some untested functions get_authorized_classes and get_authorized_methods intended to help with this. > 2.b) Each button, hyperlink or form pointing to a particular > table/action combination should be displayed only if the current user is > allowed to call that combination. > In other words, the templates should hide all the elements that would > point to an action the user is not allowed to perform. > Ideally, the user should never see a "not allowed" page, unless she > tries to perform a particular action by typing a specific URL direcly > into the address-bar. This sounds like what I have in mind. > 3) Write role-specific templates. This could allow the developer to > customize the interface on a per-role basis. This also sounds like what I want to do. I'd love to see anything you do in this direction. Otherwise templates will become more and more complex with conditional code to decide whether there should be edit or delete buttons or whatever. Cheers, Dave From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 12 15:26:40 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 12 Jan 2005 15:26:40 +0000 Subject: [Maypole] User Validation (eventually) In-Reply-To: <200501111627.11921.ghaverla@materialisations.com> References: <200501111627.11921.ghaverla@materialisations.com> Message-ID: <41E541B0.3050702@mrc-lmb.cam.ac.uk> Gordon Haverland wrote: > One example, is debugging help. I suspect the > easiest to understand is to set some global variable to some > value to activate various levels of debugging. Maypole allows > one to define a subroutine to control debugging, but in practice > this seems to do almost nothing.. Using a subroutine is a performance thing. Perl inlines subroutines that just return a constant so this should allow for better optimisation than checking variables. I've no idea what difference it actually makes. Simon is steadily improving the diagnostics but at present I still think there's no substitute for adding warn or print statements at all places that are important to you. Cheers, Dave From ghaverla@materialisations.com Wed Jan 12 15:35:02 2005 From: ghaverla@materialisations.com (Gordon Haverland) Date: Wed, 12 Jan 2005 08:35:02 -0700 Subject: [Maypole] User Validation (eventually) In-Reply-To: <20050112094032.96270.qmail@web52102.mail.yahoo.com> References: <20050112094032.96270.qmail@web52102.mail.yahoo.com> Message-ID: <200501120835.03088.ghaverla@materialisations.com> On Wednesday 12 January 2005 02:40, Peter Speltz wrote: > That's all i can help you with. One more thing, maypole-test.pl > that Dave wrote uses Maypole::CLI and works great in VI with > the perl debugger. Why not use it like that? Also, i had to > disable my authentication to get it to run thru (just made it > return OK again) but don't know why. I've been using it (maypole-test.pl) in emacs/perldb. I kept getting a use of uninitialised variable from print $class->call_url($url); in Maypole-test.pl. So, I changed it to my $ret = $class->call_url( $url ) || "All done\n"; print $ret; And at least that warning has gone away (after everything else is done). I still can't get the lead page to display, because of: [Wed Jan 12 07:34:38 2005] maypole_test.pl: We don't have that table (frontpage). [Wed Jan 12 07:34:38 2005] maypole_test.pl: Available tables are: book,review,bookTOC,bookReview,bookAuthor,bookEditor,bookTranslator,bookWeb at /usr/local/share/perl/5.8.4/Maypole.pm line 144. It would display before I started adding stuff to allow logins to part of the site (what you guys are calling roles I guess). Oh well, go fight with it some more. :-) Gord From sri@oook.de Wed Jan 12 15:39:19 2005 From: sri@oook.de (Sebastian Riedel) Date: Wed, 12 Jan 2005 16:39:19 +0100 Subject: [Maypole] role based authentication In-Reply-To: <41E52C70.2000806@spinsoft.it> References: <41E52C70.2000806@spinsoft.it> Message-ID: <1105544359.26767.47.camel@localhost> Marcello: > I am developing and application using maypole, and I would like to > discuss role based authentication. > > The main uses I see for roles in maypole are: > > 1) Check if the current user is allowed to call a particular > tagle/action couple. > For example, we could have a "role" table and a "user" table which > should be visible to "administrators" (i.e. users who belong to role > "administrator") but not to "customers" (i.e. users who belong to role > "customer"); or, we could limit customers' access to their data to be > read-only, so a user with role "customer" could call customerdata/list > but not customerdata/delete; and so on. In Catalyst it's the other way around. You just do something like this directly in your actions, i personally find this much more simple and maintainable. __PACKAGE__->action( 'sign-in.html' => sub { my ( $self, $c ) = @_; $c->stash->{template} = 'sign-in.tt'; # ...do sign-in stuff... }, 'index.html' => sub { my ( $self, $c ) = @_; $c->roles('customer') ? $c->stash->{template} = 'index.tt' : $c->forward('sign-in.html'); } ); > > 2.a) Build a menu template which displays only the allowed actions for > the current user. > > 2.b) Each button, hyperlink or form pointing to a particular > table/action combination should be displayed only if the current user is > allowed to call that combination. > > 3) Write role-specific templates. Why are you guys always trying to exploit the built in actions? They're just to get you started! I would even vote to reduce them to a minimum and get them out of Maypole::Model::CDBI...but i already said that many times in the past! And again a glimpse at how i do it in Catalyst. ;) Everything in Catalyst, Model, View and Controller are components, represented as object classes. Finding .pm's and instantiating them is all automatically done by Catalyst, you just write a MyApp/Model/CDBI.pm and begin to use it. package MyApp::Model::CDBI; use base 'Catalyst::Model::CDBI'; __PACKAGE__->config( dsn => 'dbi:Pg:dbname=petstore', password => '', user => 'postgres', options => { AutoCommit => 1 }, relationships => 1 ); package MyApp; use Catalyst; # ... actions and stuff ... Now if you want CRUD, you just replace Catalyst::Model::CDBI with Catalyst::Model::CDBI::CRUD, and define an action for every table where you forward processing to the built-in crud method, which redispatches to list/add/delete/edit... __PACKAGE__->action( tablename => sub { my ( $self, $c ) = @_; $c->forward(/MyApp::Model::CDBI crud/); } ); -- sebastian From dhoworth@mrc-lmb.cam.ac.uk Wed Jan 12 15:46:50 2005 From: dhoworth@mrc-lmb.cam.ac.uk (Dave Howorth) Date: Wed, 12 Jan 2005 15:46:50 +0000 Subject: [Maypole] Maypole::Plugin::Authorization In-Reply-To: <41E53E51.5030106@mrc-lmb.cam.ac.uk> References: <41E53E51.5030106@mrc-lmb.cam.ac.uk> Message-ID: <41E5466A.9010403@mrc-lmb.cam.ac.uk> This is a multi-part message in MIME format. --------------060603050808000707060702 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit I wrote: > I've attached an initial version of this. I've now attached a version that I think compiles! Sorry, I was tidying the POD and made a silly mistake. I've also attached some sample data for the authorization tables and the complete text of the BeerDB.pm I'm running under CGI. You can ignore the: Maypole::Config->mk_accessors('template_extension'); and sub additional_data { my $r = shift; $r->template_args->{classmetadata} = { cgi => 'DUMMY CGI'} } Those are just weirdnesses in my environment. Cheers, Dave --------------060603050808000707060702 Content-Type: application/x-perl; name="Authorization.pm" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Authorization.pm" package Maypole::Plugin::Authorization; use strict; use warnings; # This module provides role-based authorization for Maypole our $VERSION = '0.02'; # We can determine whether a given user_id is authorized to invoke a # particular method in a model_class using the following SQL query: my $check_auth_sql = <model_class; my $method = $r->action; my $userid = $r->user->id; # The caller needs to deal with requests with no model class before # calling us because the response is application-specific. If such a # request gets this far, we just turn it down return undef unless $class; # Find a class that can run SQL queries for us and make sure the SQL # query has been prepared my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(check_authorization => $check_auth_sql) unless $cdbi_class->can('sql_check_authorization'); # Check the permissions return $cdbi_class->sql_check_authorization ->select_val($userid, $class, $method); } # Auxiliary methods for finding lists of authorized classes and methods my $get_auth_classes_sql = <user->id; my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(get_authorized_classes => $get_auth_classes_sql) unless $cdbi_class->can('sql_get_authorized_classes'); return $cdbi_class->sql_get_authorized_classes->execute($userid); } my $get_auth_methods_sql = <model_class; my $userid = $r->user->id; my $cdbi_class = $r->config->auth->{user_class}; $cdbi_class->set_sql(get_authorized_methods => $get_auth_methods_sql) unless $cdbi_class->can('sql_get_authorized_methods'); return $cdbi_class->sql_get_authorized_methods->execute($userid, $class); } 1; __END__ =head1 NAME Maypole::Plugin::Authorization - Provide role-based authorization for Maypole applications =head1 SYNOPSIS package BeerDB; use Maypole::Application qw(Authentication::UserSessionCookie Authorization); sub authenticate { my ($self, $r) = @_; ... if $self->authorize($r) { return OK; } else { # take application-specific authorization failure action ... } ... } =head1 DESCRIPTION This module provides simple role-based authorization for Maypole. It uses the database to store permissions, which fits well with Maypole. It determines whether I are authorized to invoke specific I in I. Normally these will be I in model classes. Permission to invoke methods is not granted directly; it is assigned to I, and each user may be assigned one or more roles. =head1 Database structure The module depends on four database tables to store the necessary data. =over =item users The C table records details of each individual who has an account on the system. It is also used by L to do user authentication and session management. Additional columns can be added to suit whatever other needs you have. =item auth_roles Users are not given permissions directly because that causes an explosion in the table size and an administrative headache. Instead roles are given permissions and users acquire those permissions by being assigned to roles. The C table just records the name of the role. You could add things like a description if you wish. The table is not called C so that the name is left free for your application to use. =item role_assignments C is a classic many-many link table. Records contain the id of a user and of a role which the user has been assigned. =item permissions The C table authorizes a specific role to execute a particular method in a particular class. The classes are expected to be the model subclasses and the methods will be the actions, but the scheme will also work in other situations. To reduce administrative burden and table size, it is allowed to use a '*' wildcard instead of a method name; this grants permission to all methods in the class. It would be possible to add a similar wildcard for classes but there's probably no action that you want to allow on B classes! =back The table definitions to implement this scheme look like this: CREATE TABLE users ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, UID VARCHAR(20) NOT NULL, password VARCHAR(20) NOT NULL, PRIMARY KEY (id), UNIQUE (UID), ) TYPE=InnoDB; CREATE TABLE auth_roles ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(40) NOT NULL, PRIMARY KEY (id), ) TYPE=InnoDB; CREATE TABLE role_assignments ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, auth_role_id INT NOT NULL, PRIMARY KEY (id), UNIQUE (user_id, auth_role_id), INDEX (auth_role_id), FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (auth_role_id) REFERENCES auth_roles (id), ) TYPE=InnoDB; CREATE TABLE permissions ( id INT NOT NULL AUTO_INCREMENT, auth_role_id INT NOT NULL, model_class VARCHAR(100) NOT NULL, method VARCHAR(100) NOT NULL, PRIMARY KEY (id), UNIQUE (auth_role_id, model_class, method), INDEX (model_class(20)), INDEX (method(20)), FOREIGN KEY (auth_role_id) REFERENCES auth_roles (id), ) TYPE=InnoDB; =head1 Processing We can determine whether a given C is authorized to invoke a particular C in a C using the following SQL query: SELECT p.id FROM permissions AS p, role_assignments AS r WHERE r.user_id = ? AND p.model_class = ? AND (p.method = ? OR p.method = '*') AND p.auth_role_id = r.auth_role_id LIMIT 1 This query is executed in the C method which is called from the driver's C method. (Maypole's terminology is a little confused about authentication and authorization but the code works the same either way!) =head2 authorize The C method is called in the driver's authenticate method, though it is explicitly passed the request object and so can in be called from elsewhere if desired. package BeerDB; sub authenticate { my ($self, $r) = @_; ... if $self->authorize($r) { return OK; } else { # take application-specific auth failure action } ... } It returns a true value if authorization is granted and C if not. =head2 administration The permissions database can be maintained by any person who is assigned to the I role. Most administration is performed using normal Maypole actions and templates such as list, search, addnew, view, edit and delete. User administration is separated out to a I role. I don't yet know whether this will prove beneficial but these people are the only ones who can access passwords and personal details. There needs to be special code to allow users to edit their own passwords, since that is a data-dependent permission as opposed to the metadata-dependent nature of the authorizations scheme. Such code is part of the application's authentication scheme. There is a I role that should be assigned to every user. Perhaps it should be hardwired in the SQL so that users don't have to be actually added to the role? =head1 Use Cases =over =item Create new user User administration mechanisms belong in the domain of the authentication system, though this authorization modules imposes a few additional requirements. This action should be