summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-04-15 11:53:38 +0200
committerYorhel <git@yorhel.nl>2020-04-15 11:53:40 +0200
commitbe5ee198129301d84912380ed8d1636ad32f68b3 (patch)
treed02840ee97c05818556f886e69bcc5783b44c229 /lib
parent5a3a446b0530632942c577edbf10e9c7c2fb6fa9 (diff)
SQL: Split "perm" column into multiple booleans
This simplifies several actions and makes permission checks more obvious. This is also yack shaving for another feature I've been planning to add: boardmods should be able to set other users' "board" permission, tagmods for tags, etc. So that partial user bans don't need the full "usermod" permission.
Diffstat (limited to 'lib')
-rw-r--r--lib/VNDB/DB/Users.pm2
-rw-r--r--lib/VNDB/Util/Auth.pm2
-rw-r--r--lib/VNWeb/Auth.pm27
-rw-r--r--lib/VNWeb/Docs/Lib.pm11
-rw-r--r--lib/VNWeb/Elm.pm1
-rw-r--r--lib/VNWeb/User/Edit.pm26
6 files changed, 25 insertions, 44 deletions
diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm
index 2f7d8e5c..85654180 100644
--- a/lib/VNDB/DB/Users.pm
+++ b/lib/VNDB/DB/Users.pm
@@ -29,7 +29,7 @@ sub dbUserGet {
);
my @select = (
- qw|id username c_votes c_changes c_tags hide_list|,
+ qw|id username c_votes c_changes c_tags|,
VNWeb::DB::sql_user(), # XXX: This duplicates id and username, but updating all the code isn't going to be easy
q|extract('epoch' from registered) as registered|,
);
diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm
index 4394149f..b05c86f9 100644
--- a/lib/VNDB/Util/Auth.pm
+++ b/lib/VNDB/Util/Auth.pm
@@ -73,7 +73,7 @@ sub authInfo {
# a certain action.
sub authCan {
my(undef, $act) = @_;
- auth->perm() & auth->listPerms->{$act}
+ auth && auth->{user}{"perm_$act"}
}
diff --git a/lib/VNWeb/Auth.pm b/lib/VNWeb/Auth.pm
index 82484397..08aa8a91 100644
--- a/lib/VNWeb/Auth.pm
+++ b/lib/VNWeb/Auth.pm
@@ -64,36 +64,20 @@ TUWF::set log_format => sub {
use overload bool => sub { defined shift->{user}{user_id} };
sub uid { shift->{user}{user_id} }
-sub perm { shift->{user}{perm}||0 }
sub user { shift->{user} }
sub token { shift->{token} }
-# The 'perm' field is a bit field, with the following bits.
-# The 'usermod' flag is hardcoded in sql/func.sql for the user_* functions.
-# Flag 256 was used for 'affiliates', now also free.
-my %perms = qw{
- board 1
- boardmod 2
- edit 4
- imgvote 8
- tag 16
- dbmod 32
- tagmod 64
- usermod 128
-};
-
-sub defaultPerms { $perms{board} + $perms{edit} + $perms{tag} + $perms{imgvote} }
-sub allPerms { my $i = 0; $i |= $_ for values %perms; $i }
-sub listPerms { \%perms }
+my @perms = qw/board boardmod edit imgvote tag dbmod tagmod usermod/;
+sub listPerms { @perms }
# Create a read-only accessor to check if the current user is authorized to
# perform a particular action.
-for my $perm (keys %perms) {
+for my $perm (@perms) {
no strict 'refs';
- *{ "perm".ucfirst($perm) } = sub { (shift->perm() & $perms{$perm}) > 0 }
+ *{ 'perm'.ucfirst($perm) } = sub { shift->{user}{"perm_$perm"} }
}
@@ -150,7 +134,8 @@ sub _load_session {
my($self, $uid, $token_db) = @_;
my $user = $uid ? tuwf->dbRowi(
- 'SELECT perm, ', sql_user(), ' FROM users u
+ 'SELECT ', sql_user(), ',', sql_comma(map "perm_$_", @perms), '
+ FROM users u
WHERE id = ', \$uid,
'AND', sql_func(user_isvalidsession => 'id', sql_fromhex($token_db), \'web')
) : {};
diff --git a/lib/VNWeb/Docs/Lib.pm b/lib/VNWeb/Docs/Lib.pm
index e6805d45..aeb4f172 100644
--- a/lib/VNWeb/Docs/Lib.pm
+++ b/lib/VNWeb/Docs/Lib.pm
@@ -5,16 +5,19 @@ use VNWeb::Prelude;
our @EXPORT = qw/enrich_html/;
+my @special_perms = qw/boardmod dbmod usermod tagmod/;
+
sub _moderators {
- my $l = tuwf->dbAlli('SELECT id, username, perm FROM users WHERE (perm & ', \(auth->allPerms &~ auth->defaultPerms), ') > 0 ORDER BY id LIMIT 100');
- my @modperms = grep 0 == (auth->listPerms->{$_} & auth->defaultPerms), keys auth->listPerms->%*;
+ my $cols = sql_comma map "perm_$_", @special_perms;
+ my $where = sql_or map "perm_$_", @special_perms;
+ my $l = tuwf->dbAlli("SELECT id, username, $cols FROM users WHERE $where ORDER BY id LIMIT 100");
xml_string sub {
dl_ sub {
for my $u (@$l) {
dt_ sub { a_ href => "/u$u->{id}", $u->{username} };
- dd_ auth->allPerms == ($u->{perm} & auth->allPerms) ? 'admin'
- : join ', ', sort grep $u->{perm} & auth->listPerms->{$_}, @modperms;
+ dd_ @special_perms == grep($u->{"perm_$_"}, @special_perms) ? 'admin'
+ : join ', ', grep $u->{"perm_$_"}, @special_perms;
}
}
}
diff --git a/lib/VNWeb/Elm.pm b/lib/VNWeb/Elm.pm
index 70871bdd..d6d8d862 100644
--- a/lib/VNWeb/Elm.pm
+++ b/lib/VNWeb/Elm.pm
@@ -351,7 +351,6 @@ sub write_types {
$data .= def urlStatic => String => string config->{url_static};
$data .= def adminEMail => String => string config->{admin_email};
- $data .= def userPerms => 'List (Int, String)' => list map tuple(VNWeb::Auth::listPerms->{$_}, string $_), sort keys VNWeb::Auth::listPerms->%*;
$data .= def skins => 'List (String, String)' =>
list map tuple(string $_, string tuwf->{skins}{$_}[0]),
sort { tuwf->{skins}{$a}[0] cmp tuwf->{skins}{$b}[0] } keys tuwf->{skins}->%*;
diff --git a/lib/VNWeb/User/Edit.pm b/lib/VNWeb/User/Edit.pm
index bfd2e5f8..0153dfdb 100644
--- a/lib/VNWeb/User/Edit.pm
+++ b/lib/VNWeb/User/Edit.pm
@@ -6,7 +6,6 @@ use VNWeb::Prelude;
my $FORM = form_compile in => {
username => { username => 1 },
email => { email => 1 },
- perm => { uint => 1, func => sub { ($_[0] & ~auth->allPerms) == 0 } },
ign_votes => { anybool => 1 },
show_nsfw => { anybool => 1 },
traits_sexual => { anybool => 1 },
@@ -17,6 +16,7 @@ my $FORM = form_compile in => {
spoilers => { uint => 1, range => [ 0, 2 ] },
skin => { enum => tuwf->{skins} },
customcss => { required => 0, default => '', maxlength => 2000 },
+ map(+("perm_$_" => { anybool => 1 }), VNWeb::Auth::listPerms),
nodistract_can => { anybool => 1 },
nodistract_noads => { anybool => 1 },
@@ -47,8 +47,9 @@ sub _getmail {
}
TUWF::get qr{/$RE{uid}/edit}, sub {
+ my $permcols = sql_comma map "perm_$_", auth->listPerms;
my $u = tuwf->dbRowi(q{
- SELECT id, username, perm, ign_votes, show_nsfw, traits_sexual
+ SELECT id, username, ign_votes, show_nsfw, traits_sexual,}, $permcols, q{
, tags_all, tags_cont, tags_ero, tags_tech, spoilers, skin, customcss
, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled
FROM users WHERE id =}, \tuwf->capture('id')
@@ -61,12 +62,6 @@ TUWF::get qr{/$RE{uid}/edit}, sub {
$u->{password} = undef;
$u->{skin} ||= config->{skin_default};
- # Let's not disclose this (though it's not hard to find out through other means)
- if(!auth->permUsermod) {
- $u->{ign_votes} = 0;
- $u->{perm} = auth->defaultPerms;
- }
-
my $title = $u->{id} == auth->uid ? 'My Account' : "Edit $u->{username}";
framework_ title => $title, type => 'u', dbobj => $u, tab => 'edit',
sub {
@@ -85,13 +80,18 @@ elm_api UserEdit => undef, $FORM, sub {
return elm_Taken if $data->{uniname}
&& tuwf->dbVali('SELECT 1 FROM users WHERE id <>', \$data->{id}, 'AND username =', \lc($data->{uniname}));
+ my @setcols = qw/
+ show_nsfw traits_sexual tags_all tags_cont tags_ero tags_tech spoilers skin customcss
+ nodistract_noads nodistract_nofancy support_enabled uniname pubskin_enabled
+ /;
if(auth->permUsermod) {
tuwf->dbExeci(update => users => set => {
username => $data->{username},
ign_votes => $data->{ign_votes},
email_confirmed => 1,
}, where => { id => $data->{id} });
- tuwf->dbExeci(select => sql_func user_setperm => \$data->{id}, \auth->uid, sql_fromhex(auth->token), \$data->{perm});
+ tuwf->dbExeci(select => sql_func user_setperm_usermod => \$data->{id}, \auth->uid, sql_fromhex(auth->token), \$data->{perm_usermod});
+ push @setcols, map "perm_$_", grep $_ ne 'usermod', auth->listPerms;
}
if($data->{password}) {
@@ -136,13 +136,7 @@ elm_api UserEdit => undef, $FORM, sub {
$data->{skin} = '' if $data->{skin} eq config->{skin_default};
$data->{uniname} = '' if $data->{uniname} eq $data->{username};
- tuwf->dbExeci('UPDATE users SET', { %{$data}{qw/
- show_nsfw traits_sexual tags_all tags_cont tags_ero tags_tech spoilers skin customcss
- nodistract_noads nodistract_nofancy support_enabled uniname pubskin_enabled
- /} },
- 'WHERE id =', \$data->{id}
- );
-
+ tuwf->dbExeci('UPDATE users SET', { %{$data}{@setcols} }, 'WHERE id =', \$data->{id});
$ret->();
};