Skip to content

Commit

Permalink
Merge branch '5.0-trunk'
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnavy committed Dec 19, 2024
2 parents 13dfcec + d18adc5 commit 94aa307
Show file tree
Hide file tree
Showing 31 changed files with 430 additions and 62 deletions.
46 changes: 46 additions & 0 deletions docs/query_builder.pod
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ F<docs/images/sorting-display-columns.png>]

=for :man [Sorting and Display Columns F<docs/images/sorting-display-columns.png>]

=head2 Sorting Results

There is more than one option for Sorting so you can view tickets in a
search result set in a meaningful order. For example, let's say you
start off by sorting tickets in a search by their owner. Tickets will then
Expand All @@ -106,6 +108,8 @@ each owner. To further organize the tickets owned by each user, you could
add a sort by Due to see tickets sorted first by owner, and then Due date
within the tickets per owner.

=head2 Display Columns

The Display Columns tab allows you to add or remove information displayed in
the results of your search. NEWLINE indicates a line break, or new row, in how
the results are displayed. NBSP for adding an empty column (such as what shows
Expand Down Expand Up @@ -143,6 +147,48 @@ the most important information and also to optimize the display for users.
This formatting is saved when you save a search, so you can set different
formats for different searches (see L</"Saved Searches">).

=head2 Advanced Output Formatting

There are some additional advanced features you can use to further customize
the appearance and functionality of your search results. You can enable
these by editing the underlying Format definitions directly. To see these
definitions, click the Advanced tab in the Query Builder.

The Advanced page shows the full text of your query at the top, and has a
Format box on the bottom, which shows the actual format definition for the
columns you have selected. You can change these directly in the Format box
to refine how columns are shown in search results. Here are some examples
of changes you can make.

=over

=item Change the Column Title

The default column format for the ticket ID looks like:

'<a href="__WebPath__/Asset/Display.html?id=__id__">__id__</a>/TITLE:#',

If you want the column title to show "ID" rather than "#", you can change
it to:

'<a href="__WebPath__/Asset/Display.html?id=__id__">__id__</a>/TITLE:ID',

=item Filter Link Types

The default format for links, like Depends On, looks like this:

'__DependsOn__',

A ticket can have links to other tickets, assets, or other things. If you
want to filter the display to only show asset links, you can update the
format like this:

'__DependsOn.{Asset}__',

If you set "Ticket" instead of "Asset", it will show only ticket links.

=back

=head1 Dynamic Filtering and Sorting

After you perform a search, you can refine your results directly on the
Expand Down
2 changes: 1 addition & 1 deletion etc/cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ requires 'HTML::Gumbo';
requires 'HTML::Mason', '>= 1.43';
requires 'HTML::Mason::PSGIHandler', '>= 0.52';
requires 'HTML::Quoted';
requires 'HTML::RewriteAttributes', '>= 0.05';
requires 'HTML::RewriteAttributes', '>= 0.06';
requires 'HTML::Scrubber', '>= 0.08';
requires 'HTTP::Message', '>= 6.07';
requires 'IPC::Run3';
Expand Down
2 changes: 1 addition & 1 deletion lib/RT/Action/CreateTickets.pm
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ A convoluted example:
my $groups = RT::Groups->new(RT->SystemUser);
$groups->LimitToUserDefinedGroups();
$groups->Limit(FIELD => "Name", OPERATOR => "=", VALUE => $name, CASESENSITIVE => 0);
$groups->WithMember($TransactionObj->CreatorObj->Id);
$groups->WithMember(PrincipalId => $TransactionObj->CreatorObj->Id);
my $groupid = $groups->First->Id;
Expand Down
45 changes: 34 additions & 11 deletions lib/RT/Interface/Web.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2104,9 +2104,14 @@ sub RewriteInlineImages {
$$content = HTML::RewriteAttributes::Resources->rewrite($$content, sub {
my $cid = shift;
my %meta = @_;
return $cid unless lc $meta{tag} eq 'img'
and lc $meta{attr} eq 'src'
and $cid =~ s/^cid://i;
return $cid unless lc $meta{tag} eq 'img';

if ( !$meta{attrs}{loading} ) {
$meta{attrs}{loading} = 'lazy';
push @{ $meta{attr_list} }, 'loading';
}

return $cid unless lc $meta{attr} eq 'src' && $cid =~ s/^cid://i;

for my $attach (@{$args{Related}}) {
if (($attach->GetHeader('Content-ID') || '') =~ /^(<)?\Q$cid\E(?(1)>)$/) {
Expand Down Expand Up @@ -5350,22 +5355,40 @@ sub GetDefaultQueue {
my %args = (
IncludeFirst => 0,
@_ );
my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );

# RememberDefaultQueue tracks the last queue used by this user, if set.
if ( $session{'DefaultQueue'} && RT->Config->Get( "RememberDefaultQueue", $session{'CurrentUser'} ) ) {
$queue = $session{'DefaultQueue'};

# Confirm the user can see and load the queue
$queue_obj->Load($queue);
}
else {

# Need to check Name here rather than Id to confirm SeeQueue rights.
# This aligns with the evaluation in the final return line.

# Check for a personal user preference
if ( !defined $queue_obj->Name || $queue_obj->Disabled ) {
$queue = RT->Config->Get( "DefaultQueue", $session{'CurrentUser'} );

if ( $queue ) {
# Confirm the user can see and load the queue
$queue_obj->Load($queue);
}
}

# Confirm the user can see and load the default queue
my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
$queue_obj->Load($queue);
# Check for global system-level setting
if ( !defined $queue_obj->Name || $queue_obj->Disabled ) {
$queue = RT->Config->Get( "DefaultQueue" );

# Need to check Name here rather than Id to confirm SeeQueue rights.
# This aligns with the evaluation in the final return line.
unless ( $queue_obj && $queue_obj->Name ) {
if ( $queue ) {
# Confirm the user can see and load the queue
$queue_obj->Load($queue);
}
}

if ( !defined $queue_obj->Name || $queue_obj->Disabled ) {
if ( $args{'IncludeFirst'} ) {
# pick first in list in normal order unless queue provided from form/url/defaults
my $cache_key = SetObjectSessionCache(
Expand All @@ -5380,7 +5403,7 @@ sub GetDefaultQueue {
}
}

return defined $queue_obj->Name ? $queue_obj->Id : undef;
return ($queue_obj && defined $queue_obj->Name && !$queue_obj->Disabled) ? $queue_obj->Id : undef;
}

=head2 ListOfReports
Expand Down
21 changes: 21 additions & 0 deletions lib/RT/Interface/Web/MenuBuilder.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,27 @@ sub _BuildAdminPageMenu {
);
}
}

# Define a mapping for Rights and History paths
my %rights_pages = (
'Groups' => 'GroupRights.html',
'Users' => 'UserRights.html',
);

# Match request paths for Rights and History pages
if ( $request_path =~ m{^/Admin/Global/(GroupRights|UserRights)\.html$} ) {
my $type = $1 eq 'GroupRights' ? 'Groups' : 'Users';
$page->child( rights => title => loc('Rights'), path => "/Admin/Global/$1.html" );
$page->child( history => title => loc('History'), path => "/Admin/Global/RightsHistory.html?Type=$type" );
}
elsif ( $request_path =~ m{^/Admin/Global/RightsHistory\.html} ) {
# Extract type from request arguments
if ( my $type = $HTML::Mason::Commands::DECODED_ARGS->{'Type'} ) {
my $rights_page = $rights_pages{$type} || 'UserRights.html'; # Default to UserRights
$page->child( rights => title => loc('Rights'), path => "/Admin/Global/$rights_page" );
$page->child( history => title => loc('History'), path => "/Admin/Global/RightsHistory.html?Type=$type" );
}
}
}

sub BuildSelfServiceMainNav {
Expand Down
2 changes: 1 addition & 1 deletion lib/RT/LDAPImport.pm
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ sub _import_users {

my $done = 0; my $count = scalar @$users;
while (my $entry = shift @$users) {
my $user = $self->_build_user_object( ldap_entry => $entry );
my $user = $self->_build_user_object( ldap_entry => $entry, import => $args{import} );
$self->_import_user( user => $user, ldap_entry => $entry, import => $args{import} );
$done++;
$RT::Logger->debug("Imported $done/$count users");
Expand Down
3 changes: 2 additions & 1 deletion lib/RT/Migrate.pm
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ sub progress {
my $start;
my $left;
my $offset;
my $clear = `clear`;
return sub {
my $obj = shift;
my $force = shift;
Expand All @@ -117,7 +118,7 @@ sub progress {
my $elapsed = $now - $start;

# Determine terminal size
print `clear`;
print $clear;
my ($cols, $rows) = (80, 25);
eval {
require Term::ReadKey;
Expand Down
7 changes: 5 additions & 2 deletions lib/RT/Migrate/Importer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,13 @@ sub CloseStream {

# Fill CGM

# $self here isn't an RT::Record
my $groups_table = RT::Group->can('QuotedTableName') ? RT::Group->QuotedTableName('Groups') : 'Groups';

# Groups
$self->RunSQL(<<'EOF');
INSERT INTO CachedGroupMembers (GroupId, MemberId, Via, ImmediateParentId, Disabled)
SELECT Groups.id, Groups.id, 0, Groups.id, Principals.Disabled FROM Groups
SELECT Groups.id, Groups.id, 0, Groups.id, Principals.Disabled FROM $groups_table
LEFT JOIN Principals ON ( Groups.id = Principals.id )
LEFT JOIN CachedGroupMembers ON (
Groups.id = CachedGroupMembers.GroupId
Expand Down Expand Up @@ -673,7 +676,7 @@ FROM
AND cgm3.MemberId = gm2.MemberId
AND cgm3.Via = cgm1.id
AND cgm3.ImmediateParentId = cgm1.MemberId )
LEFT JOIN Groups g ON (
LEFT JOIN $groups_table g ON (
cgm1.GroupId = g.id
)
WHERE cgm1.GroupId != cgm1.MemberId
Expand Down
7 changes: 5 additions & 2 deletions lib/RT/RightsInspector.pm
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,20 @@ sub InnerRoleQuery {
or die "No parent mapping specified for $inner_class";
my $parent_table = $parent_class->Table;

# $self here isn't an RT::Record
my $groups_table = RT::Group->can('QuotedTableName') ? RT::Group->QuotedTableName('Groups') : 'Groups';

my @query = qq[
SELECT main.id,
MIN(InnerRecords.id) AS example_record,
COUNT(InnerRecords.id)-1 AS other_count
FROM ACL main
JOIN Groups ParentRoles
JOIN $groups_table ParentRoles
ON main.PrincipalId = ParentRoles.id
JOIN $inner_table InnerRecords
ON (ParentRoles.Domain = '$parent_class-Role' AND InnerRecords.$parent_column = ParentRoles.Instance)
OR ParentRoles.Domain = 'RT::System-Role'
JOIN Groups InnerRoles
JOIN $groups_table InnerRoles
ON InnerRoles.Instance = InnerRecords.Id
AND InnerRoles.Name = main.PrincipalType
];
Expand Down
4 changes: 2 additions & 2 deletions lib/RT/Shredder.pm
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ sometimes when you have big mail loops you may hit it.
Defaults to 1000. To change this (for example, to 10000) add the
following to your F<RT_SiteConfig.pm>:
Set( $DependenciesLimit, 10_000 );>
Set( $DependenciesLimit, 10_000 );
=head2 $ShredderStoragePath
Expand All @@ -160,7 +160,7 @@ F</opt/rt5/var/data/RT-Shredder> (assuming an /opt/rt5 installation).
To change this (for example, to /some/backup/path) add the following to
your F<RT_SiteConfig.pm>:
Set( $ShredderStoragePath, "/some/backup/path" );>
Set( $ShredderStoragePath, "/some/backup/path" );
Be sure to specify an absolute path.
Expand Down
16 changes: 10 additions & 6 deletions lib/RT/Test.pm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ my $Test_NoWarnings_Catcher = $SIG{__WARN__};
my $check_warnings_in_end = 1;

use Socket;
use IO::Socket::INET;
use File::Temp qw(tempfile);
use File::Path qw(mkpath);
use File::Spec;
Expand Down Expand Up @@ -262,14 +263,17 @@ sub find_idle_port {
# server binds. However, since we mostly care about race
# conditions with ourselves under high concurrency, this is
# generally good enough.
my $paddr = sockaddr_in( $port, inet_aton('localhost') );
socket( SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp') )
or die "socket: $!";
if ( connect( SOCK, $paddr ) ) {
close(SOCK);

if (! IO::Socket::INET->new(
Listen => SOMAXCONN,
LocalPort => $port,
LocalAddr => '0.0.0.0',
Proto => 'tcp',
ReuseAddr => 1,
)) {
# Port is probably busy.
redo;
}
close(SOCK);
}

$ports{$port}++;
Expand Down
11 changes: 9 additions & 2 deletions sbin/rt-externalize-attachments.in
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ for my $class (qw/RT::Attachments RT::ObjectCustomFieldValues/) {
$attach->{'find_disabled_rows'} = 1;
}

$attach->RowsPerPage(100);
# if using ids arg process them all at once
$attach->RowsPerPage(100) unless $opts{ids};
while ( my $a = $attach->Next and $batchsize > 0) {
$id = $a->id;

Expand Down Expand Up @@ -221,7 +222,13 @@ for my $class (qw/RT::Attachments RT::ObjectCustomFieldValues/) {
}
}

last unless $attach->Count and $batchsize > 0;
# an endless loop was observed when using --ids
# if any one of the ids is for an attachment that will not be externalized
# (perhaps coming from an RT with a smaller ExternalStorageCutoffSize)
# the code would keep looping over the same ids
# the loops also occurs if run using --dry-run and --ids
# the fix is to break out of the loop if --ids was used
last unless !$opts{ids} and $attach->Count and $batchsize > 0;
}
# Do not affect the normal externalize process when handing specific ones
$last->{$class} = $id unless $opts{ids};
Expand Down
9 changes: 9 additions & 0 deletions sbin/rt-validator.in
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Init(
'force',
'verbose|v',
'links-only',
'cgm-only',
);

Pod::Usage::pod2usage( { verbose => 2 } ) unless $opt{check};
Expand Down Expand Up @@ -1330,6 +1331,10 @@ if ($opt{'links-only'}) {
@do_check = grep { /^Links:/ } @do_check;
}

if ($opt{'cgm-only'}) {
@do_check = grep { /^CGM vs/ } @do_check;
}

my $status = 1;
while ( my $check = shift @do_check ) {
$status *= $CHECKS{ $check }->();
Expand Down Expand Up @@ -1670,4 +1675,8 @@ records or resurrect accidentally deleted.

only run the Link validation routines, useful if you changed your Organization

=item cgm-only

only run the CachedGroupMembers validation routines

=back
Loading

0 comments on commit 94aa307

Please sign in to comment.