summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2021-06-28 11:13:18 +0200
committerYorhel <git@yorhel.nl>2021-06-28 11:13:18 +0200
commit823536f5ef4eaaa629888aa829e07877a4aa44b6 (patch)
tree003f7aa03c819817b7d0f9fbc6de1d709cf2fdf9 /lib
parenta2794afdc01d464c1e4a2046fd6c6c9ae862afca (diff)
Add a few global lockdown modes
Diffstat (limited to 'lib')
-rw-r--r--lib/VNWeb/DB.pm7
-rw-r--r--lib/VNWeb/HTML.pm6
-rw-r--r--lib/VNWeb/Images/Upload.pm2
-rw-r--r--lib/VNWeb/Images/Vote.pm9
-rw-r--r--lib/VNWeb/Misc/Lockdown.pm54
-rw-r--r--lib/VNWeb/User/Register.pm10
-rw-r--r--lib/VNWeb/VN/Tagmod.pm8
-rw-r--r--lib/VNWeb/Validation.pm6
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}));
}