diff options
author | Yorhel <git@yorhel.nl> | 2021-06-28 11:13:18 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2021-06-28 11:13:18 +0200 |
commit | 823536f5ef4eaaa629888aa829e07877a4aa44b6 (patch) | |
tree | 003f7aa03c819817b7d0f9fbc6de1d709cf2fdf9 /lib | |
parent | a2794afdc01d464c1e4a2046fd6c6c9ae862afca (diff) |
Add a few global lockdown modes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/VNWeb/DB.pm | 7 | ||||
-rw-r--r-- | lib/VNWeb/HTML.pm | 6 | ||||
-rw-r--r-- | lib/VNWeb/Images/Upload.pm | 2 | ||||
-rw-r--r-- | lib/VNWeb/Images/Vote.pm | 9 | ||||
-rw-r--r-- | lib/VNWeb/Misc/Lockdown.pm | 54 | ||||
-rw-r--r-- | lib/VNWeb/User/Register.pm | 10 | ||||
-rw-r--r-- | lib/VNWeb/VN/Tagmod.pm | 8 | ||||
-rw-r--r-- | lib/VNWeb/Validation.pm | 6 |
8 files changed, 90 insertions, 12 deletions
diff --git a/lib/VNWeb/DB.pm b/lib/VNWeb/DB.pm index e86dbd66..e3c5c238 100644 --- a/lib/VNWeb/DB.pm +++ b/lib/VNWeb/DB.pm @@ -10,6 +10,7 @@ use VNDB::Schema; our @EXPORT = qw/ sql + global_settings sql_identifier sql_join sql_comma sql_and sql_or sql_array sql_func sql_fromhex sql_tohex sql_fromtime sql_totime sql_like sql_user enrich enrich_merge enrich_flatten enrich_obj db_maytimeout db_entry db_edit @@ -116,6 +117,12 @@ sub sql_user { } +# Returns a (potentially cached) version of the global_settings table. +sub global_settings { + tuwf->req->{global_settings} //= tuwf->dbRowi('SELECT * FROM global_settings'); +} + + # The enrich*() functions are based on https://dev.yorhel.nl/doc/sqlobject diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm index 58f0cf22..f71d7e6b 100644 --- a/lib/VNWeb/HTML.pm +++ b/lib/VNWeb/HTML.pm @@ -248,10 +248,10 @@ sub _menu_ { a_ href => "$uid/hist", 'My Recent Changes'; br_; a_ href => '/g/links?u='.auth->uid, 'My Tags'; br_; br_; - if(auth->permImgvote) { + if(VNWeb::Images::Vote::can_vote()) { a_ href => '/img/vote', 'Image Flagging'; br_; } - if(auth->permEdit) { + if(can_edit v => {}) { a_ href => '/v/add', 'Add Visual Novel'; br_; a_ href => '/p/add', 'Add Producer'; br_; a_ href => '/s/new', 'Add Staff'; br_; @@ -266,6 +266,8 @@ sub _menu_ { b_ class => 'grayedout', ' | '; a_ href => '/report/list?s=lastmod', sprintf '%d upd', $stats->{upd}; br_; + a_ global_settings->{lockdown_edit} || global_settings->{lockdown_board} || global_settings->{lockdown_registration} ? (class => 'standout') : (), href => '/lockdown', 'Lockdown'; + br_; } br_; form_ action => "$uid/logout", method => 'post', sub { diff --git a/lib/VNWeb/Images/Upload.pm b/lib/VNWeb/Images/Upload.pm index ce2c2ae5..2dbe4db7 100644 --- a/lib/VNWeb/Images/Upload.pm +++ b/lib/VNWeb/Images/Upload.pm @@ -10,7 +10,7 @@ TUWF::post qr{/elm/ImageUpload.json}, sub { warn "Invalid CSRF token in request\n"; return elm_CSRF; } - return elm_Unauth if !auth->permEdit; + return elm_Unauth if !(auth->permDbmod || (auth->permEdit && !global_settings->{lockdown_edit})); my $type = tuwf->validate(post => type => { enum => [qw/cv ch sf/] })->data; my $imgdata = tuwf->reqUploadRaw('img'); diff --git a/lib/VNWeb/Images/Vote.pm b/lib/VNWeb/Images/Vote.pm index 04deb786..f6419e7c 100644 --- a/lib/VNWeb/Images/Vote.pm +++ b/lib/VNWeb/Images/Vote.pm @@ -16,10 +16,13 @@ my $SEND = form_compile any => { }; +sub can_vote { auth->permImgmod || (auth->permImgvote && !global_settings->{lockdown_edit}) } + + # Fetch a list of images for the user to vote on. elm_api Images => $SEND, { excl_voted => { anybool => 1 } }, sub { my($data) = @_; - return elm_Unauth if !auth->permImgvote; + return elm_Unauth if !can_vote; state $stats = tuwf->dbRowi('SELECT COUNT(*) as total, COUNT(*) FILTER (WHERE c_weight > 0) AS referenced FROM images'); @@ -65,7 +68,7 @@ elm_api ImageVote => undef, { } }, }, sub { my($data) = @_; - return elm_Unauth if !auth->permImgvote; + return elm_Unauth if !can_vote; return elm_CSRF if !validate_token $data->{votes}; # Find out if any of these images are being overruled @@ -106,7 +109,7 @@ sub imgflag_ { TUWF::get qr{/img/vote}, sub { - return tuwf->resDenied if !auth->permImgvote; + return tuwf->resDenied if !can_vote; my $recent = tuwf->dbAlli('SELECT id FROM image_votes WHERE uid =', \auth->uid, 'ORDER BY date DESC LIMIT', \30); enrich_image 1, $recent; diff --git a/lib/VNWeb/Misc/Lockdown.pm b/lib/VNWeb/Misc/Lockdown.pm new file mode 100644 index 00000000..94408b1e --- /dev/null +++ b/lib/VNWeb/Misc/Lockdown.pm @@ -0,0 +1,54 @@ +package VNWeb::Misc::Lockdown; + +use VNWeb::Prelude; + +TUWF::get '/lockdown', sub { + return tuwf->resDenied if !auth->isMod; + + sub chk_ { + my($name, $lbl) = @_; + label_ sub { + input_ type => 'checkbox', name => $name, global_settings->{$name} ? (checked => 'checked') : (); + txt_ $lbl; + }; + br_; + } + + framework_ title => 'Database lockdown', sub { + div_ class => 'mainbox', sub { + h1_ 'Database lockdown'; + + p_ sub { + txt_ 'This form provides a sledghehammer approach to dealing with + targeted vandalism or spam attacks on the site. The goal of + these options is to put the website in a temporary lockdown + while waiting for Yorhel to wake up or while a better solution + is being worked on.'; + br_; + txt_ 'Moderators can keep using the site as usual regardless of these settings.'; + }; + + form_ action => '/lockdown', method => 'post', style => 'margin: 20px', sub { + chk_ lockdown_registration => ' Disable account creation.'; + chk_ lockdown_edit => ' Disable database editing globally. Also disables image and tag voting.'; + chk_ lockdown_board => ' Disable forum and review posting globally.'; + input_ type => 'submit', name => 'submit', class => 'submit', value => 'Submit'; + }; + }; + }; +}; + + +TUWF::post '/lockdown', sub { + return auth->resDenied if !auth->isMod || !samesite; + my $frm = tuwf->validate(post => + lockdown_registration => { anybool => 1 }, + lockdown_edit => { anybool => 1 }, + lockdown_board => { anybool => 1 }, + )->data; + tuwf->dbExeci('UPDATE global_settings SET', $frm); + auth->audit(0, 'lockdown', JSON::XS->new->encode($frm)); + tuwf->resRedirect('/lockdown', 'post'); +}; + +1; diff --git a/lib/VNWeb/User/Register.pm b/lib/VNWeb/User/Register.pm index 5cd28924..f8938a8e 100644 --- a/lib/VNWeb/User/Register.pm +++ b/lib/VNWeb/User/Register.pm @@ -6,7 +6,14 @@ use VNWeb::Prelude; TUWF::get '/u/register', sub { return tuwf->resRedirect('/', 'temp') if auth; framework_ title => 'Register', sub { - elm_ 'User.Register'; + if(global_settings->{lockdown_registration}) { + div_ class => 'mainbox', sub { + h1_ 'Create an account'; + p_ 'Account registration is temporarily disabled. Try again later.'; + } + } else { + elm_ 'User.Register'; + } }; }; @@ -17,6 +24,7 @@ elm_api UserRegister => undef, { vns => { int => 1 }, }, sub { my $data = shift; + return elm_Unauth if global_settings->{lockdown_registration}; my $num = tuwf->dbVali("SELECT count FROM stats_cache WHERE section = 'vn'"); return elm_Bot if $data->{vns} < $num*0.995 || $data->{vns} > $num*1.005; diff --git a/lib/VNWeb/VN/Tagmod.pm b/lib/VNWeb/VN/Tagmod.pm index 8d86cdfd..7a35846d 100644 --- a/lib/VNWeb/VN/Tagmod.pm +++ b/lib/VNWeb/VN/Tagmod.pm @@ -29,9 +29,13 @@ my $FORM = { my $FORM_IN = form_compile in => $FORM; my $FORM_OUT = form_compile out => $FORM; + +sub can_tag { auth->permTagmod || (auth->permTag && !global_settings->{lockdown_edit}) } + + elm_api Tagmod => $FORM_OUT, $FORM_IN, sub { my($id, $tags) = $_[0]->@{'id', 'tags'}; - return elm_Unauth if !auth->permTag; + return elm_Unauth if !can_tag; $tags = [ grep $_->{vote}, @$tags ]; $_->{overrule} = 0 for auth->permTagmod ? () : @$tags; @@ -70,7 +74,7 @@ elm_api Tagmod => $FORM_OUT, $FORM_IN, sub { TUWF::get qr{/$RE{vid}/tagmod}, sub { my $v = tuwf->dbRowi('SELECT id, title, hidden AS entry_hidden, locked AS entry_locked FROM vn WHERE id =', \tuwf->capture('id')); return tuwf->resNotFound if !$v->{id} || (!auth->permDbmod && $v->{entry_hidden}); - return tuwf->resDenied if !auth->permTag; + return tuwf->resDenied if !can_tag; my $tags = tuwf->dbAlli(' SELECT t.id, t.name, t.cat, count(*) as count, t.hidden, t.locked, t.applicable diff --git a/lib/VNWeb/Validation.pm b/lib/VNWeb/Validation.pm index cf95734c..823fde01 100644 --- a/lib/VNWeb/Validation.pm +++ b/lib/VNWeb/Validation.pm @@ -218,8 +218,8 @@ sub can_edit { return auth->permDbmod if $type eq 'd'; if($type eq 't') { - return 0 if !auth->permBoard; return 1 if auth->permBoardmod; + return 0 if !auth->permBoard || (global_settings->{lockdown_board} && !auth->isMod); if(!$entry->{id}) { # Allow at most 5 new threads per day per user. return auth && tuwf->dbVali('SELECT count(*) < ', \5, 'FROM threads_posts WHERE num = 1 AND date > NOW()-\'1 day\'::interval AND uid =', \auth->uid); @@ -235,7 +235,7 @@ sub can_edit { if($type eq 'w') { return 1 if auth->permBoardmod; - return auth->permReview if !$entry->{id}; + return auth->permReview && (!global_settings->{lockdown_board} || auth->isMod) if !$entry->{id}; return auth && auth->uid eq $entry->{user_id}; } @@ -246,7 +246,7 @@ sub can_edit { die "Can't do authorization test when entry_hidden/entry_locked fields aren't present" if $entry->{id} && (!exists $entry->{entry_hidden} || !exists $entry->{entry_locked}); - auth->permDbmod || (auth->permEdit && !($entry->{entry_hidden} || $entry->{entry_locked})); + auth->permDbmod || (auth->permEdit && !global_settings->{lockdown_edit} && !($entry->{entry_hidden} || $entry->{entry_locked})); } |