diff options
Diffstat (limited to 'rt/share/html/REST/1.0/search')
-rwxr-xr-x | rt/share/html/REST/1.0/search/dhandler | 245 | ||||
-rwxr-xr-x | rt/share/html/REST/1.0/search/ticket | 165 |
2 files changed, 241 insertions, 169 deletions
diff --git a/rt/share/html/REST/1.0/search/dhandler b/rt/share/html/REST/1.0/search/dhandler index b81c56c6d..d8a07291e 100755 --- a/rt/share/html/REST/1.0/search/dhandler +++ b/rt/share/html/REST/1.0/search/dhandler @@ -47,10 +47,247 @@ %# END BPS TAGGED BLOCK }}} %# REST/1.0/search/dhandler %# +<%ARGS> +$query +$format => undef +$orderby => undef +$fields => undef +</%ARGS> <%INIT> -my $status = "500 Server Error"; -my $output = "Unsupported object type."; +my $type = $m->dhandler_arg; +my ( $status, $output ); + +if ( $type =~ /^(ticket|queue|user|group)$/i ) { + $status = "200 Ok"; + $output = ''; + my $type = lc $1; + + if ( + $type eq 'user' + && !$session{CurrentUser}->HasRight( + Object => $RT::System, + Right => 'AdminUsers', + ) + ) + { + + $status = "403 Forbidden"; + $output = "Permission denied"; + goto OUTPUT; + } + + my $class = 'RT::' . ucfirst $type . 's'; + my $objects = $class->new( $session{CurrentUser} ); + + # Parse and validate any field specifications. + require RT::Interface::REST; + my $field = RT::Interface::REST->field_spec; + my ( %fields, @fields ); + if ($fields) { + $format ||= "l"; + unless ( $fields =~ /^(?:$field,)*$field$/ ) { + $status = "400 Bad Request"; + $output = "Invalid field specification: $fields"; + goto OUTPUT; + } + @fields = map lc, split /\s*,\s*/, $fields; + @fields{@fields} = (); + unless ( exists $fields{id} ) { + unshift @fields, "id"; + $fields{id} = (); + } + } + + $format ||= "s"; + if ( $format !~ /^[isl]$/ ) { + $status = "400 Bad request"; + $output = "Unknown listing format: $format. (Use i, s, or l.)\n"; + goto OUTPUT; + } + + my ( $n, $s ); + $n = 0; + my @output; + + + if ( $type eq 'group' ) { + $objects->LimitToUserDefinedGroups; + } + + if ( defined $query && length $query ) { + if ( $type eq 'ticket' ) { + my ( $n, $s ); + eval { ( $n, $s ) = $objects->FromSQL($query); }; + if ( $@ || $n == 0 ) { + $s ||= $@; + $status = "400 Bad request"; + $output = "Invalid query: '$s'.\n"; + goto OUTPUT; + } + } + else { + require Text::ParseWords; + my ( $field, $op, $value ) = Text::ParseWords::shellwords($query); + if ( $op !~ + /^(?:[!<>]?=|[<>]|(NOT )?LIKE|STARTSWITH|ENDSWITH|MATCHES)$/i ) + { + $status = "400 Bad Request"; + $output = "Invalid operator specification: $op"; + goto OUTPUT; + } + + if ( ! $search_whitelist{$type}{lc $field} ) { + $status = "400 Bad Request"; + $output = "Invalid field specification: $field"; + goto OUTPUT; + } + + + if ( $field && $op && defined $value ) { + if ( $field eq 'Disabled' ) { + if ($value) { + if ( $type eq 'queue' ) { + $objects->FindAllRows; + $objects->Limit( + FIELD => $field, + OPERATOR => uc $op, + VALUE => $value + ); + } + else { + $objects->LimitToDeleted; + } + } + else { + if ( $type eq 'queue' ) { + $objects->UnLimit; + } + else { + $objects->LimitToEnabled; + } + } + } + else { + $objects->Limit( + FIELD => $field, + OPERATOR => uc $op, + VALUE => $value, + CASESENSITIVE => 0, + ); + } + } + else { + $output = "Invalid query specification: $query"; + goto OUTPUT; + } + } + } + else { + if ( $type eq 'queue' ) { + $objects->UnLimit; + } + elsif ( $type eq 'user' ) { + $objects->LimitToPrivileged; + } + } + + if ($orderby) { + my ( $order, $field ) = $orderby =~ /^([\+\-])?(.+)/; + $order = $order && $order eq '-' ? 'DESC' : 'ASC'; + $objects->OrderBy( FIELD => $field, ORDER => $order ); + } + + while ( my $object = $objects->Next ) { + next if $type eq 'user' && ( $object->id == RT->SystemUser->id || $object->id == RT->Nobody->id ); + $n++; + + my $id = $object->Id; + if ( $format eq "i" ) { + $output .= "$type/" . $id . "\n"; + } + elsif ( $format eq "s" ) { + if ($fields) { + my $result = $m->comp( + "/REST/1.0/Forms/$type/default", + id => $id, + format => $format, + fields => \%fields + ); + my ( $notes, $order, $key_values, $errors ) = @$result; + + # If it's the first time through, add our header + if ( $n == 1 ) { + $output .= join( "\t", @$order ) . "\n"; + } + + # Cut off the annoying $type/ before the id; + $key_values->{'id'} = $id; + $output .= join( + "\t", + map { + ref $key_values->{$_} eq 'ARRAY' + ? join( ', ', @{ $key_values->{$_} } ) + : $key_values->{$_} + } @$order + ) . "\n"; + } + else { + if ( $type eq 'ticket' ) { + $output .= $object->Id . ": " . $object->Subject . "\n"; + } + else { + $output .= $object->Id . ": " . $object->Name . "\n"; + } + } + } + else { + my $d = $m->comp( + "/REST/1.0/Forms/$type/default", + id => $id, + format => $format, + fields => \%fields + ); + my ( $c, $o, $k, $e ) = @$d; + push @output, [ $c, $o, $k ]; + } + } + if ( $n == 0 && $format ne "i" ) { + $output = "No matching results.\n"; + } + + $output = form_compose( \@output ) if @output; +} +else { + $status = "500 Server Error"; + $output = "Unsupported object type."; + goto OUTPUT; +} + +OUTPUT: +$m->out("RT/". $RT::VERSION . " " . $status ."\n\n"); +$m->out($output ); </%INIT> -RT/<% $RT::VERSION %> <% $status %> -<% $output |n %> +<%ONCE> +my %search_whitelist = ( + queue => { + map { lc $_ => 1 } + grep { $RT::Record::_TABLE_ATTR->{'RT::Queue'}{$_}{read} } + keys %{ $RT::Record::_TABLE_ATTR->{'RT::Queue'} } + }, + user => { + disabled => 1, + map { lc $_ => 1 } + grep { $RT::Record::_TABLE_ATTR->{'RT::User'}{$_}{read} } + keys %{ $RT::Record::_TABLE_ATTR->{'RT::User'} } + }, + group => { + disabled => 1, + map { lc $_ => 1 } + grep { $RT::Record::_TABLE_ATTR->{'RT::Group'}{$_}{read} } + keys %{ $RT::Record::_TABLE_ATTR->{'RT::Group'} } + } +); + +</%ONCE> + diff --git a/rt/share/html/REST/1.0/search/ticket b/rt/share/html/REST/1.0/search/ticket deleted file mode 100755 index f022b0330..000000000 --- a/rt/share/html/REST/1.0/search/ticket +++ /dev/null @@ -1,165 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC -%# <sales@bestpractical.com> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -%# REST/1.0/search/ticket -%# -<%ARGS> -$query -$format => undef -$orderby => undef -$fields => undef -</%ARGS> -<%INIT> -use RT::Interface::REST; -my $output = ""; -my $status = "200 Ok"; -my $tickets = RT::Tickets->new($session{CurrentUser}); - -# Parse and validate any field specifications. -my $field = RT::Interface::REST->field_spec; -my (%fields, @fields); -if ($fields) { - $format ||= "l"; - unless ($fields =~ /^(?:$field,)*$field$/) { - $status = "400 Bad Request"; - $output = "Invalid field specification: $fields"; - goto OUTPUT; - } - @fields = map lc, split /\s*,\s*/, $fields; - @fields{@fields} = (); - unless (exists $fields{id}) { - unshift @fields, "id"; - $fields{id} = (); - } -} - -$format ||= "s"; -if ($format !~ /^[isl]$/) { - $status = "400 Bad request"; - $output = "Unknown listing format: $format. (Use i, s, or l.)\n"; - goto OUTPUT; -} - -my ($n, $s); -eval { - ($n, $s) = $tickets->FromSQL($query); -}; - -if ($orderby) { - my %args; - - my $order = substr($orderby, 0, 1); - if ($order eq '+' || $order eq '-') { - # remove the +/- sorting sigil - substr($orderby, 0, 1, ''); - - if ($order eq '+') { - $args{ORDER} = 'ASC'; - } - elsif ($order eq '-') { - $args{ORDER} = 'DESC'; - } - } - - $tickets->OrderBy( - FIELD => $orderby, - %args, - ); -} - -if ($@ || $n == 0) { - $s ||= $@; - $status = "400 Bad request"; - $output = "Invalid query: '$s'.\n"; - goto OUTPUT; -} - -$n = 0; -my @output; -while (my $ticket = $tickets->Next) { - $n++; - - my $id = $ticket->Id; - if ($format eq "i") { - $output .= "ticket/" . $id . "\n"; - } - elsif ($format eq "s") { - if ($fields) { - my $result = $m->comp("/REST/1.0/Forms/ticket/default", id => $id, format => $format, fields => \%fields); - my ($notes, $order, $key_values, $errors) = @$result; - # If it's the first time through, add our header - if ($n == 1) { - $output .= join("\t",@$order)."\n"; - } - # Cut off the annoying ticket/ before the id; - $key_values->{'id'} = $id; - $output .= join("\t", map { ref $key_values->{$_} eq 'ARRAY' ? -join( ', ', @{$key_values->{$_}} ) : $key_values->{$_} } @$order)."\n"; - - - } else { - $output .= $ticket->Id . ": ". $ticket->Subject . "\n"; - } - } - else { - my $d = $m->comp("/REST/1.0/Forms/ticket/default", id => $id, format => $format, fields => \%fields); - my ($c, $o, $k, $e) = @$d; - push @output, [ $c, $o, $k ]; - } -} -if ($n == 0 && $format ne "i") { - $output = "No matching results.\n"; -} - -$output = form_compose(\@output) if @output; - -OUTPUT: -$m->out("RT/". $RT::VERSION . " " . $status ."\n\n"); - -$m->out($output ); -return(); -</%INIT> |