[Rt-commit] rt branch, 4.0/rest-search-refactor, created. rt-4.0.6-179-g8ade2ed
? sunnavy
sunnavy at bestpractical.com
Wed Jun 13 10:15:19 EDT 2012
The branch, 4.0/rest-search-refactor has been created
at 8ade2ed3bfdabc395d01a0ea18e0012093cfa84d (commit)
- Log -----------------------------------------------------------------
commit af8eda3bb306a4e52b2a87bce8c2259a68bfaa2f
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jun 23 12:56:28 2011 +0800
prepare to support restful searches for queues, users and groups
diff --git a/bin/rt.in b/bin/rt.in
index 2a9f643..8681106 100755
--- a/bin/rt.in
+++ b/bin/rt.in
@@ -327,32 +327,53 @@ sub list {
$data{orderby} =~ s/^\+?(.*)/-$1/;
}
- if (!defined $q) {
- $q = $config{query};
+ $type ||= "ticket";
+
+ if (!defined $q ) {
+ if ( $type eq 'ticket' ) {
+ $q = $config{query};
+ }
+ else {
+ $q = '';
+ }
}
-
- $q =~ s/^#//; # get rid of leading hash
- if ($q =~ /^\d+$/) {
- # only digits, must be an id, formulate a correct query
- $q = "id=$q" if $q =~ /^\d+$/;
- } else {
- # a string only, take it as an owner or requestor (quoting done later)
- $q = "(Owner=$q or Requestor like $q) and $config{query}"
- if $q =~ /^[\w\-]+$/;
- # always add a query for a specific queue or (comma separated) queues
- $queue =~ s/,/ or Queue=/g if $queue;
- $q .= " and (Queue=$queue)" if $queue and $q and $q !~ /Queue\s*=/i
- and $q !~ /id\s*=/i;
+
+ if ( $type ne 'ticket' ) {
+ $rawprint = 1;
}
- # correctly quote strings in a query
- $q =~ s/(=|like\s)\s*([^'\d\s]\S*)\b/$1\'$2\'/g;
- $type ||= "ticket";
- unless ($type && defined $q) {
+ unless (defined $q) {
my $item = $type ? "query string" : "object type";
whine "No $item specified.";
$bad = 1;
}
+
+ $q =~ s/^#//; # get rid of leading hash
+ if ( $type eq 'ticket' ) {
+ if ( $q =~ /^\d+$/ ) {
+
+ # only digits, must be an id, formulate a correct query
+ $q = "id=$q" if $q =~ /^\d+$/;
+ }
+ else {
+
+ # a string only, take it as an owner or requestor (quoting done later)
+ $q = "(Owner=$q or Requestor like $q) and $config{query}"
+ if $q =~ /^[\w\-]+$/;
+
+ # always add a query for a specific queue or (comma separated) queues
+ $queue =~ s/,/ or Queue=/g if $queue;
+ $q .= " and (Queue=$queue)"
+ if $queue
+ and $q
+ and $q !~ /Queue\s*=/i
+ and $q !~ /id\s*=/i;
+ }
+
+ # correctly quote strings in a query
+ $q =~ s/(=|like\s)\s*([^'\d\s]\S*)\b/$1\'$2\'/g;
+ }
+
#return help("list", $type) if $bad;
return suggest_help("list", $type, $bad) if $bad;
@@ -2159,13 +2180,14 @@ Text:
Displays a list of objects matching the specified conditions.
("ls", "list", and "search" are synonyms.)
- Conditions are expressed in the SQL-like syntax used internally by
- RT. (For more information, see "rt help query".) The query string
- must be supplied as one argument.
+ The query string must be supplied as one argument.
+
+ if on tickets, query is in the SQL-like syntax used internally by
+ RT. (For more information, see "rt help query".), otherwise, query
+ is plain string with format "FIELD OP VALUE", e.g. "Name = General".
- (Right now, the server doesn't support listing anything but tickets.
- Other types will be supported in future; this client will be able to
- take advantage of that support without any changes.)
+ if query string is absent, we limit to privileged ones on users and
+ user defined ones on groups automatically.
Options:
@@ -2196,6 +2218,9 @@ Text:
rt ls -t ticket "Subject like '[PATCH]%'"
rt ls -q systems
rt ls -f owner,subject
+ rt ls -t queue 'Name = General'
+ rt ls -t user 'EmailAddress like foo at bar.com'
+ rt ls -t group 'Name like foo'
--
commit 410ce6fbebfd97a5e5809e82c5ea3e144a3f7246
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jun 23 13:19:30 2011 +0800
restful search support for queues/users/groups
diff --git a/share/html/REST/1.0/Forms/group/default b/share/html/REST/1.0/Forms/group/default
index 7686f21..ca08b3d 100644
--- a/share/html/REST/1.0/Forms/group/default
+++ b/share/html/REST/1.0/Forms/group/default
@@ -58,7 +58,17 @@ my @comments;
my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $group = RT::Group->new($session{CurrentUser});
-my @fields = qw(Name Description);
+
+my @fields;
+if ( $fields && %$fields ) {
+ @fields =
+ grep { exists $fields->{ lc $_ } }
+ qw(Name Description);
+}
+else {
+ @fields = qw(Name Description);
+}
+
my %fields = map { lc $_ => $_ } @fields;
if ($id ne 'new') {
@@ -109,31 +119,33 @@ if (%data == 0) {
my @data;
push @data, [ id => "group/".$group->Id ];
- push @data, [ Name => $group->Name ];
- push @data, [ Description => $group->Description ];
-
+ foreach my $key (@fields) {
+ push @data, [ $key => $group->$key ];
+ }
# Members
- my $gms = [];
- my $GroupMembers = $group->MembersObj();
- while ( my $mo = $GroupMembers->Next() ) {
- if ( $mo->MemberObj->IsGroup ) {
- my $us = $mo->MemberObj->Object->UserMembersObj();
- my @users;
- while ( my $u = $us->Next() ) {
- push @users, $u->RealName . ' <' . $u->EmailAddress . '>';
+ unless ( $fields && !exists $fields->{members} ) {
+ my $gms = [];
+ my $GroupMembers = $group->MembersObj();
+ while ( my $mo = $GroupMembers->Next() ) {
+ if ( $mo->MemberObj->IsGroup ) {
+ my $us = $mo->MemberObj->Object->UserMembersObj();
+ my @users;
+ while ( my $u = $us->Next() ) {
+ push @users, $u->RealName . ' <' . $u->EmailAddress . '>';
+ }
+ push @$gms,
+ 'GROUP ['
+ . $mo->MemberObj->Object->Name . ']' . ' ('
+ . join( ';', @users ) . ')';
+ } elsif ( $mo->MemberObj->IsUser ) {
+ push @$gms,
+ $mo->MemberObj->Object->RealName . ' <'
+ . $mo->MemberObj->Object->EmailAddress . '>';
}
- push @$gms,
- 'GROUP ['
- . $mo->MemberObj->Object->Name . ']' . ' ('
- . join( ';', @users ) . ')';
- } elsif ( $mo->MemberObj->IsUser ) {
- push @$gms,
- $mo->MemberObj->Object->RealName . ' <'
- . $mo->MemberObj->Object->EmailAddress . '>';
}
+ push @data, [ Members => $gms ];
}
- push @data, [ Members => $gms ];
# Custom fields
my $CustomFields = $group->CustomFields;
diff --git a/share/html/REST/1.0/Forms/queue/default b/share/html/REST/1.0/Forms/queue/default
index e6d50f3..9f02db2 100755
--- a/share/html/REST/1.0/Forms/queue/default
+++ b/share/html/REST/1.0/Forms/queue/default
@@ -58,8 +58,17 @@ my @comments;
my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $queue = RT::Queue->new($session{CurrentUser});
-my @fields = qw(Name Description CorrespondAddress CommentAddress
+
+my @fields;
+if ( $fields && %$fields ) {
+ @fields =
+ grep { exists $fields->{ lc $_ } }
+ qw(Name Description CorrespondAddress CommentAddress InitialPriority FinalPriority DefaultDueIn);
+}
+else {
+ @fields = qw(Name Description CorrespondAddress CommentAddress
InitialPriority FinalPriority DefaultDueIn);
+}
my %fields = map { lc $_ => $_ } @fields;
if ($id ne 'new') {
diff --git a/share/html/REST/1.0/Forms/user/default b/share/html/REST/1.0/Forms/user/default
index a5786ba..87c2bce 100755
--- a/share/html/REST/1.0/Forms/user/default
+++ b/share/html/REST/1.0/Forms/user/default
@@ -51,17 +51,33 @@
$id
$format => 's'
$changes => {}
+$fields => undef
</%ARGS>
<%perl>
my @comments;
my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $user = RT::User->new($session{CurrentUser});
-my @fields = qw(RealName NickName Gecos Organization Address1 Address2 City
- State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
- FreeformContactInfo Comments Signature Lang EmailEncoding
- WebEncoding ExternalContactInfoId ContactInfoSystem
- ExternalAuthId AuthSystem Privileged Disabled);
+
+my @fields;
+if ( $fields && %$fields ) {
+ @fields =
+ grep { exists $fields->{ lc $_ } }
+ qw(Name EmailAddress RealName NickName Gecos Organization Address1
+ Address2 City State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
+ FreeformContactInfo Comments Signature Lang EmailEncoding
+ WebEncoding ExternalContactInfoId ContactInfoSystem
+ ExternalAuthId AuthSystem Privileged Disabled);
+}
+else {
+ @fields =
+ qw(Name EmailAddress RealName NickName Gecos Organization Address1
+ Address2 City State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
+ FreeformContactInfo Comments Signature Lang EmailEncoding
+ WebEncoding ExternalContactInfoId ContactInfoSystem
+ ExternalAuthId AuthSystem Privileged Disabled);
+}
+
my %fields = map { lc $_ => $_ } @fields;
if ($id ne 'new') {
@@ -117,14 +133,17 @@ if (keys %data == 0) {
my @data;
push @data, [ id => "user/".$user->Id ];
- push @data, [ Name => $user->Name ];
- push @data, [ Password => '********' ];
- push @data, [ EmailAddress => $user->EmailAddress ];
- foreach my $key (@fields) {
- my $val = $user->$key;
+ unless ( $fields && %$fields && !exists $fields->{'password'} ) {
+ push @data, [ Password => '********' ];
+ }
- if ( (defined ($format) && $format eq 'l') || (defined $val && $val ne '')) {
+ for my $key (@fields) {
+ my $val = $user->$key;
+ if ( ( $fields && exists $fields->{ lc $key } )
+ || ( defined $format && $format eq 'l' )
+ || ( defined $val && $val ne '' ) )
+ {
$key = "ContactInfo" if $key eq 'FreeformContactInfo';
push @data, [ $key => $val ];
}
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index e1ddb9b..417de01 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -47,10 +47,153 @@
%# 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.";
-</%INIT>
-RT/<% $RT::VERSION %> <% $status %>
+my $type = $m->dhandler_arg;
+my ( $status, $output );
+
+if ( $type =~ /^(queue|user|group)$/i ) {
+ $status = "200 Ok";
+ $output = '';
+ my $type = lc $1;
+ 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;
+ }
+
+ if ($orderby) {
+ my ( $order, $field ) = $orderby =~ /^([\+\-])?(.+)/;
+ $order = $order && $order eq '-' ? 'DESC' : 'ASC';
+ $objects->OrderBy( FIELD => $field, ORDER => $order );
+ }
+
+ my ( $n, $s );
+ $n = 0;
+ my @output;
+
+ if ( defined $query && length $query ) {
+ 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;
+ }
-<% $output |n %>
+ if ( $field && $op && defined $value ) {
+ $objects->Limit(
+ FIELD => $field,
+ OPERATOR => uc $op,
+ VALUE => $value
+ );
+ }
+ else {
+ $output = "Invalid query specification: $query";
+ goto OUTPUT;
+ }
+ }
+ else {
+ if ( $type eq 'queue' ) {
+ $objects->UnLimit;
+ }
+ elsif ( $type eq 'group' ) {
+ $objects->LimitToUserDefinedGroups;
+ }
+ elsif ( $type eq 'user' ) {
+ $objects->LimitToPrivileged;
+ }
+ }
+
+ while ( my $object = $objects->Next ) {
+ $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 {
+ $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>
commit b6782d08e8857b14c167c986c821158ed800fbc4
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jun 23 15:11:53 2011 +0800
merge restful ticket search to dhandler to avoid replicated code
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index 417de01..0c524ee 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -57,7 +57,7 @@ $fields => undef
my $type = $m->dhandler_arg;
my ( $status, $output );
-if ( $type =~ /^(queue|user|group)$/i ) {
+if ( $type =~ /^(ticket|queue|user|group)$/i ) {
$status = "200 Ok";
$output = '';
my $type = lc $1;
@@ -90,35 +90,43 @@ if ( $type =~ /^(queue|user|group)$/i ) {
goto OUTPUT;
}
- if ($orderby) {
- my ( $order, $field ) = $orderby =~ /^([\+\-])?(.+)/;
- $order = $order && $order eq '-' ? 'DESC' : 'ASC';
- $objects->OrderBy( FIELD => $field, ORDER => $order );
- }
-
my ( $n, $s );
$n = 0;
my @output;
if ( defined $query && length $query ) {
- 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 ( $field && $op && defined $value ) {
- $objects->Limit(
- FIELD => $field,
- OPERATOR => uc $op,
- VALUE => $value
- );
+ 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 {
- $output = "Invalid query specification: $query";
- goto OUTPUT;
+ 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 ( $field && $op && defined $value ) {
+ $objects->Limit(
+ FIELD => $field,
+ OPERATOR => uc $op,
+ VALUE => $value
+ );
+ }
+ else {
+ $output = "Invalid query specification: $query";
+ goto OUTPUT;
+ }
}
}
else {
@@ -133,6 +141,12 @@ if ( $type =~ /^(queue|user|group)$/i ) {
}
}
+ if ($orderby) {
+ my ( $order, $field ) = $orderby =~ /^([\+\-])?(.+)/;
+ $order = $order && $order eq '-' ? 'DESC' : 'ASC';
+ $objects->OrderBy( FIELD => $field, ORDER => $order );
+ }
+
while ( my $object = $objects->Next ) {
$n++;
@@ -167,7 +181,12 @@ if ( $type =~ /^(queue|user|group)$/i ) {
) . "\n";
}
else {
- $output .= $object->Id . ": " . $object->Name . "\n";
+ if ( $type eq 'ticket' ) {
+ $output .= $object->Id . ": " . $object->Subject . "\n";
+ }
+ else {
+ $output .= $object->Id . ": " . $object->Name . "\n";
+ }
}
}
else {
diff --git a/share/html/REST/1.0/search/ticket b/share/html/REST/1.0/search/ticket
deleted file mode 100755
index 16c6c6a..0000000
--- a/share/html/REST/1.0/search/ticket
+++ /dev/null
@@ -1,165 +0,0 @@
-%# BEGIN BPS TAGGED BLOCK {{{
-%#
-%# COPYRIGHT:
-%#
-%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
-%# <sales at 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>
commit 6e9456802e02d8d6c9f1481326d3187c14d1bd40
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Jun 24 12:13:36 2011 +0800
clean some replicated code
diff --git a/share/html/REST/1.0/Forms/group/default b/share/html/REST/1.0/Forms/group/default
index ca08b3d..a71ed8f 100644
--- a/share/html/REST/1.0/Forms/group/default
+++ b/share/html/REST/1.0/Forms/group/default
@@ -59,14 +59,9 @@ my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $group = RT::Group->new($session{CurrentUser});
-my @fields;
+my @fields = qw(Name Description);
if ( $fields && %$fields ) {
- @fields =
- grep { exists $fields->{ lc $_ } }
- qw(Name Description);
-}
-else {
- @fields = qw(Name Description);
+ @fields = grep { exists $fields->{ lc $_ } } @fields;
}
my %fields = map { lc $_ => $_ } @fields;
diff --git a/share/html/REST/1.0/Forms/queue/default b/share/html/REST/1.0/Forms/queue/default
index 9f02db2..393962d 100755
--- a/share/html/REST/1.0/Forms/queue/default
+++ b/share/html/REST/1.0/Forms/queue/default
@@ -59,16 +59,12 @@ my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $queue = RT::Queue->new($session{CurrentUser});
-my @fields;
+my @fields =
+ qw(Name Description CorrespondAddress CommentAddress InitialPriority FinalPriority DefaultDueIn);
if ( $fields && %$fields ) {
- @fields =
- grep { exists $fields->{ lc $_ } }
- qw(Name Description CorrespondAddress CommentAddress InitialPriority FinalPriority DefaultDueIn);
-}
-else {
- @fields = qw(Name Description CorrespondAddress CommentAddress
- InitialPriority FinalPriority DefaultDueIn);
+ @fields = grep { exists $fields->{ lc $_ } } @fields;
}
+
my %fields = map { lc $_ => $_ } @fields;
if ($id ne 'new') {
diff --git a/share/html/REST/1.0/Forms/user/default b/share/html/REST/1.0/Forms/user/default
index 87c2bce..01ef531 100755
--- a/share/html/REST/1.0/Forms/user/default
+++ b/share/html/REST/1.0/Forms/user/default
@@ -59,23 +59,15 @@ my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $user = RT::User->new($session{CurrentUser});
-my @fields;
+my @fields =
+ qw(Name EmailAddress RealName NickName Gecos Organization Address1
+ Address2 City State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
+ FreeformContactInfo Comments Signature Lang EmailEncoding
+ WebEncoding ExternalContactInfoId ContactInfoSystem
+ ExternalAuthId AuthSystem Privileged Disabled);
+
if ( $fields && %$fields ) {
- @fields =
- grep { exists $fields->{ lc $_ } }
- qw(Name EmailAddress RealName NickName Gecos Organization Address1
- Address2 City State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
- FreeformContactInfo Comments Signature Lang EmailEncoding
- WebEncoding ExternalContactInfoId ContactInfoSystem
- ExternalAuthId AuthSystem Privileged Disabled);
-}
-else {
- @fields =
- qw(Name EmailAddress RealName NickName Gecos Organization Address1
- Address2 City State Zip Country HomePhone WorkPhone MobilePhone PagerPhone
- FreeformContactInfo Comments Signature Lang EmailEncoding
- WebEncoding ExternalContactInfoId ContactInfoSystem
- ExternalAuthId AuthSystem Privileged Disabled);
+ @fields = grep { exists $fields->{ lc $_ } } @fields;
}
my %fields = map { lc $_ => $_ } @fields;
commit 2ef89d22587def82aa6ff1b2862c9ba5845647cc
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Jun 24 12:30:02 2011 +0800
shouldn't allow user to search password field
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index 0c524ee..9cdbac7 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -117,6 +117,12 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
}
if ( $field && $op && defined $value ) {
+ if ( $type eq 'user' && $field =~ /password/i ) {
+ $status = "400 Bad Request";
+ $output = "Invalid field specification: $field";
+ goto OUTPUT;
+ }
+
$objects->Limit(
FIELD => $field,
OPERATOR => uc $op,
commit b858f5b05ea3094b4c9fa62a2b1b5ecb2639b20a
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Jun 24 12:44:04 2011 +0800
allow restful user search only if current user has AdminUsers right
user data is sensible and shouldn't be seen easily.
besides, we don't have SeeUser right either.
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index 9cdbac7..b454471 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -61,6 +61,21 @@ 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} );
commit a19ec9dc08667f8669431c04e5173ad60957dec3
Author: sunnavy <sunnavy at bestpractical.com>
Date: Sat Jun 25 15:28:54 2011 +0800
search user defined groups only
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index b454471..c99aeea 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -109,6 +109,11 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
$n = 0;
my @output;
+
+ if ( $type eq 'group' ) {
+ $objects->LimitToUserDefinedGroups;
+ }
+
if ( defined $query && length $query ) {
if ( $type eq 'ticket' ) {
my ( $n, $s );
@@ -154,9 +159,6 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
if ( $type eq 'queue' ) {
$objects->UnLimit;
}
- elsif ( $type eq 'group' ) {
- $objects->LimitToUserDefinedGroups;
- }
elsif ( $type eq 'user' ) {
$objects->LimitToPrivileged;
}
commit fd12f69a80081d546a41f1ca4963d3d43f2c2acc
Author: sunnavy <sunnavy at bestpractical.com>
Date: Tue Jun 28 22:29:15 2011 +0800
whitelist of restful search fields
this is better than only blacklisting hardcoded "password"
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index c99aeea..9178b8f 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -136,12 +136,14 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
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 ( $type eq 'user' && $field =~ /password/i ) {
- $status = "400 Bad Request";
- $output = "Invalid field specification: $field";
- goto OUTPUT;
- }
$objects->Limit(
FIELD => $field,
@@ -239,3 +241,25 @@ OUTPUT:
$m->out("RT/". $RT::VERSION . " " . $status ."\n\n");
$m->out($output );
</%INIT>
+
+<%ONCE>
+my %search_whitelist = (
+ queue => {
+ map { lc $_ => 1 }
+ grep { $RT::Record::_TABLE_ATTR->{'RT::Queue'}{$_}{read} }
+ keys %{ $RT::Record::_TABLE_ATTR->{'RT::Queue'} }
+ },
+ user => {
+ map { lc $_ => 1 }
+ grep { $RT::Record::_TABLE_ATTR->{'RT::User'}{$_}{read} }
+ keys %{ $RT::Record::_TABLE_ATTR->{'RT::User'} }
+ },
+ group => {
+ map { lc $_ => 1 }
+ grep { $RT::Record::_TABLE_ATTR->{'RT::Group'}{$_}{read} }
+ keys %{ $RT::Record::_TABLE_ATTR->{'RT::Group'} }
+ }
+);
+
+</%ONCE>
+
commit 99572eb685274a138dbbb1ecb29f8c3d0a295694
Author: sunnavy <sunnavy at bestpractical.com>
Date: Mon Jul 4 18:52:27 2011 +0800
allow < and > ops too
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index 9178b8f..8ce8497 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -129,7 +129,7 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
require Text::ParseWords;
my ( $field, $op, $value ) = Text::ParseWords::shellwords($query);
if ( $op !~
- /^(?:[!<>]?=|(NOT )?LIKE|STARTSWITH|ENDSWITH|MATCHES)$/i )
+ /^(?:[!<>]?=|[<>]|(NOT )?LIKE|STARTSWITH|ENDSWITH|MATCHES)$/i )
{
$status = "400 Bad Request";
$output = "Invalid operator specification: $op";
commit a6fd969fdb1967d03709e317e15d83c782f467af
Author: sunnavy <sunnavy at bestpractical.com>
Date: Mon Jul 4 20:19:26 2011 +0800
tests for restful search of queue/group/user
diff --git a/t/web/rest-search-group.t b/t/web/rest-search-group.t
new file mode 100644
index 0000000..a5bc4e6
--- /dev/null
+++ b/t/web/rest-search-group.t
@@ -0,0 +1,85 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use RT::Test tests => 18;
+
+my $group_foo = RT::Group->new($RT::SystemUser);
+$group_foo->CreateUserDefinedGroup( Name => 'foo' );
+
+my $group_bar = RT::Group->new($RT::SystemUser);
+$group_bar->CreateUserDefinedGroup( Name => 'bar' );
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+
+ok( $m->login, 'logged in' );
+
+search_groups_ok(
+ { query => 'id = ' . $group_foo->id },
+ [ $group_foo->id . ': foo' ],
+ 'search by id'
+);
+
+search_groups_ok(
+ {
+ query => 'Name = ' . $group_foo->Name,
+ format => 's',
+ fields => 'id,name',
+ },
+ [ "id\tName", $group_foo->id . "\tfoo" ],
+ 'search by name with customized fields'
+);
+
+search_groups_ok(
+ { query => 'foo = 3' },
+ ['Invalid field specification: foo'],
+ 'invalid field'
+);
+
+search_groups_ok(
+ { query => 'id foo 3' },
+ ['Invalid operator specification: foo'],
+ 'invalid op'
+);
+
+search_groups_ok(
+ { query => '', orderby => 'id' },
+ [ $group_foo->id . ': foo', $group_bar->id . ': bar', ],
+ 'order by id'
+);
+
+search_groups_ok(
+ { query => '', orderby => 'name' },
+ [ $group_bar->id . ': bar', $group_foo->id . ': foo' ],
+ 'order by name'
+);
+
+search_groups_ok(
+ { query => '', orderby => '+name' },
+ [ $group_bar->id . ': bar', $group_foo->id . ': foo' ],
+ 'order by +name'
+);
+
+search_groups_ok(
+ { query => '', orderby => '-name' },
+ [ $group_foo->id . ': foo', $group_bar->id . ': bar' ],
+ 'order by -name'
+);
+
+sub search_groups_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $query = shift;
+ my $expected = shift;
+ my $name = shift || 'search groups';
+
+ my $uri = URI->new("$baseurl/REST/1.0/search/group");
+ $uri->query_form(%$query);
+ $m->get_ok($uri);
+
+ my @lines = split /\n/, $m->content;
+ shift @lines; # header
+ shift @lines; # empty line
+
+ is_deeply( \@lines, $expected, $name );
+
+}
+
diff --git a/t/web/rest-search-queue.t b/t/web/rest-search-queue.t
new file mode 100644
index 0000000..e9701ad
--- /dev/null
+++ b/t/web/rest-search-queue.t
@@ -0,0 +1,83 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use RT::Test tests => 20;
+
+my $queue_foo = RT::Test->load_or_create_queue( Name => 'foo' );
+my $queue_bar = RT::Test->load_or_create_queue( Name => 'bar' );
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+
+ok( $m->login, 'logged in' );
+
+search_queues_ok( { query => 'id = 1' }, ['1: General'], 'search id = 1' );
+search_queues_ok(
+ {
+ query => 'Name = General',
+ format => 's',
+ fields => 'id,name,description'
+ },
+ [ "id\tName\tDescription", "1\tGeneral\tThe default queue" ],
+ 'search by name with customized fields'
+);
+
+search_queues_ok(
+ { query => 'id > 10' },
+ ['No matching results.'],
+ 'no matching results'
+);
+
+search_queues_ok(
+ { query => 'foo = 3' },
+ ['Invalid field specification: foo'],
+ 'invalid field'
+);
+
+search_queues_ok(
+ { query => 'id foo 3' },
+ ['Invalid operator specification: foo'],
+ 'invalid op'
+);
+
+search_queues_ok(
+ { query => '', orderby => 'id' },
+ [ '1: General', $queue_foo->id . ': foo', $queue_bar->id . ': bar', ],
+ 'order by id'
+);
+
+search_queues_ok(
+ { query => '', orderby => 'name' },
+ [ '1: General', $queue_bar->id . ': bar', $queue_foo->id . ': foo' ],
+ 'order by name'
+);
+
+search_queues_ok(
+ { query => '', orderby => '+name' },
+ [ '1: General', $queue_bar->id . ': bar', $queue_foo->id . ': foo' ],
+ 'order by +name'
+);
+
+search_queues_ok(
+ { query => '', orderby => '-name' },
+ [ $queue_foo->id . ': foo', $queue_bar->id . ': bar', '1: General', ],
+ 'order by -name'
+);
+
+sub search_queues_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $query = shift;
+ my $expected = shift;
+ my $name = shift || 'search queues';
+
+ my $uri = URI->new("$baseurl/REST/1.0/search/queue");
+ $uri->query_form(%$query);
+ $m->get_ok($uri);
+
+ my @lines = split /\n/, $m->content;
+ shift @lines; # header
+ shift @lines; # empty line
+
+ is_deeply( \@lines, $expected, $name );
+
+}
+
diff --git a/t/web/rest-search-user.t b/t/web/rest-search-user.t
new file mode 100644
index 0000000..e633aa3
--- /dev/null
+++ b/t/web/rest-search-user.t
@@ -0,0 +1,100 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use RT::Test tests => 23;
+
+my $root = RT::Test->load_or_create_user( Name => 'root', );
+my $user_foo = RT::Test->load_or_create_user(
+ Name => 'foo',
+ Password => 'password',
+);
+my $user_bar = RT::Test->load_or_create_user( Name => 'bar' );
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+
+ok( $m->login, 'logged in' );
+
+search_users_ok(
+ { query => 'id = ' . $user_foo->id },
+ [ $user_foo->id . ': foo' ],
+ 'search by id'
+);
+
+search_users_ok(
+ {
+ query => 'Name = ' . $user_foo->Name,
+ format => 's',
+ fields => 'id,name'
+ },
+ [ "id\tName", $user_foo->id . "\tfoo" ],
+ 'search by name with customized fields'
+);
+
+
+search_users_ok(
+ { query => 'foo = 3' },
+ ['Invalid field specification: foo'],
+ 'invalid field'
+);
+
+search_users_ok(
+ { query => 'id foo 3' },
+ ['Invalid operator specification: foo'],
+ 'invalid op'
+);
+
+search_users_ok(
+ { query => 'password = foo' },
+ ['Invalid field specification: password'],
+ "can't search password"
+);
+
+search_users_ok(
+ { query => '', orderby => 'id' },
+ [ $root->id . ': root', $user_foo->id . ': foo', $user_bar->id . ': bar', ],
+ 'order by id'
+);
+
+search_users_ok(
+ { query => '', orderby => 'name' },
+ [ $user_bar->id . ': bar', $user_foo->id . ': foo', $root->id . ': root' ],
+ 'order by name'
+);
+
+search_users_ok(
+ { query => '', orderby => '+name' },
+ [ $user_bar->id . ': bar', $user_foo->id . ': foo', $root->id . ': root' ],
+ 'order by +name'
+);
+
+search_users_ok(
+ { query => '', orderby => '-name' },
+ [ $root->id . ': root', $user_foo->id . ': foo', $user_bar->id . ': bar' ],
+ 'order by -name'
+);
+
+ok( $m->login( 'foo', 'password', logout => 1 ), 'logged in as foo' );
+search_users_ok(
+ { query => 'id = ' . $user_foo->id },
+ [ 'Permission denied' ],
+ "can't search without permission"
+);
+
+sub search_users_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $query = shift;
+ my $expected = shift;
+ my $name = shift || 'search users';
+
+ my $uri = URI->new("$baseurl/REST/1.0/search/user");
+ $uri->query_form(%$query);
+ $m->get_ok($uri);
+
+ my @lines = split /\n/, $m->content;
+ shift @lines; # header
+ shift @lines; # empty line
+
+ is_deeply( \@lines, $expected, $name );
+
+}
+
commit 02fad4466852497d6008e3471fe54dab88a9a56a
Author: sunnavy <sunnavy at bestpractical.com>
Date: Wed Jun 13 08:41:32 2012 +0800
REST: show Disabled column for queues/groups
diff --git a/share/html/REST/1.0/Forms/group/default b/share/html/REST/1.0/Forms/group/default
index a71ed8f..3b966e9 100644
--- a/share/html/REST/1.0/Forms/group/default
+++ b/share/html/REST/1.0/Forms/group/default
@@ -59,7 +59,7 @@ my ($c, $o, $k, $e) = ("", [], {}, 0);
my %data = %$changes;
my $group = RT::Group->new($session{CurrentUser});
-my @fields = qw(Name Description);
+my @fields = qw(Name Description Disabled);
if ( $fields && %$fields ) {
@fields = grep { exists $fields->{ lc $_ } } @fields;
}
diff --git a/share/html/REST/1.0/Forms/queue/default b/share/html/REST/1.0/Forms/queue/default
index 393962d..5691af5 100755
--- a/share/html/REST/1.0/Forms/queue/default
+++ b/share/html/REST/1.0/Forms/queue/default
@@ -60,7 +60,7 @@ my %data = %$changes;
my $queue = RT::Queue->new($session{CurrentUser});
my @fields =
- qw(Name Description CorrespondAddress CommentAddress InitialPriority FinalPriority DefaultDueIn);
+ qw(Name Description CorrespondAddress CommentAddress InitialPriority FinalPriority DefaultDueIn Disabled);
if ( $fields && %$fields ) {
@fields = grep { exists $fields->{ lc $_ } } @fields;
}
commit 9da2fcd775a050da7b4a17a6b33ba341cc630357
Author: sunnavy <sunnavy at bestpractical.com>
Date: Wed Jun 13 09:41:37 2012 +0800
REST: handle Disabled column search for queues/groups/users
diff --git a/share/html/REST/1.0/search/dhandler b/share/html/REST/1.0/search/dhandler
index 8ce8497..9db6666 100755
--- a/share/html/REST/1.0/search/dhandler
+++ b/share/html/REST/1.0/search/dhandler
@@ -144,12 +144,28 @@ if ( $type =~ /^(ticket|queue|user|group)$/i ) {
if ( $field && $op && defined $value ) {
+ if ( $field eq 'Disabled' ) {
+ if ($value) {
+ $objects->FindAllRows;
+ if ( $type eq 'queue' ) {
- $objects->Limit(
- FIELD => $field,
- OPERATOR => uc $op,
- VALUE => $value
- );
+ # special case for queue that
+ # Disabled could be 2(___Approvals)
+ $objects->Limit(
+ FIELD => $field,
+ OPERATOR => uc $op,
+ VALUE => $value
+ );
+ }
+ }
+ }
+ else {
+ $objects->Limit(
+ FIELD => $field,
+ OPERATOR => uc $op,
+ VALUE => $value
+ );
+ }
}
else {
$output = "Invalid query specification: $query";
@@ -250,11 +266,13 @@ my %search_whitelist = (
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'} }
commit 8ade2ed3bfdabc395d01a0ea18e0012093cfa84d
Author: sunnavy <sunnavy at bestpractical.com>
Date: Wed Jun 13 22:07:29 2012 +0800
test number fix
diff --git a/t/web/rest-search-group.t b/t/web/rest-search-group.t
index a5bc4e6..c5f9d4a 100644
--- a/t/web/rest-search-group.t
+++ b/t/web/rest-search-group.t
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
use strict;
use warnings;
-use RT::Test tests => 18;
+use RT::Test tests => 20;
my $group_foo = RT::Group->new($RT::SystemUser);
$group_foo->CreateUserDefinedGroup( Name => 'foo' );
diff --git a/t/web/rest-search-queue.t b/t/web/rest-search-queue.t
index e9701ad..649912f 100644
--- a/t/web/rest-search-queue.t
+++ b/t/web/rest-search-queue.t
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
use strict;
use warnings;
-use RT::Test tests => 20;
+use RT::Test tests => 22;
my $queue_foo = RT::Test->load_or_create_queue( Name => 'foo' );
my $queue_bar = RT::Test->load_or_create_queue( Name => 'bar' );
diff --git a/t/web/rest-search-user.t b/t/web/rest-search-user.t
index e633aa3..b6b11ca 100644
--- a/t/web/rest-search-user.t
+++ b/t/web/rest-search-user.t
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
use strict;
use warnings;
-use RT::Test tests => 23;
+use RT::Test tests => 25;
my $root = RT::Test->load_or_create_user( Name => 'root', );
my $user_foo = RT::Test->load_or_create_user(
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list