Author: dom
Date: 2008-10-20 00:24:51 +0100 (Mon, 20 Oct 2008)
New Revision: 1240
Added:
trunk/t/81_node_moderate_whitelist.t
Modified:
trunk/Build.PL
trunk/Changes
trunk/MANIFEST
trunk/lib/OpenGuides.pm
trunk/lib/OpenGuides/Config.pm
trunk/lib/OpenGuides/Test.pm
trunk/lib/OpenGuides/Utils.pm
Log:
Add the ability to whitelist hosts who can change moderated nodes
without explicit moderation - thanks Oliver (fixes #203)
Modified: trunk/Build.PL
===================================================================
--- trunk/Build.PL 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/Build.PL 2008-10-19 23:24:51 UTC (rev 1240)
@@ -311,6 +311,8 @@
'URI::Escape' => 0,
'XML::RSS' => 0,
'Data::Validate::URI' => 0,
+ 'Net::Netmask' => 0,
+ 'List::Utils' => 0,
},
build_requires => {
'Module::Build' => '0.26', # API change for accessing config
data
Modified: trunk/Changes
===================================================================
--- trunk/Changes 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/Changes 2008-10-19 23:24:51 UTC (rev 1240)
@@ -16,6 +16,8 @@
Fix install with CPAN when Config::Tiny not already installed (#224)
Add an admin navbar, to be displayed if the user requests (#261)
Move the node image outside the metadata div, to aid styling (#222)
+ Add the ability to whitelist hosts who can change moderated nodes
+ without explicit moderation (#203)
0.63 16 August 2008
Major overhaul of RDF output.
Modified: trunk/MANIFEST
===================================================================
--- trunk/MANIFEST 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/MANIFEST 2008-10-19 23:24:51 UTC (rev 1240)
@@ -145,6 +145,7 @@
t/77_send_email.t
t/78_about.t
t/79_host_blacklist.t
+t/81_node_moderate_whitelist.t
t/85_universal_edit_link.t
t/templates/15_test.tt
wiki.cgi
Modified: trunk/lib/OpenGuides/Config.pm
===================================================================
--- trunk/lib/OpenGuides/Config.pm 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/lib/OpenGuides/Config.pm 2008-10-19 23:24:51 UTC (rev 1240)
@@ -22,7 +22,8 @@
custom_template_path geo_handler ellipsoid gmaps_api_key centre_long
show_gmap_in_node_display google_analytics_key
centre_lat default_gmaps_zoom default_gmaps_search_zoom force_wgs84
- licence_name licence_url licence_info_url moderation_requires_password
+ licence_name licence_url licence_info_url
+ moderation_requires_password moderate_whitelist
enable_node_image enable_common_categories enable_common_locales
spam_detector_module host_checker_module static_path static_url
send_moderation_notifications website_link_max_chars
@@ -80,6 +81,7 @@
indexing_directory =>
"/usr/lib/cgi-bin/openguides/indexes/",
enable_page_deletion => 0,
moderation_requires_password => 1,
+ moderate_whitelist => "",
admin_pass => "Change This!",
enable_node_image => 1,
enable_common_categories => 0,
@@ -202,6 +204,7 @@
static_url => "What is the URL corresponding to the static
content?",
send_moderation_notifications => "Should we send email notifications when
a moderated node is edited?",
website_link_max_chars => "How many characters of the URL of node
websites should be displayed?",
+ moderate_whitelist => "Enter a comma-separated list of IP addresses able
to make changes to moderated nodes and have them show up immediately",
);
foreach my $var ( keys %questions ) {
@@ -336,6 +339,8 @@
=item * send_moderation_notifications
+=item * moderate_whitelist
+
=item * website_link_max_chars (default: C<20>)
=back
Modified: trunk/lib/OpenGuides/Test.pm
===================================================================
--- trunk/lib/OpenGuides/Test.pm 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/lib/OpenGuides/Test.pm 2008-10-19 23:24:51 UTC (rev 1240)
@@ -66,6 +66,7 @@
geo_handler => 1,
force_wgs84 => 1,
contact_email => 'admins(a)example.org'org',
+ moderate_whitelist => "",
}
);
Modified: trunk/lib/OpenGuides/Utils.pm
===================================================================
--- trunk/lib/OpenGuides/Utils.pm 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/lib/OpenGuides/Utils.pm 2008-10-19 23:24:51 UTC (rev 1240)
@@ -10,6 +10,8 @@
use Wiki::Toolkit::Plugin::RSS::Reader;
use URI::Escape;
use MIME::Lite;
+use Net::Netmask;
+use List::Util qw( first );
use Data::Validate::URI qw( is_web_uri );
=head1 NAME
@@ -497,6 +499,35 @@
}
}
+=item B<in_moderate_whitelist>
+
+ if (OpenGuides::Utils->in_moderate_whitelist( '127.0.0.1' )) {
+ # skip moderation and apply new verson to published site
+ }
+
+Admins can supply a comma separated list of IP addresses or CIDR-notation
+subnets indicating the hosts which can bypass enforced moderation. Any
+values which cannot be parsed by C<NetAddr::IP> will be ignored.
+
+=cut
+
+sub in_moderate_whitelist {
+ my ($self, $config, $ip) = @_;
+ return undef if not defined $ip;
+
+ # create NetAddr::IP object of the test IP
+ my $addr = Net::Netmask->new2($ip) or return undef;
+
+ # load the configured whitelist
+ my @whitelist
+ = split ',', $config->moderate_whitelist;
+
+ # test each entry in the whitelist
+ return eval{
+ first { Net::Netmask->new2($_)->match($addr->base) } @whitelist
+ };
+}
+
=back
=head1 AUTHOR
Modified: trunk/lib/OpenGuides.pm
===================================================================
--- trunk/lib/OpenGuides.pm 2008-10-19 17:09:42 UTC (rev 1239)
+++ trunk/lib/OpenGuides.pm 2008-10-19 23:24:51 UTC (rev 1240)
@@ -1556,7 +1556,10 @@
# Skip this for nodes needing moderation - this occurs for them once
# they've been moderated
my $needs_moderation = $wiki->node_required_moderation($node);
- unless( $needs_moderation ) {
+ my $in_moderate_whitelist
+ = OpenGuides::Utils->in_moderate_whitelist($self->config,
$new_metadata{host});
+
+ if ( $in_moderate_whitelist or not $needs_moderation ) {
$self->_autoCreateCategoryLocale(
id => $node,
metadata => \%new_metadata
@@ -1567,22 +1570,30 @@
\%new_metadata );
if ($written) {
- if ( $needs_moderation and $config->send_moderation_notifications ) {
- my $body = "The node '$node' in the OpenGuides
installation\n" .
- "'" . $config->site_name . "' requires
moderation. ".
- "Please visit\n" .
- $config->script_url . $config->script_name .
- "?action=show_needing_moderation\nat your convenience.\n";
- eval {
- OpenGuides::Utils->send_email(
- config => $config,
- subject => "Node requires moderation",
- body => $body,
- admin => 1,
- return_output => $return_output
+ if ( $needs_moderation ) {
+ if ( $in_moderate_whitelist ) {
+ $self->wiki->moderate_node(
+ name => $node,
+ version => $written
);
- };
- warn $@ if $@;
+ }
+ elsif ( $config->send_moderation_notifications ) {
+ my $body = "The node '$node' in the OpenGuides
installation\n" .
+ "'" . $config->site_name . "' requires
moderation. ".
+ "Please visit\n" .
+ $config->script_url . $config->script_name .
+ "?action=show_needing_moderation\nat your convenience.\n";
+ eval {
+ OpenGuides::Utils->send_email(
+ config => $config,
+ subject => "Node requires moderation",
+ body => $body,
+ admin => 1,
+ return_output => $return_output
+ );
+ };
+ warn $@ if $@;
+ }
}
my $output = $self->redirect_to_node($node);
Added: trunk/t/81_node_moderate_whitelist.t
===================================================================
--- trunk/t/81_node_moderate_whitelist.t (rev 0)
+++ trunk/t/81_node_moderate_whitelist.t 2008-10-19 23:24:51 UTC (rev 1240)
@@ -0,0 +1,96 @@
+use strict;
+use Wiki::Toolkit::Setup::SQLite;
+use OpenGuides;
+use OpenGuides::Test;
+use Test::More;
+
+eval { require DBD::SQLite; };
+
+if ( $@ ) {
+ my ($error) = $@ =~ /^(.*?)\n/;
+ plan skip_all => "DBD::SQLite could not be used - no database to test with
($error)";
+}
+
+plan tests => 12;
+
+Wiki::Toolkit::Setup::SQLite::setup( { dbname => "t/node.db" } );
+my $config = OpenGuides::Test->make_basic_config;
+$config->script_name( "wiki.cgi" );
+$config->script_url( "http://example.com/" );
+$config->moderate_whitelist( "127.0.0.1,127.0.0.2" );
+my $guide = OpenGuides->new( config => $config );
+isa_ok( $guide, "OpenGuides" );
+my $wiki = $guide->wiki;
+isa_ok( $wiki, "Wiki::Toolkit" );
+
+# Clear out the database from any previous runs.
+foreach my $del_node ( $wiki->list_all_nodes ) {
+ print "# Deleting node $del_node\n";
+ $wiki->delete_node( $del_node ) or die "Can't delete $del_node";
+}
+
+
+# Add a page
+my $q = CGI->new;
+$q->param( -name => "content", -value => "foo" );
+$q->param( -name => "categories", -value => "Alpha" );
+$q->param( -name => "locales", -value => "" );
+$q->param( -name => "phone", -value => "" );
+$q->param( -name => "fax", -value => "" );
+$q->param( -name => "website", -value => "" );
+$q->param( -name => "hours_text", -value => "" );
+$q->param( -name => "address", -value => "" );
+$q->param( -name => "postcode", -value => "" );
+$q->param( -name => "map_link", -value => "" );
+$q->param( -name => "os_x", -value => "" );
+$q->param( -name => "os_y", -value => "" );
+$q->param( -name => "username", -value => "bob" );
+$q->param( -name => "comment", -value => "foo" );
+$q->param( -name => "edit_type", -value => "Minor tidying"
);
+$ENV{REMOTE_ADDR} = "127.0.0.1";
+
+my $output = $guide->commit_node(
+ return_output => 1,
+ id => "Wombats",
+ cgi_obj => $q,
+ );
+
+# Check it's moderated
+my %details = $wiki->retrieve_node("Wombats");
+is($details{'moderated'}, 1, "Moderated");
+is($wiki->node_required_moderation("Wombats"), 0, "No
moderation");
+
+# Turn on moderation
+$wiki->set_node_moderation(
+ name => "Wombats",
+ required => 1,
+);
+is($wiki->node_required_moderation("Wombats"), 1, "Moderation");
+
+
+# Now add a new one, with new categories and locales
+$q->param( -name => "categories", -value => "Alpha\r\nBeta"
);
+$q->param( -name => "locales", -value => "Hello" );
+$q->param( -name => "edit_type", -value => "Normal edit" );
+$q->param( -name => "checksum", -value => $details{checksum} );
+$output = $guide->commit_node(
+ return_output => 1,
+ id => "Wombats",
+ cgi_obj => $q,
+ );
+
+# Check that the current version is now 2
+%details = $wiki->retrieve_node("Wombats");
+is($details{'version'}, 2, "Still on v1");
+is($details{'moderated'}, 1, "v1 Moderated");
+
+# Check that version 2 is moderated
+my %v2 = $wiki->retrieve_node(name=>"Wombats",version=>2);
+is($v2{'version'}, 2, "Is v2");
+is($v2{'moderated'}, 1, "Moderated");
+
+# Check that the new categories and locales are there
+is(1, $wiki->node_exists("Category Alpha"), "Right Categories");
+is(1, $wiki->node_exists("Category Beta"), "Right Categories");
+is(1, $wiki->node_exists("Locale Hello"), "Right Locales");
+