[MKDoc-commit] Patch to add user-group functionality (Sam Tregar).
bruno at mkdoc.demon.co.uk
bruno at mkdoc.demon.co.uk
Wed Jan 26 13:19:54 GMT 2005
Log Message:
-----------
Patch to add user-group functionality (Sam Tregar). Note: 3 SQL tables need
to be created to avoid breaking existing sites.
Tags:
----
mkdoc-1-6
Modified Files:
--------------
mkd/MKDoc/Site/ConfigWriter:
Httpd_Conf.pm
mkd/MKDoc/Site/Deploy/DB:
Schema.pm
mkd/flo/plugin/Admin:
UserDelete.pm
UserInsert.pm
UserModify.pm
mkd/templates/admin/user_insert:
en.html
mkd/templates/admin/user_modify:
en.html
Added Files:
-----------
mkd/MKDoc/Handler:
GroupAuthz.pm
-------------- next part --------------
--- /dev/null
+++ MKDoc/Handler/GroupAuthz.pm
@@ -0,0 +1,123 @@
+# ----------------------------------------------------------------------------
+# MKDoc::Handler::GroupAuthz
+# ----------------------------------------------------------------------------
+# Author: Sam Tregar
+# Copyright: (c) MKDoc Holdings Ltd, 2005
+#
+# This file is part of MKDoc.
+#
+# MKDoc is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# MKDoc is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MKDoc; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# ---------------------------------------------------------------------------
+package MKDoc::Handler::GroupAuthz;
+use strict;
+use warnings;
+use Apache::Constants qw/:common/;
+use flo::Standard;
+use strict;
+use Carp;
+
+=head1 NAME
+
+MKDoc::Handler::GroupAuthz - enforce group-based security
+
+=head1 SYNOPSIS
+
+In httpd.conf for an authenticating host (like the default users.* setup):
+
+ PerlAuthzHandler MKDoc::Handler::GroupAuthz
+
+In httpd.conf for a non-authenticating host (like the default www.* setup):
+
+ <Location />
+ PerlModule MKDoc::Handler::GroupAuthz
+ PerlAuthenHandler MKDoc::Handler::GroupAuthz->null_authen_handler
+ PerlAuthzHandler MKDoc::Handler::GroupAuthz
+ AuthName "Group Authorization"
+ AuthType GroupAuthz
+ require valid-group
+ </Location>
+
+=head1 DESCRIPTION
+
+Checks for group authorization in MKDoc's Grp tables. If the document
+requested is assigned to one or more groups in Document_Grp then the
+user must be assigned to one of the groups in Editor_Grp.
+
+Users may be assigned to groups in the user editor by the admin.
+Groups are managed directly in the database (for now).
+
+=head1 AUTHOR
+
+Sam Tregar <sam at tregar.com>
+
+=cut
+
+sub handler {
+ my $r = shift;
+ my $user = $::MKD_USER;
+
+ # get the current document, locally setting PATH_INFO which is
+ # needed by the current_document() code but not yet setup by
+ # Apache at this stage
+ my $document = do {
+ local $ENV{PATH_INFO} = $r->path_info;
+ flo::Standard::current_document();
+ };
+
+ # if it wasn't found then this request can't be group protected
+ # (could be a CSS link, an image, etc)
+ return OK unless $document;
+
+ # check if this document is assigned to one or more groups
+ my $document_grp_t = flo::Standard::table('Document_Grp');
+ my @res = $document_grp_t->select (
+ cols => 'Grp_ID',
+ where => lib::sql::Condition->new(Document_ID => $document->id)
+ )->fetch_all();
+
+ # no results means this document is available to all
+ return OK unless @res;
+
+ # if the user isn't correctly logged in then they can't see this
+ # page
+ return FORBIDDEN unless $user and ref $user and $user->can('id');
+
+ # get a list of the user's groups. (It would be nice to just do a
+ # query against Editor_Grp like (editor_id = ? AND (grp_id = ? OR
+ # ...)) but I can't figure out how to get lib::sql to do anything
+ # that complicated. SQL replacements are great, huh?)
+ my $editor_grp_t = flo::Standard::table('Editor_Grp');
+ my $con = lib::sql::Condition->new(Editor_ID => $user->id);
+ my @groups = $editor_grp_t->select(cols => 'Grp_ID',
+ where => $con)->fetch_all;
+
+ # no results means the user wasn't in any of the groups, denied
+ return FORBIDDEN unless @groups;
+
+ # allow through if the user is in one of the document's groups
+ my %groups = map { ($_->{Grp_ID}, 1) } @groups;
+ return OK if grep { $groups{$_->{Grp_ID}} } @res;
+
+ # otherwise, no dice
+ return FORBIDDEN;
+}
+
+# an authen handler that does nothing. This is needed to allow the
+# group authz mechanism to work on www.* which doesn't do
+# authentication.
+sub null_authen_handler ($$) { OK }
+
+1;
Index: Httpd_Conf.pm
===================================================================
RCS file: /var/spool/cvs/mkd/MKDoc/Site/ConfigWriter/Httpd_Conf.pm,v
retrieving revision 1.1.2.28
retrieving revision 1.1.2.29
diff -LMKDoc/Site/ConfigWriter/Httpd_Conf.pm -LMKDoc/Site/ConfigWriter/Httpd_Conf.pm -u -r1.1.2.28 -r1.1.2.29
--- MKDoc/Site/ConfigWriter/Httpd_Conf.pm
+++ MKDoc/Site/ConfigWriter/Httpd_Conf.pm
@@ -208,6 +208,7 @@
#Editor: vim:syn=apache
<Location />
PerlAuthenHandler MKDoc::Handler::Authenticate
+ PerlAuthzHandler MKDoc::Handler::GroupAuthz
AuthName "Please enter your user credentials"
AuthType Basic
require valid-user
@@ -239,6 +240,16 @@
PerlInitHandler MKDoc::Handler::Initialize
Include $SITE_DIR/httpd/httpd-static.conf
Include $SITE_DIR/httpd/httpd-mkdoc.conf
+
+ <Location />
+ PerlModule MKDoc::Handler::GroupAuthz
+ PerlAuthenHandler MKDoc::Handler::GroupAuthz->null_authen_handler
+ PerlAuthzHandler MKDoc::Handler::GroupAuthz
+ AuthName "Group Authorization"
+ AuthType GroupAuthz
+ require valid-group
+ </Location>
+
</VirtualHost>
<VirtualHost *>
Index: Schema.pm
===================================================================
RCS file: /var/spool/cvs/mkd/MKDoc/Site/Deploy/DB/Schema.pm,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -LMKDoc/Site/Deploy/DB/Schema.pm -LMKDoc/Site/Deploy/DB/Schema.pm -u -r1.1.2.6 -r1.1.2.7
--- MKDoc/Site/Deploy/DB/Schema.pm
+++ MKDoc/Site/Deploy/DB/Schema.pm
@@ -364,6 +364,63 @@
fk => { Document => { Document_ID => 'ID' } },
);
+## GRP TABLE - holds user groups. (The table can't be named Group
+## because group is a reserved word in SQL.)
+new lib::sql::Table
+ (
+ name => 'Grp',
+ pk => [ 'ID' ],
+ ai => 1,
+ cols => [
+ { name => 'ID',
+ type => lib::sql::type::Int->new( not_null => 1 ) },
+ { name => 'Name',
+ type => lib::sql::type::Char->new( size => 255 ) },
+ { name => 'Description',
+ type => lib::sql::type::Char->new( size => 255 ) },
+ ]
+ );
+
+## EDITOR GRP TABLE - holds assignments of editors (users) to
+## groups. When a user is assigned to a group she can access
+## documents assigned to that group.
+new lib::sql::Table
+ (
+ name => 'Editor_Grp',
+ pk => [ 'Editor_ID', 'Grp_ID' ],
+ cols => [
+ { name => 'Editor_ID',
+ type => lib::sql::type::Int->new( not_null => 1 ) },
+ { name => 'Grp_ID',
+ type => lib::sql::type::Int->new( not_null => 1 ) },
+ ],
+ fk => {
+ Grp => { Grp_ID => 'ID' },
+ Editor => { Editor_ID => 'ID' },
+ },
+ index => { ReverseGrpEditorIndex => [ 'Grp_ID', 'Editor_ID' ] },
+ );
+
+## DOCUMENT GRP TABLE - holds assignments of documents to groups.
+## When a document is assigned to one or more groups only members of
+## that group can access the document.
+new lib::sql::Table
+ (
+ name => 'Document_Grp',
+ pk => [ 'Document_ID', 'Grp_ID' ],
+ cols => [
+ { name => 'Document_ID',
+ type => lib::sql::type::Int->new( not_null => 1 ) },
+ { name => 'Grp_ID',
+ type => lib::sql::type::Int->new( not_null => 1 ) },
+ ],
+ fk => {
+ Grp => { Grp_ID => 'ID' },
+ Document => { Document_ID => 'ID' },
+ },
+ index => { ReverseGrpDocumentIndex => [ 'Grp_ID', 'Document_ID' ] },
+ );
+
1;
__END__
Index: UserDelete.pm
===================================================================
RCS file: /var/spool/cvs/mkd/flo/plugin/Admin/UserDelete.pm,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -Lflo/plugin/Admin/UserDelete.pm -Lflo/plugin/Admin/UserDelete.pm -u -r1.1.2.4 -r1.1.2.5
--- flo/plugin/Admin/UserDelete.pm
+++ flo/plugin/Admin/UserDelete.pm
@@ -47,6 +47,11 @@
{
my $self = shift;
my $user_edit = $self->user_edit();
+
+ # clear grp assignments
+ my $editor_group_t = flo::Standard::table ('Editor_Grp');
+ $editor_group_t->delete(Editor_ID => $user_edit->id);
+
$user_edit->delete();
use flo::plugin::Admin::UserList;
Index: UserModify.pm
===================================================================
RCS file: /var/spool/cvs/mkd/flo/plugin/Admin/UserModify.pm,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lflo/plugin/Admin/UserModify.pm -Lflo/plugin/Admin/UserModify.pm -u -r1.1.2.5 -r1.1.2.6
--- flo/plugin/Admin/UserModify.pm
+++ flo/plugin/Admin/UserModify.pm
@@ -70,6 +70,7 @@
$user_edit->save();
$self->insert_base_document ($user_edit->id());
+ $self->insert_groups ($user_edit->id());
$self->{ok} = 1;
return $self->http_get();
}
@@ -88,6 +89,19 @@
$base_document_t->insert (Editor_ID => $id, Document_ID => $_) for (@base_documents);
}
+# create entries in Editor_Grp for group choices
+sub insert_groups
+{
+ my ($self, $id) = @_;
+ my $cgi = flo::Standard::cgi();
+ my @groups = $cgi->param('groups');
+
+ my $editor_group_t = flo::Standard::table ('Editor_Grp');
+ $editor_group_t->delete(Editor_ID => $id);
+ $editor_group_t->insert(Editor_ID => $id, Grp_ID => $_)
+ for @groups;
+}
+
sub documents
{
@@ -102,7 +116,20 @@
return wantarray ? @res : \@res;
}
+# return list of available groups for template
+sub groups {
+ my $self = shift;
+ my $document_t = flo::Standard::table ('Grp');
+ my @res = $document_t->select (
+ cols => ['ID', 'Name' ],
+ sort => [ 'Name' ],
+ desc => 0,
+ )->fetch_all();
+ return wantarray ? @res : \@res;
+}
+
+# returns true if the document is selected, false if not
sub is_selected
{
my $self = shift;
@@ -114,5 +141,21 @@
return;
}
+# returns true if the group is selected, false if not
+sub is_group_selected {
+ my ($self, $id) = @_;
+
+ # look for a row for this editor and group in the Editor_Grp table
+ my $grp_t = flo::Standard::table ('Editor_Grp');
+ my @res = $grp_t->select (
+ cols => ['Grp_ID'],
+ where => lib::sql::Condition->new(Grp_ID => $id,
+ Editor_ID => $self->user_edit->id)
+ )->fetch_all();
+
+ return 1 if @res;
+ return;
+}
+
1;
Index: UserInsert.pm
===================================================================
RCS file: /var/spool/cvs/mkd/flo/plugin/Admin/UserInsert.pm,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -Lflo/plugin/Admin/UserInsert.pm -Lflo/plugin/Admin/UserInsert.pm -u -r1.1.2.3 -r1.1.2.4
--- flo/plugin/Admin/UserInsert.pm
+++ flo/plugin/Admin/UserInsert.pm
@@ -45,6 +45,7 @@
$self->has_errors() and return $self->http_get();
$self->insert_base_document ($user->id());
+ $self->insert_groups ($user->id());
$self->{ok} = 1;
$cgi->delete ($cgi->param());
@@ -64,6 +65,18 @@
$base_document_t->insert (Editor_ID => $id, Document_ID => $_) for (@base_documents);
}
+# create entries in Editor_Grp for group choices
+sub insert_groups
+{
+ my ($self, $id) = @_;
+ my $cgi = flo::Standard::cgi();
+ my @groups = $cgi->param('groups');
+
+ my $editor_group_t = flo::Standard::table ('Editor_Grp');
+ $editor_group_t->delete(Editor_ID => $id);
+ $editor_group_t->insert(Editor_ID => $id, Grp_ID => $_)
+ for @groups;
+}
sub documents
{
@@ -78,6 +91,18 @@
return wantarray ? @res : \@res;
}
+# return list of available groups for template
+sub groups {
+ my $self = shift;
+ my $document_t = flo::Standard::table ('Grp');
+ my @res = $document_t->select (
+ cols => ['ID', 'Name' ],
+ sort => [ 'Name' ],
+ desc => 0,
+ )->fetch_all();
+
+ return wantarray ? @res : \@res;
+}
sub is_selected
{
Index: en.html
===================================================================
RCS file: /var/spool/cvs/mkd/templates/admin/user_insert/Attic/en.html,v
retrieving revision 1.1.2.16
retrieving revision 1.1.2.17
diff -Ltemplates/admin/user_insert/en.html -Ltemplates/admin/user_insert/en.html -u -r1.1.2.16 -r1.1.2.17
--- templates/admin/user_insert/en.html
+++ templates/admin/user_insert/en.html
@@ -292,6 +292,43 @@
<em
class="help"
>
+ Users may belong to one or more groups.
+ You can use groups to restrict access to areas
+ of your site to groups of users. This restriction affects
+ both editing and viewing. To select multiple groups or
+ select no groups you might need to use the
+ <kbd>Ctrl</kbd> key.
+ </em>
+ <label
+ for="groups"
+ >Group(s)</label>
+ <br />
+ <select
+ multiple="multiple"
+ size="5"
+ id="groups"
+ name="groups"
+ >
+ <option
+ title="Bar"
+ petal:repeat="group self/groups"
+ petal:attributes="value group/ID;
+ title group/ID;"
+ petal:content="group/Name"
+ >Happy People</option>
+ </select>
+ </p>
+
+ <p
+ lang="en"
+ xml:lang="en"
+ dir="ltr"
+ align="left"
+ petal:attributes="align align"
+ >
+ <em
+ class="help"
+ >
Accounts can be enabled, which means that they can be used, or disabled which means that
they can't be used.
</em>
Index: en.html
===================================================================
RCS file: /var/spool/cvs/mkd/templates/admin/user_modify/Attic/en.html,v
retrieving revision 1.1.2.16
retrieving revision 1.1.2.17
diff -Ltemplates/admin/user_modify/en.html -Ltemplates/admin/user_modify/en.html -u -r1.1.2.16 -r1.1.2.17
--- templates/admin/user_modify/en.html
+++ templates/admin/user_modify/en.html
@@ -288,6 +288,44 @@
>/foo/bar/</option>
</select>
</p>
+
+ <p
+ lang="en"
+ xml:lang="en"
+ dir="ltr"
+ align="left"
+ petal:attributes="align align"
+ >
+ <em
+ class="help"
+ >
+ Users may belong to one or more groups.
+ You can use groups to restrict access to areas
+ of your site to groups of users. This restriction affects
+ both editing and viewing. To select multiple groups or
+ select no groups you might need to use the
+ <kbd>Ctrl</kbd> key.
+ </em>
+ <label
+ for="groups"
+ >Group(s)</label>
+ <br />
+ <select
+ multiple="multiple"
+ size="5"
+ id="groups"
+ name="groups"
+ >
+ <option
+ title="Bar"
+ petal:repeat="group self/groups"
+ petal:attributes="selected self/is_group_selected $group/ID;
+ value group/ID;
+ title group/ID;"
+ petal:content="group/Name"
+ >Happy People</option>
+ </select>
+ </p>
<p
lang="en"
More information about the MKDoc-commit
mailing list