674 lines
23 KiB
Perl
674 lines
23 KiB
Perl
|
|
#!/usr/bin/perl
|
||
|
|
#
|
||
|
|
# DW::Controller::Admin::VirtualGift
|
||
|
|
#
|
||
|
|
# Management pages for virtual gifts in the shop.
|
||
|
|
#
|
||
|
|
# Authors:
|
||
|
|
# Jen Griffin <kareila@livejournal.com>
|
||
|
|
#
|
||
|
|
# Copyright (c) 2020 by Dreamwidth Studios, LLC.
|
||
|
|
#
|
||
|
|
# This program is free software; you may redistribute it and/or modify it under
|
||
|
|
# the same terms as Perl itself. For a copy of the license, please reference
|
||
|
|
# 'perldoc perlartistic' or 'perldoc perlgpl'.
|
||
|
|
#
|
||
|
|
|
||
|
|
package DW::Controller::Admin::VirtualGift;
|
||
|
|
|
||
|
|
use strict;
|
||
|
|
|
||
|
|
use DW::Controller;
|
||
|
|
use DW::Controller::Admin;
|
||
|
|
use DW::Routing;
|
||
|
|
use DW::Template;
|
||
|
|
|
||
|
|
use DW::VirtualGift;
|
||
|
|
use DW::FormErrors;
|
||
|
|
|
||
|
|
use Image::Size;
|
||
|
|
|
||
|
|
my $vgift_privs = [
|
||
|
|
'vgifts',
|
||
|
|
'siteadmin:vgifts',
|
||
|
|
sub {
|
||
|
|
return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml("/admin/index.tt.devserver") );
|
||
|
|
}
|
||
|
|
];
|
||
|
|
|
||
|
|
DW::Controller::Admin->register_admin_page(
|
||
|
|
'/',
|
||
|
|
path => 'vgifts',
|
||
|
|
ml_scope => '/admin/vgifts/index.tt',
|
||
|
|
privs => $vgift_privs
|
||
|
|
);
|
||
|
|
|
||
|
|
DW::Routing->register_string( "/admin/vgifts/index", \&index_controller, app => 1 );
|
||
|
|
DW::Routing->register_string( "/admin/vgifts/inactive", \&inactive_controller, app => 1 );
|
||
|
|
DW::Routing->register_string( "/admin/vgifts/tags", \&tags_controller, app => 1 );
|
||
|
|
|
||
|
|
sub _loose_refer {
|
||
|
|
my $baseuri = $_[0];
|
||
|
|
my $refer = DW::Request->get->header_in('Referer');
|
||
|
|
return 1 unless $refer;
|
||
|
|
|
||
|
|
# annoyingly, we get different results for /index vs /
|
||
|
|
if ( $baseuri =~ m(/$) ) {
|
||
|
|
return 1 if LJ::check_referer("${baseuri}index");
|
||
|
|
}
|
||
|
|
return LJ::check_referer($baseuri);
|
||
|
|
}
|
||
|
|
|
||
|
|
sub _strict_refer {
|
||
|
|
|
||
|
|
# make sure we have a referer header. check_referer doesn't care.
|
||
|
|
my $ret = DW::Request->get->header_in('Referer') && _loose_refer( $_[0] );
|
||
|
|
return $ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
sub _check_id {
|
||
|
|
my $err_ml = $_[1] // \undef;
|
||
|
|
|
||
|
|
if ( my $id = $_[0] ) {
|
||
|
|
my $vgift = DW::VirtualGift->new($id);
|
||
|
|
return $vgift if $vgift && $vgift->name;
|
||
|
|
$$err_ml = "vgift.error.badid";
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$$err_ml = "error.invalidform";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
sub index_controller {
|
||
|
|
my ( $ok, $rv ) = controller( form_auth => 0, privcheck => $vgift_privs );
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $scope = '/admin/vgifts/index.tt';
|
||
|
|
my $vars = {};
|
||
|
|
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $siteadmin = $remote->has_priv( 'siteadmin', 'vgifts' ) || $LJ::IS_DEV_SERVER;
|
||
|
|
|
||
|
|
my $form_args = $r->did_post ? $r->post_args : $r->get_args;
|
||
|
|
|
||
|
|
# process multipart form
|
||
|
|
if ( $r->did_post && !%$form_args ) {
|
||
|
|
my $size = $r->header_in("Content-Length");
|
||
|
|
return error_ml("$scope.error.upload.noheader") unless $size;
|
||
|
|
|
||
|
|
my $uploads = eval { $r->uploads };
|
||
|
|
return error_ml( "$scope.error.upload.content", { err => $@ } ) if $@;
|
||
|
|
|
||
|
|
foreach my $h (@$uploads) {
|
||
|
|
$form_args->{ $h->{name} } = $h->{body};
|
||
|
|
}
|
||
|
|
|
||
|
|
# now uploaded data is in $form_args, we can continue
|
||
|
|
}
|
||
|
|
|
||
|
|
my $checkid = sub { return _check_id( $form_args->{id}, $_[0] ) };
|
||
|
|
|
||
|
|
my $mode = lc( $form_args->{mode} || $r->get_args->{mode} || '' );
|
||
|
|
|
||
|
|
# process post request, but only if we have a mode
|
||
|
|
if ( $r->did_post && $mode ) {
|
||
|
|
|
||
|
|
# check auth manually in case we had a multipart form
|
||
|
|
return error_ml("error.invalidform")
|
||
|
|
unless LJ::check_form_auth( $form_args->{lj_form_auth} );
|
||
|
|
|
||
|
|
$mode = '' unless _loose_refer("/admin/vgifts/");
|
||
|
|
|
||
|
|
my $errors = DW::FormErrors->new;
|
||
|
|
|
||
|
|
my $loadpic = sub {
|
||
|
|
my ($id) = @_;
|
||
|
|
|
||
|
|
my $imgposted = length( $form_args->{"data_$id"} ) || length( $form_args->{"url_$id"} );
|
||
|
|
return undef unless $imgposted;
|
||
|
|
|
||
|
|
my $data;
|
||
|
|
|
||
|
|
if ( $form_args->{$id} eq 'url' ) {
|
||
|
|
$data = $form_args->{"url_$id"};
|
||
|
|
|
||
|
|
if ( length($data) == 0 ) {
|
||
|
|
$errors->add( '', "$scope.error.upload.nourl" );
|
||
|
|
}
|
||
|
|
elsif ( $data !~ m!^https?://! ) {
|
||
|
|
$errors->add( '', "$scope.error.upload.badurl" );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
my $ua = LJ::get_useragent( role => 'vgift' );
|
||
|
|
my $res = $ua->get($data);
|
||
|
|
if ( $res && $res->is_success ) {
|
||
|
|
$data = $res->content;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$errors->add( '', "$scope.error.upload.urlerror" );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
elsif ( $form_args->{$id} eq 'file' ) {
|
||
|
|
$data = $form_args->{"data_$id"};
|
||
|
|
$errors->add( '', "$scope.error.upload.nofile" )
|
||
|
|
unless length($data);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$errors->add( '', 'error.invalidform' );
|
||
|
|
}
|
||
|
|
|
||
|
|
return undef if $errors->exist;
|
||
|
|
|
||
|
|
# further processing
|
||
|
|
my ( $width, $height, $filetype ) = Image::Size::imgsize( \$data );
|
||
|
|
unless ( $width && $height ) {
|
||
|
|
$errors->add( '', "$scope.error.upload.badtype", { filetype => $filetype } );
|
||
|
|
}
|
||
|
|
elsif ( ( $width > 100 || $height > 100 ) && $id eq 'img_small' ) {
|
||
|
|
$errors->add(
|
||
|
|
'',
|
||
|
|
"$scope.error.upload.dimstoolarge",
|
||
|
|
{ imagesize => "${width}x$height", maxsize => "100x100" }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
elsif ( ( $width > 300 || $height > 300 ) && $id eq 'img_large' ) {
|
||
|
|
$errors->add(
|
||
|
|
'',
|
||
|
|
"$scope.error.upload.dimstoolarge",
|
||
|
|
{ imagesize => "${width}x$height", maxsize => "300x300" }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
elsif ( length($data) > 250 * 1024 ) { # 250KB (arbitrary)
|
||
|
|
$errors->add( '', "$scope.error.upload.filetoolarge", { maxsize => "250" } );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# data should be good, return a reference to it
|
||
|
|
return \$data;
|
||
|
|
}
|
||
|
|
|
||
|
|
# check $errors to see what went wrong
|
||
|
|
return undef;
|
||
|
|
};
|
||
|
|
|
||
|
|
my ( $redirect_args, $err_ml, $errmsg );
|
||
|
|
|
||
|
|
if ( $mode eq 'create' ) {
|
||
|
|
return error_ml( "$scope.error.denied", { action => $mode } )
|
||
|
|
unless $remote->has_priv('vgifts') || $siteadmin;
|
||
|
|
|
||
|
|
$errors->add( 'name', "$scope.error.create.noname" ) unless $form_args->{name};
|
||
|
|
$errors->add( 'desc', "$scope.error.create.nodesc" ) unless $form_args->{desc};
|
||
|
|
|
||
|
|
my $creatorid;
|
||
|
|
|
||
|
|
if ( $form_args->{creator} && $siteadmin ) {
|
||
|
|
my $u = LJ::load_user_or_identity( $form_args->{creator} );
|
||
|
|
if ( $u && $u->is_individual ) {
|
||
|
|
$creatorid = $u->id;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$errors->add(
|
||
|
|
'creator',
|
||
|
|
"$scope.error.create.badusername",
|
||
|
|
{ name => $form_args->{creator} }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
my ( $img_small, $img_large );
|
||
|
|
|
||
|
|
$img_small = $loadpic->('img_small') unless $errors->exist;
|
||
|
|
$img_large = $loadpic->('img_large') unless $errors->exist;
|
||
|
|
|
||
|
|
unless ( $errors->exist ) {
|
||
|
|
my $vgift = DW::VirtualGift->create(
|
||
|
|
error => \$errmsg,
|
||
|
|
name => $form_args->{name},
|
||
|
|
description => $form_args->{desc},
|
||
|
|
img_small => $img_small,
|
||
|
|
img_large => $img_large,
|
||
|
|
creatorid => $creatorid
|
||
|
|
);
|
||
|
|
return error_ml( "$scope.error.create.failure", { err => $errmsg } )
|
||
|
|
unless $vgift;
|
||
|
|
|
||
|
|
# hallelujah, the vgift was created.
|
||
|
|
$redirect_args = { mode => 'view', title => 'created', id => $vgift->id };
|
||
|
|
}
|
||
|
|
|
||
|
|
# return template below if there were correctable errors
|
||
|
|
$vars->{mode} = '';
|
||
|
|
}
|
||
|
|
|
||
|
|
elsif ( $mode eq 'edit' ) {
|
||
|
|
return error_ml($err_ml) unless my $vgift = $checkid->( \$err_ml );
|
||
|
|
|
||
|
|
return error_ml( "$scope.error.denied", { action => $mode } )
|
||
|
|
unless $vgift->can_be_edited_by($remote);
|
||
|
|
|
||
|
|
my ( $img_small, $img_large );
|
||
|
|
|
||
|
|
$img_small = $loadpic->('img_small') unless $errors->exist;
|
||
|
|
$img_large = $loadpic->('img_large') unless $errors->exist;
|
||
|
|
|
||
|
|
# Don't honor null attributes.
|
||
|
|
delete $form_args->{name} unless length $form_args->{name};
|
||
|
|
delete $form_args->{desc} unless length $form_args->{desc};
|
||
|
|
|
||
|
|
# Note: this resets any existing approval status.
|
||
|
|
unless ( $errors->exist ) {
|
||
|
|
my $ok = $vgift->edit(
|
||
|
|
error => \$errmsg,
|
||
|
|
approved => '',
|
||
|
|
name => $form_args->{name},
|
||
|
|
description => $form_args->{desc},
|
||
|
|
img_small => $img_small,
|
||
|
|
img_large => $img_large
|
||
|
|
);
|
||
|
|
return error_ml( "$scope.error.edit.failure", { err => $errmsg } )
|
||
|
|
unless $ok;
|
||
|
|
|
||
|
|
$redirect_args = { mode => 'view', title => 'edited', id => $vgift->id };
|
||
|
|
}
|
||
|
|
|
||
|
|
# return template below if there were correctable errors
|
||
|
|
$vars->{mode} = 'view';
|
||
|
|
}
|
||
|
|
|
||
|
|
elsif ( $mode eq 'approve' ) {
|
||
|
|
return error_ml($err_ml) unless my $vgift = $checkid->( \$err_ml );
|
||
|
|
|
||
|
|
return error_ml( "$scope.error.denied", { action => $mode } )
|
||
|
|
unless $vgift->can_be_approved_by($remote);
|
||
|
|
|
||
|
|
my $id = $vgift->id;
|
||
|
|
|
||
|
|
return error_ml("$scope.error.changed")
|
||
|
|
if $form_args->{"${id}_chksum"} ne $vgift->checksum;
|
||
|
|
|
||
|
|
if ( exists $form_args->{"${id}_approve"} ) {
|
||
|
|
if ( $form_args->{"${id}_approve"} ) {
|
||
|
|
my $ok = $vgift->edit(
|
||
|
|
error => \$errmsg,
|
||
|
|
approved => $form_args->{"${id}_approve"},
|
||
|
|
approved_why => $form_args->{"${id}_comment"},
|
||
|
|
approved_by => $remote->userid
|
||
|
|
);
|
||
|
|
return error_ml( "$scope.error.edit.failure", { err => $errmsg } )
|
||
|
|
unless $ok;
|
||
|
|
|
||
|
|
$vgift->notify_approved;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# this error isn't fatal
|
||
|
|
$errors->add( "${id}_approve", "$scope.error.yn" );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $form_args->{"${id}_featured"} || $form_args->{"${id}_cost"} ) {
|
||
|
|
my %opts;
|
||
|
|
foreach my $k (qw( featured cost )) {
|
||
|
|
$opts{$k} = $form_args->{"${id}_$k"} if $form_args->{"${id}_$k"};
|
||
|
|
}
|
||
|
|
my $ok = $vgift->edit( error => \$errmsg, %opts );
|
||
|
|
return error_ml( "$scope.error.edit.failure", { err => $errmsg } )
|
||
|
|
unless $ok;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $form_args->{"${id}_tags"} ) {
|
||
|
|
my $ok = $vgift->tags(
|
||
|
|
$form_args->{"${id}_tags"},
|
||
|
|
error => \$errmsg,
|
||
|
|
autovivify => $siteadmin
|
||
|
|
);
|
||
|
|
return error_ml( "$scope.error.edit.failure", { err => $errmsg } )
|
||
|
|
unless $ok;
|
||
|
|
}
|
||
|
|
|
||
|
|
unless ( $errors->exist ) {
|
||
|
|
return $r->redirect("/admin/vgifts/inactive")
|
||
|
|
if $form_args->{activation};
|
||
|
|
|
||
|
|
# return to review page for item
|
||
|
|
$redirect_args = { mode => 'review', title => 'approved', id => $id };
|
||
|
|
my $days = $form_args->{days} ? $form_args->{days} + 0 : 0;
|
||
|
|
$redirect_args->{days} = $days if $days;
|
||
|
|
}
|
||
|
|
|
||
|
|
# return template below if there were correctable errors
|
||
|
|
$vars->{mode} = 'review';
|
||
|
|
}
|
||
|
|
|
||
|
|
elsif ( $mode eq 'confirm' ) {
|
||
|
|
return error_ml($err_ml) unless my $vgift = $checkid->( \$err_ml );
|
||
|
|
|
||
|
|
my $ok = $vgift->delete($remote);
|
||
|
|
return error_ml("$scope.error.delete") unless $ok;
|
||
|
|
|
||
|
|
my $re_mode = $remote->userid == $vgift->creatorid ? 'view' : 'review';
|
||
|
|
|
||
|
|
$redirect_args = { mode => $re_mode, title => 'deleted' };
|
||
|
|
}
|
||
|
|
|
||
|
|
else {
|
||
|
|
# if we get here, check_referer failed or something weird happened
|
||
|
|
return $r->redirect("$LJ::SITEROOT/admin/vgifts/");
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( defined $redirect_args ) {
|
||
|
|
return $r->redirect( LJ::create_url( undef, args => $redirect_args ) );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$vars->{errors} = $errors;
|
||
|
|
$vars->{formdata} = $form_args;
|
||
|
|
|
||
|
|
# fall through to template
|
||
|
|
}
|
||
|
|
} # end did_post
|
||
|
|
|
||
|
|
# transform get arguments into template variables (id -> vgift; user -> vu)
|
||
|
|
|
||
|
|
if ( $form_args->{title} && _strict_refer("/admin/vgifts/") ) {
|
||
|
|
$vars->{title} = $form_args->{title};
|
||
|
|
}
|
||
|
|
|
||
|
|
$vars->{mode} //= $form_args->{mode};
|
||
|
|
|
||
|
|
if ( $form_args->{id} ) {
|
||
|
|
return error_ml("$scope.error.badid") unless $vars->{vgift} = $checkid->();
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $form_args->{user} ) {
|
||
|
|
$vars->{vu} = LJ::load_user( $form_args->{user} );
|
||
|
|
return error_ml( "$scope.error.baduser", { user => $form_args->{user} } )
|
||
|
|
unless LJ::isu( $vars->{vu} );
|
||
|
|
}
|
||
|
|
|
||
|
|
$vars->{remote} = $remote;
|
||
|
|
$vars->{siteadmin} = $siteadmin;
|
||
|
|
|
||
|
|
$vars->{inactive} = $form_args->{title} ? $form_args->{title} eq 'inactive' : 0;
|
||
|
|
$vars->{days} = $form_args->{days} ? $form_args->{days} + 0 : 0;
|
||
|
|
|
||
|
|
$vars->{review_list} = sub {
|
||
|
|
my $days = $vars->{days};
|
||
|
|
return [ DW::VirtualGift->list_recent($days) ] if $days;
|
||
|
|
return [ DW::VirtualGift->list_queued() ];
|
||
|
|
};
|
||
|
|
|
||
|
|
$vars->{display_creatorlist} = sub { DW::VirtualGift->display_creatorlist( $_[0] ) };
|
||
|
|
|
||
|
|
$vars->{list_created_by} = sub { [ DW::VirtualGift->list_created_by( $_[0] ) ] };
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'admin/vgifts/index.tt', $vars );
|
||
|
|
}
|
||
|
|
|
||
|
|
sub inactive_controller {
|
||
|
|
my $privs = [ $vgift_privs->[1], $vgift_privs->[2] ];
|
||
|
|
|
||
|
|
my ( $ok, $rv ) = controller( privcheck => $privs );
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $scope = '/admin/vgifts/inactive.tt';
|
||
|
|
my $vars = {};
|
||
|
|
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $form_args = $r->did_post ? $r->post_args : $r->get_args;
|
||
|
|
|
||
|
|
my $mode = lc( $form_args->{mode} || $r->get_args->{mode} || '' );
|
||
|
|
|
||
|
|
# process post request, but only if we have a mode
|
||
|
|
if ( $r->did_post && $mode ) {
|
||
|
|
|
||
|
|
$mode = '' unless _loose_refer("/admin/vgifts/inactive");
|
||
|
|
|
||
|
|
if ( $mode eq 'activate' ) {
|
||
|
|
my @vgs;
|
||
|
|
foreach ( keys %$form_args ) {
|
||
|
|
my ($id) = ( $_ =~ /^(\d+)_activate$/ );
|
||
|
|
next unless $id;
|
||
|
|
|
||
|
|
my $err_ml;
|
||
|
|
my $vg = _check_id( $id, $err_ml );
|
||
|
|
return error_ml($err_ml) unless $vg;
|
||
|
|
|
||
|
|
next if $vg->is_active; # already active
|
||
|
|
|
||
|
|
return error_ml( "$scope.error.notags", { name => $vg->name_ehtml } )
|
||
|
|
if $vg->is_untagged;
|
||
|
|
|
||
|
|
return error_ml( "$scope.error.changed", { name => $vg->name_ehtml } )
|
||
|
|
if $form_args->{"${id}_chksum"} ne $vg->checksum;
|
||
|
|
|
||
|
|
push @vgs, $vg;
|
||
|
|
}
|
||
|
|
|
||
|
|
# now that we're clear of possible errors, do the activation
|
||
|
|
$_->mark_active foreach @vgs;
|
||
|
|
my $ids = join ', ', map { $_->id } @vgs;
|
||
|
|
LJ::statushistory_add( 0, $remote, 'vgifts', "Activated: $ids" )
|
||
|
|
if $ids;
|
||
|
|
|
||
|
|
# go back to where we were
|
||
|
|
return $r->redirect( $r->header_in('Referer') );
|
||
|
|
}
|
||
|
|
|
||
|
|
else {
|
||
|
|
# if we get here, check_referer failed or something weird happened
|
||
|
|
return $r->redirect("$LJ::SITEROOT/admin/vgifts/inactive");
|
||
|
|
}
|
||
|
|
} # end did_post
|
||
|
|
|
||
|
|
my @vgs;
|
||
|
|
|
||
|
|
if ( $mode eq 'tags' ) {
|
||
|
|
my $tag = $form_args->{tag} || '';
|
||
|
|
|
||
|
|
if ($tag) {
|
||
|
|
return error_ml("$scope.error.badid")
|
||
|
|
unless DW::VirtualGift->get_tagid($tag);
|
||
|
|
|
||
|
|
$vars->{tag} = $tag;
|
||
|
|
$vars->{count} = scalar grep { $_->is_approved } DW::VirtualGift->list_untagged;
|
||
|
|
|
||
|
|
@vgs = DW::VirtualGift->list_tagged_with($tag);
|
||
|
|
|
||
|
|
# list_tagged_with includes active gifts
|
||
|
|
@vgs = grep { $_->is_inactive } @vgs;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
@vgs = DW::VirtualGift->list_untagged;
|
||
|
|
}
|
||
|
|
|
||
|
|
my $app = DW::VirtualGift->fetch_tagcounts_approved;
|
||
|
|
my $act = DW::VirtualGift->fetch_tagcounts_active;
|
||
|
|
|
||
|
|
$vars->{approved_inactive} = {};
|
||
|
|
$vars->{approved_inactive}->{$_} = $app->{$_} - ( $act->{$_} // 0 ) foreach keys %$app;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# DEFAULT PAGE DISPLAY
|
||
|
|
@vgs = DW::VirtualGift->list_inactive;
|
||
|
|
}
|
||
|
|
|
||
|
|
# don't include queued or rejected gifts
|
||
|
|
@vgs = grep { $_->is_approved } @vgs;
|
||
|
|
|
||
|
|
$vars->{feat} = [ grep { $_->is_featured } @vgs ];
|
||
|
|
$vars->{nonfeat} = [ grep { !$_->is_featured } @vgs ];
|
||
|
|
$vars->{nonpriv} = { map { $_ => 1 } DW::VirtualGift->list_nonpriv_tags };
|
||
|
|
|
||
|
|
$vars->{mode} = $mode;
|
||
|
|
$vars->{modes} = [ '', 'tags' ]; # ordered
|
||
|
|
$vars->{tabs} = {
|
||
|
|
'' => '.tab.default',
|
||
|
|
'tags' => '.tab.tags',
|
||
|
|
};
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'admin/vgifts/inactive.tt', $vars );
|
||
|
|
}
|
||
|
|
|
||
|
|
sub tags_controller {
|
||
|
|
my $privs = [ $vgift_privs->[1], $vgift_privs->[2] ];
|
||
|
|
|
||
|
|
my ( $ok, $rv ) = controller( privcheck => $privs );
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $scope = '/admin/vgifts/tags.tt';
|
||
|
|
my $vars = {};
|
||
|
|
|
||
|
|
my $form_args = $r->did_post ? $r->post_args : $r->get_args;
|
||
|
|
my $redirect_args;
|
||
|
|
|
||
|
|
my $mode = lc( $form_args->{mode} || $r->get_args->{mode} || '' );
|
||
|
|
|
||
|
|
# process post request, but only if we have a mode
|
||
|
|
if ( $r->did_post && $mode ) {
|
||
|
|
|
||
|
|
$mode = '' unless _loose_refer("/admin/vgifts/tags");
|
||
|
|
|
||
|
|
my $errors = DW::FormErrors->new;
|
||
|
|
|
||
|
|
if ( $mode eq 'edit' ) {
|
||
|
|
my $tagid = $form_args->{id};
|
||
|
|
return error_ml("$scope.error.badid") unless $tagid;
|
||
|
|
|
||
|
|
my $tag = DW::VirtualGift->get_tagname($tagid);
|
||
|
|
return error_ml("$scope.error.badid") unless $tag;
|
||
|
|
|
||
|
|
my $priv = $form_args->{"${tagid}_addpriv"};
|
||
|
|
my $arg = $form_args->{"${tagid}_privarg"};
|
||
|
|
|
||
|
|
$errors->add( "${tagid}_addpriv", "$scope.error.needpriv" ) if $arg && !$priv;
|
||
|
|
|
||
|
|
if ($priv) {
|
||
|
|
my $e_priv = LJ::ehtml($priv);
|
||
|
|
my $e_arg = LJ::ehtml($arg);
|
||
|
|
|
||
|
|
# make sure the new priv is valid
|
||
|
|
$errors->add( "${tagid}_addpriv", "$scope.error.badpriv", { priv => $e_priv } )
|
||
|
|
unless DW::VirtualGift->validate_priv($priv);
|
||
|
|
|
||
|
|
# also validate arg if given
|
||
|
|
if ( $arg && $arg ne '*' ) {
|
||
|
|
my $valid_args = LJ::list_valid_args($priv);
|
||
|
|
$errors->add( "${tagid}_privarg", "$scope.error.badarg",
|
||
|
|
{ priv => $e_priv, arg => $e_arg } )
|
||
|
|
unless $valid_args && $valid_args->{$arg};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# process rename first
|
||
|
|
if ( my $newtag = $form_args->{"${tagid}_rename"} ) {
|
||
|
|
|
||
|
|
if ( DW::VirtualGift->alter_tag( $tag, $newtag ) ) {
|
||
|
|
$tag = $newtag; # subsequent changes target $newtag
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$errors->add( "${tagid}_rename", "$scope.error.badtagname",
|
||
|
|
{ tag => LJ::ehtml($newtag) } );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unless ( $errors->exist ) {
|
||
|
|
|
||
|
|
# process new privilege
|
||
|
|
if ($priv) {
|
||
|
|
my $e_privarg = LJ::ehtml($priv) . ':' . LJ::ehtml($arg);
|
||
|
|
DW::VirtualGift->add_priv_to_tag( $tag, $priv, $arg )
|
||
|
|
or return error_ml( "$scope.error.privarg", { privarg => $e_privarg } );
|
||
|
|
}
|
||
|
|
|
||
|
|
# process old privileges
|
||
|
|
if ( my $maxprivnum = $form_args->{"${tagid}_maxprivnum"} ) {
|
||
|
|
|
||
|
|
# only remove existing privs if not renamed (can resubmit)
|
||
|
|
unless ( $form_args->{"${tagid}_rename"} ) {
|
||
|
|
DW::VirtualGift->remove_priv_from_tag( $tag, $_->[0], $_->[1] )
|
||
|
|
foreach DW::VirtualGift->list_tagprivs($tag);
|
||
|
|
}
|
||
|
|
|
||
|
|
# add back selected privs
|
||
|
|
foreach my $i ( 0 .. $maxprivnum ) {
|
||
|
|
my $priv_i = $form_args->{"${tagid}_priv$i"};
|
||
|
|
next unless $priv_i;
|
||
|
|
my ( $p, $a ) = ( $priv_i =~ /^([^:]+):(.*)$/ );
|
||
|
|
next unless $p;
|
||
|
|
DW::VirtualGift->add_priv_to_tag( $tag, $p, $a )
|
||
|
|
or return error_ml( "$scope.error.privarg",
|
||
|
|
{ privarg => LJ::ehtml("$p:$a") } );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$redirect_args =
|
||
|
|
{ mode => 'view', title => 'edited', id => DW::VirtualGift->get_tagid($tag) };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
elsif ( $mode eq 'confirm' ) {
|
||
|
|
my $tag = DW::VirtualGift->get_tagname( $form_args->{id} );
|
||
|
|
return error_ml("$scope.error.badid") unless $tag;
|
||
|
|
DW::VirtualGift->alter_tag($tag); # deletes the tag
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $errors->exist ) {
|
||
|
|
$vars->{errors} = $errors;
|
||
|
|
$vars->{formdata} = $form_args;
|
||
|
|
|
||
|
|
# fall through to template
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return $r->redirect( LJ::create_url( undef, args => $redirect_args ) );
|
||
|
|
}
|
||
|
|
} # end did_post
|
||
|
|
|
||
|
|
# non post processing stuff (check for gets)
|
||
|
|
my $tag = LJ::durl( $form_args->{tag} || '' );
|
||
|
|
my $id;
|
||
|
|
|
||
|
|
if ($mode) {
|
||
|
|
return $r->redirect( LJ::create_url() ) unless $tag;
|
||
|
|
$id = DW::VirtualGift->get_tagid($tag);
|
||
|
|
return error_ml("$scope.error.badid") unless $id;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $mode eq 'remove' ) {
|
||
|
|
my $err_ml;
|
||
|
|
my $vg = _check_id( $form_args->{vg}, $err_ml );
|
||
|
|
return error_ml($err_ml) unless $vg;
|
||
|
|
|
||
|
|
# quickly process and return
|
||
|
|
$vg->remove_tag_by_id($id);
|
||
|
|
$redirect_args = { mode => 'view', tag => LJ::eurl($tag) };
|
||
|
|
return $r->redirect( LJ::create_url( undef, args => $redirect_args ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $form_args->{title} && _strict_refer("/admin/vgifts/tags") ) {
|
||
|
|
$vars->{title} = $form_args->{title};
|
||
|
|
}
|
||
|
|
|
||
|
|
$vars->{mode} = $mode;
|
||
|
|
$vars->{tag} = $tag;
|
||
|
|
$vars->{id} = $id;
|
||
|
|
|
||
|
|
$vars->{list_tagprivs} = sub { [ DW::VirtualGift->list_tagprivs( $_[0] ) ] };
|
||
|
|
$vars->{tagged_with} = sub { [ DW::VirtualGift->list_tagged_with( $_[0] ) ] };
|
||
|
|
|
||
|
|
unless ($mode) {
|
||
|
|
my $counts = DW::VirtualGift->fetch_tagcounts_approved;
|
||
|
|
my %nonpriv = map { $_ => $counts->{$_} } DW::VirtualGift->list_nonpriv_tags;
|
||
|
|
delete @$counts{ keys %nonpriv }; # leaving only privileged data
|
||
|
|
|
||
|
|
$vars->{haspriv} = $counts;
|
||
|
|
$vars->{nonpriv} = \%nonpriv;
|
||
|
|
}
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'admin/vgifts/tags.tt', $vars );
|
||
|
|
}
|
||
|
|
|
||
|
|
1;
|