X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Fshare%2Fhtml%2FREST%2F1.0%2Fsearch%2Fdhandler;h=62b76f5999abca016c40b0a17639007bc256ef1a;hp=70b799946b6c0afe4158e7d1e73aa1184ec83095;hb=187086c479a09629b7d180eec513fb7657f4e291;hpb=fc6209f398899f0211cfcedeb81a3cd65e04a941 diff --git a/rt/share/html/REST/1.0/search/dhandler b/rt/share/html/REST/1.0/search/dhandler index 70b799946..62b76f599 100755 --- a/rt/share/html/REST/1.0/search/dhandler +++ b/rt/share/html/REST/1.0/search/dhandler @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC %# %# %# (Except where explicitly superseded by other copyright notices) @@ -47,10 +47,247 @@ %# 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'} } + } +); + + +