X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Fshare%2Fhtml%2FREST%2F1.0%2Fsearch%2Fdhandler;h=99b2069782524a8def59b6056d19714e54c94019;hp=86d33b37fc20dbf24021d645acdd0ab41ff1e112;hb=de9d037528895f7151a9aead6724ce2df95f9586;hpb=b4b0c7e72d7eaee2fbfc7022022c9698323203dd diff --git a/rt/share/html/REST/1.0/search/dhandler b/rt/share/html/REST/1.0/search/dhandler index 86d33b37f..99b206978 100755 --- a/rt/share/html/REST/1.0/search/dhandler +++ b/rt/share/html/REST/1.0/search/dhandler @@ -1,40 +1,40 @@ %# BEGIN BPS TAGGED BLOCK {{{ -%# +%# %# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC -%# -%# +%# +%# This software is Copyright (c) 1996-2017 Best Practical Solutions, LLC +%# +%# %# (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 @@ -43,14 +43,251 @@ %# 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/dhandler %# +<%ARGS> +$query +$format => undef +$orderby => undef +$fields => undef + <%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 ); -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'} } + } +); + + +