diff options
-rw-r--r-- | IkiWiki.pm | 4 | ||||
-rw-r--r-- | IkiWiki/Plugin/bzr.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/git.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/mercurial.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/monotone.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/svn.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/tla.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/websetup.pm | 158 | ||||
-rw-r--r-- | IkiWiki/Setup.pm | 6 | ||||
-rw-r--r-- | IkiWiki/Setup/Standard.pm | 2 | ||||
-rw-r--r-- | doc/plugins/websetup.mdwn | 19 | ||||
-rw-r--r-- | doc/setup.mdwn | 5 | ||||
l--------- | websetup.pm | 1 |
13 files changed, 171 insertions, 36 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm index 241a7c036..51e683bb4 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -92,7 +92,7 @@ sub getsetup () { #{{{ type => "string", default => '', example => "/var/www/wiki/ikiwiki.cgi", - description => "cgi executable to generate", + description => "cgi wrapper to generate", safe => 0, # file rebuild => 0, }, @@ -288,7 +288,7 @@ sub getsetup () { #{{{ banned_users => { type => "string", default => [], - description => "users who cannot use the wiki", + description => "users who are banned from the wiki", safe => 1, rebuild => 0, }, diff --git a/IkiWiki/Plugin/bzr.pm b/IkiWiki/Plugin/bzr.pm index 99025a973..0b5059292 100644 --- a/IkiWiki/Plugin/bzr.pm +++ b/IkiWiki/Plugin/bzr.pm @@ -36,7 +36,7 @@ sub getsetup () { #{{{ bzr_wrapper => { type => "string", #example => "", # FIXME add example - description => "bzr post-commit executable to generate", + description => "bzr post-commit hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index d1c1165e0..b6ad43167 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -45,7 +45,7 @@ sub getsetup () { #{{{ git_wrapper => { type => "string", example => "/git/wiki.git/hooks/post-update", - description => "git post-update executable to generate", + description => "git post-update hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/mercurial.pm b/IkiWiki/Plugin/mercurial.pm index d2c34fa6a..23bebaaad 100644 --- a/IkiWiki/Plugin/mercurial.pm +++ b/IkiWiki/Plugin/mercurial.pm @@ -36,7 +36,7 @@ sub getsetup () { #{{{ mercurial_wrapper => { type => "string", #example => # FIXME add example - description => "mercurial post-commit executable to generate", + description => "mercurial post-commit hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/monotone.pm b/IkiWiki/Plugin/monotone.pm index 4b9be316a..bdc6ee786 100644 --- a/IkiWiki/Plugin/monotone.pm +++ b/IkiWiki/Plugin/monotone.pm @@ -68,7 +68,7 @@ sub getsetup () { #{{{ mtn_wrapper => { type => "string", example => "/srv/mtn/wiki/_MTN/ikiwiki-netsync-hook", - description => "monotone netsync hook executable to generate", + description => "monotone netsync hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/svn.pm b/IkiWiki/Plugin/svn.pm index 51683704c..c51b0f181 100644 --- a/IkiWiki/Plugin/svn.pm +++ b/IkiWiki/Plugin/svn.pm @@ -58,7 +58,7 @@ sub getsetup () { #{{{ svn_wrapper => { type => "string", example => "/svn/wikirepo/hooks/post-commit", - description => "svn post-commit executable to generate", + description => "svn post-commit hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/tla.pm b/IkiWiki/Plugin/tla.pm index 6faaecccc..1c2763359 100644 --- a/IkiWiki/Plugin/tla.pm +++ b/IkiWiki/Plugin/tla.pm @@ -34,7 +34,7 @@ sub getsetup () { #{{{ tla_wrapper => { type => "string", #example => "", # TODO example - description => "tla post-commit executable to generate", + description => "tla post-commit hook to generate", safe => 0, # file rebuild => 0, }, diff --git a/IkiWiki/Plugin/websetup.pm b/IkiWiki/Plugin/websetup.pm index 2b9240a29..c22516eec 100644 --- a/IkiWiki/Plugin/websetup.pm +++ b/IkiWiki/Plugin/websetup.pm @@ -9,11 +9,11 @@ my @rcs_plugins=(qw{git svn bzr mercurial monotone tla norcs}); # amazon_s3 is not something that should be enabled via the web. # external is not a standalone plugin. -my @default_force_plugins=(qw{amazon_s3 external}); +my @force_plugins=(qw{amazon_s3 external}); sub import { #{{{ - hook(type => "checkconfig", id => "websetup", call => \&checkconfig); hook(type => "getsetup", id => "websetup", call => \&getsetup); + hook(type => "checkconfig", id => "websetup", call => \&checkconfig); hook(type => "sessioncgi", id => "websetup", call => \&sessioncgi); hook(type => "formbuilder_setup", id => "websetup", call => \&formbuilder_setup); @@ -23,23 +23,34 @@ sub getsetup () { #{{{ return websetup_force_plugins => { type => "string", - example => \@default_force_plugins, + example => [], description => "list of plugins that cannot be enabled/disabled via the web interface", safe => 0, rebuild => 0, }, + websetup_show_unsafe => { + type => "boolean", + example => 1, + description => "show unsafe settings, read-only, in web interface?", + safe => 0, + rebuild => 0, + }, } #}}} sub checkconfig () { #{{{ - if (! exists $config{websetup_force_plugins}) { - $config{websetup_force_plugins}=\@default_force_plugins; + if (! exists $config{websetup_show_unsafe}) { + $config{websetup_show_unsafe}=1; } } #}}} -sub formatexample ($) { #{{{ +sub formatexample ($$) { #{{{ my $example=shift; + my $value=shift; - if (defined $example && ! ref $example && length $example) { + if (defined $value && length $value) { + return ""; + } + elsif (defined $example && ! ref $example && length $example) { return "<br/ ><small>Example: <tt>$example</tt></small>"; } else { @@ -57,23 +68,31 @@ sub showfields ($$$@) { #{{{ my $key=shift; my %info=%{shift()}; - # skip complex, unsafe, or internal settings - next if ref $config{$key} || ! $info{safe} || $info{type} eq "internal"; + # skip internal settings + next if $info{type} eq "internal"; + # XXX hashes not handled yet + next if ref $config{$key} && ref $config{$key} eq 'HASH' || ref $info{example} eq 'HASH'; + # maybe skip unsafe settings + next if ! $info{safe} && ! $config{websetup_show_unsafe}; # these are handled specially, so don't show next if $key eq 'add_plugins' || $key eq 'disable_plugins'; push @show, $key, \%info; } - return 0 unless @show; + return unless @show; my $section=defined $plugin ? $plugin." ".gettext("plugin") : gettext("main"); + my %shownfields; if (defined $plugin) { - if (! showplugintoggle($form, $plugin, $enabled, $section) && ! $enabled) { + if (showplugintoggle($form, $plugin, $enabled, $section)) { + $shownfields{"enable.$plugin"}=[$plugin]; + } + elsif (! $enabled) { # plugin not enabled and cannot be, so skip showing # its configuration - return 0; + return; } } @@ -85,12 +104,23 @@ sub showfields ($$$@) { #{{{ my $value=$config{$key}; # multiple plugins can have the same field my $name=defined $plugin ? $plugin.".".$key : $key; - - if ($info{type} eq "string") { + + if (ref $config{$key} eq 'ARRAY' || ref $info{example} eq 'ARRAY') { + $form->field( + name => $name, + label => $description, + comment => formatexample($info{example}, $value), + type => "text", + value => [ref $value eq 'ARRAY' ? @{$value} : "", , "", ""], + size => 60, + fieldset => $section, + ); + } + elsif ($info{type} eq "string") { $form->field( name => $name, label => $description, - comment => defined $value && length $value ? "" : formatexample($info{example}), + comment => formatexample($info{example}, $value), type => "text", value => $value, size => 60, @@ -101,7 +131,7 @@ sub showfields ($$$@) { #{{{ $form->field( name => $name, label => $description, - comment => formatexample($info{example}), + comment => formatexample($info{example}, $value), type => "text", value => $value, size => 60, @@ -113,6 +143,7 @@ sub showfields ($$$@) { #{{{ $form->field( name => $name, label => $description, + comment => formatexample($info{example}, $value), type => "text", value => $value, size => 5, @@ -130,9 +161,17 @@ sub showfields ($$$@) { #{{{ fieldset => $section, ); } + + if (! $info{safe}) { + $form->field(name => $name, disabled => 1); + $form->text(gettext("Note: Disabled options cannot be configured here, but only by editing the setup file.")); + } + else { + $shownfields{$name}=[$key, \%info]; + } } - return 1; + return %shownfields; } #}}} sub showplugintoggle ($$$$) { #{{{ @@ -141,7 +180,13 @@ sub showplugintoggle ($$$$) { #{{{ my $enabled=shift; my $section=shift; - return 0 if (grep { $_ eq $plugin } @{$config{websetup_force_plugins}}, @rcs_plugins); + if (exists $config{websetup_force_plugins} && + grep { $_ eq $plugin } @{$config{websetup_force_plugins}}) { + return 0; + } + if (grep { $_ eq $plugin } @force_plugins, @rcs_plugins) { + return 0; + } $form->field( name => "enable.$plugin", @@ -191,7 +236,7 @@ sub showform ($$) { #{{{ $form->field(name => "do", type => "hidden", value => "setup", force => 1); - showfields($form, undef, undef, IkiWiki::getsetup()); + my %fields=showfields($form, undef, undef, IkiWiki::getsetup()); # record all currently enabled plugins before all are loaded my %enabled_plugins=%IkiWiki::loaded_plugins; @@ -206,21 +251,84 @@ sub showform ($$) { #{{{ # skip all rcs plugins except for the one in use next if $plugin ne $config{rcs} && grep { $_ eq $plugin } @rcs_plugins; - delete $plugins{$plugin} if showfields($form, $plugin, $enabled_plugins{$plugin}, @{$setup}); + my %shown=showfields($form, $plugin, $enabled_plugins{$plugin}, @{$setup}); + if (%shown) { + delete $plugins{$plugin}; + $fields{$_}=$shown{$_} foreach keys %shown; + } } # list all remaining plugins (with no setup options) at the end - showplugintoggle($form, $_, $enabled_plugins{$_}, gettext("other plugins")) - foreach sort keys %plugins; + foreach (sort keys %plugins) { + if (showplugintoggle($form, $_, $enabled_plugins{$_}, gettext("other plugins"))) { + $fields{"enable.$_"}=[$_]; + } + } if ($form->submitted eq "Cancel") { IkiWiki::redirect($cgi, $config{url}); return; } - elsif ($form->submitted eq 'Save Setup' && $form->validate) { - # TODO + elsif (($form->submitted eq 'Save Setup' || $form->submitted eq 'Rebuild Wiki') && $form->validate) { + my %rebuild; + foreach my $field (keys %fields) { + if ($field=~/^enable\./) { + # rebuild is overkill for many plugins, + # but no good way to tell which + $rebuild{$field}=1; # TODO only if state changed tho + # TODO plugin enable/disable + next; + } + + my %info=%{$fields{$field}->[1]}; + my $key=$fields{$field}->[0]; + my @value=$form->field($field); + + if (! $info{safe}) { + error("unsafe field $key"); # should never happen + } + + next unless @value; + # Avoid setting fields to empty strings, + # if they were not set before. + next if ! defined $config{$key} && ! grep { length $_ } @value; + + if (ref $config{$key} eq "ARRAY" || ref $info{example} eq "ARRAY") { + if ($info{rebuild} && (! defined $config{$key} || (@{$config{$key}}) != (@value))) { + $rebuild{$field}=1; + } + $config{$key}=\@value; + } + elsif (ref $config{$key} || ref $info{example}) { + error("complex field $key"); # should never happen + } + else { + if ($info{rebuild} && (! defined $config{$key} || $config{$key} ne $value[0])) { + $rebuild{$field}=1; + } + $config{$key}=$value[0]; + } + } - $form->text(gettext("Setup saved.")); + if (%rebuild && $form->submitted eq 'Save Setup') { + $form->text(gettext("The configuration changes shown below require a wiki rebuild to take effect.")); + foreach my $field ($form->field) { + next if $rebuild{$field}; + $form->field(name => $field, type => "hidden", + force => 1); + } + $form->reset(0); # doesn't really make sense here + $buttons=["Rebuild Wiki", "Cancel"]; + } + else { + # TODO save to real path + IkiWiki::Setup::dump("/tmp/s"); + $form->text(gettext("Setup saved.")); + + if (%rebuild) { + # TODO rebuild + } + } } IkiWiki::showform($form, $buttons, $session, $cgi); diff --git a/IkiWiki/Setup.pm b/IkiWiki/Setup.pm index d14be879d..02a462082 100644 --- a/IkiWiki/Setup.pm +++ b/IkiWiki/Setup.pm @@ -76,6 +76,10 @@ sub getsetup () { #{{{ # [plugin, setup] pairs. my @ret; + # disable logging to syslog while dumping, broken plugins may whine when loaded + my $syslog=$config{syslog}; + $config{syslog}=0; + # Load all plugins, so that all setup options are available. my @plugins=grep { $_ ne $config{rcs} } sort(IkiWiki::listplugins()); unshift @plugins, $config{rcs} if $config{rcs}; # rcs plugin 1st @@ -94,6 +98,8 @@ sub getsetup () { #{{{ push @ret, [ $plugin, \@s ], } } + + $config{syslog}=$syslog; return @ret; } #}}} diff --git a/IkiWiki/Setup/Standard.pm b/IkiWiki/Setup/Standard.pm index 0e640f8ac..dd613fd03 100644 --- a/IkiWiki/Setup/Standard.pm +++ b/IkiWiki/Setup/Standard.pm @@ -28,7 +28,7 @@ sub dumpline ($$$$) { #{{{ local $Data::Dumper::Quotekeys=0; my $dumpedvalue; - if ($type eq 'boolean' || $type eq 'integer') { + if (($type eq 'boolean' || $type eq 'integer') && $value=~/^[0-9]+$/) { # avoid quotes $dumpedvalue=$value; } diff --git a/doc/plugins/websetup.mdwn b/doc/plugins/websetup.mdwn new file mode 100644 index 000000000..1e4ed4d0c --- /dev/null +++ b/doc/plugins/websetup.mdwn @@ -0,0 +1,19 @@ +[[!template id=plugin name=websetup core=0 author="[[Joey]]"]] +[[!tag type/useful]] + +This plugin allows wiki admins to configure the wiki using a web interface, +rather than editing the setup file directly. A "Wiki Setup" button is added to the +admins' preferences page. + +Most settings can be modified using the web interface. Some settings are +not considered safe enough to be manipulated over the web; these are still +shown, by default, but cannot be modified. To hide them, set `websetup_show_unsafe` +to false in the setup file. A few settings have too complex a data type +to be configured via the web. + +The web interface can also be used to enable and disable plugins, with +limitations. The plugin for the [[revision_control_system|rcs]] being used +cannot be enabled/disabled, and no other rcs plugins can be enabled. A few +problematic/unsafe plugins are also blacklisted from being enabled. Other +plugins that should not be enabled/disabled via the web interface can be +listed in `websetup_force_plugins` in the setup file. diff --git a/doc/setup.mdwn b/doc/setup.mdwn index 2989485f9..2d3942124 100644 --- a/doc/setup.mdwn +++ b/doc/setup.mdwn @@ -9,8 +9,9 @@ If you're not, see the [[download]] and [[install]] pages. ## Quick start -If you'd like to set up a wiki now, and learn more later, just run this command -and answer a couple of questions. +If you'd like to set up a wiki now, and learn more later, and you have +ikiwiki 2.60 or better installed, just run this command and answer a couple +of questions. % ikiwiki -setup /etc/ikiwiki/auto.setup What will the wiki be named? mywiki diff --git a/websetup.pm b/websetup.pm new file mode 120000 index 000000000..8ca7a8a64 --- /dev/null +++ b/websetup.pm @@ -0,0 +1 @@ +/home/joey/src/ikiwiki/IkiWiki/Plugin/websetup.pm
\ No newline at end of file |