Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bestpractical/rt.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn M Moore <shawn@bestpractical.com>2017-04-20 00:04:13 +0300
committersunnavy <sunnavy@bestpractical.com>2022-10-19 00:25:59 +0300
commit4598f1a1041c3f2ecb60c2eea6c3a8682665f37d (patch)
tree5b440719823ef898604fce7bb26d489163ba6e5a
parentfa751b05d04d91341e112f40b9fd629aea1b4039 (diff)
Add custom roles to assets
-rw-r--r--lib/RT/Asset.pm44
-rw-r--r--lib/RT/CustomRole.pm25
-rw-r--r--lib/RT/Interface/Web.pm9
-rw-r--r--lib/RT/Principal.pm4
-rw-r--r--lib/RT/Record/Role/Roles.pm6
-rw-r--r--share/html/Asset/Create.html4
-rw-r--r--share/html/Asset/Elements/AssetSearchPeople4
-rw-r--r--share/html/Asset/Elements/EditCatalogPeople4
-rw-r--r--share/html/Asset/Elements/EditPeople13
-rw-r--r--share/html/Asset/Elements/EditRoleMembers9
-rw-r--r--share/html/Asset/Elements/SelectRoleType2
-rw-r--r--share/html/Asset/Elements/ShowPeople4
-rw-r--r--share/html/Asset/Elements/ShowRoleMembers2
13 files changed, 102 insertions, 28 deletions
diff --git a/lib/RT/Asset.pm b/lib/RT/Asset.pm
index e313db5d63..c29e58f67d 100644
--- a/lib/RT/Asset.pm
+++ b/lib/RT/Asset.pm
@@ -101,6 +101,48 @@ for my $role ('Owner', 'HeldBy', 'Contact') {
);
}
+RT::CustomRole->RegisterLookupType(
+ CustomFieldLookupType() => {
+ FriendlyName => 'Assets',
+ CreateGroupPredicate => sub {
+ my ($object, $role) = @_;
+ if ($object->isa('RT::Catalog')) {
+ # In case catalog level custom role groups got deleted
+ # somehow. Allow to re-create them like default ones.
+ return $role->IsAdded($object->id);
+ }
+ elsif ($object->isa('RT::Asset')) {
+ # see if the role has been applied to the asset's catalog
+ # need to walk around ACLs
+ return $role->IsAdded($object->__Value('Catalog'));
+ }
+
+ return 0;
+ },
+ AppliesToObjectPredicate => sub {
+ my ($object, $role) = @_;
+ return 0 unless $object->CurrentUserHasRight('ShowCatalog');
+
+ # custom roles apply to catalogs, so canonicalize an asset
+ # into its catalog
+ if ($object->isa('RT::Asset')) {
+ $object = $object->CatalogObj;
+ }
+
+ if ($object->isa('RT::Catalog')) {
+ return $role->IsAdded($object->Id);
+ }
+
+ return 0;
+ },
+ Subgroup => {
+ Domain => 'RT::Asset-Role',
+ Table => 'Assets',
+ Parent => 'Catalog',
+ },
+ }
+);
+
=head1 DESCRIPTION
An Asset is a small record object upon which zero to many custom fields are
@@ -262,7 +304,7 @@ sub Create {
}
my $roles = {};
- my @errors = $self->_ResolveRoles( $roles, %args );
+ my @errors = $catalog->_ResolveRoles( $roles, %args );
return (0, @errors) if @errors;
RT->DatabaseHandle->BeginTransaction();
diff --git a/lib/RT/CustomRole.pm b/lib/RT/CustomRole.pm
index 077e8bc052..6c8b8b47fa 100644
--- a/lib/RT/CustomRole.pm
+++ b/lib/RT/CustomRole.pm
@@ -278,13 +278,30 @@ sub _ValidateName {
return ($ok, $self->loc("'[_1]' is not a valid name.", $name));
}
- # These roles are builtin, so avoid any potential confusion
- if ($name =~ m{^( cc
+ if ( $type eq 'RT::Queue-RT::Ticket' ) {
+ # These roles are ticket builtin, so avoid any potential confusion
+ if (
+ $name =~ m{^( cc
| admin[ ]?cc
| requestors?
| owner
- ) $}xi) {
- return (undef, $self->loc("Role already exists") );
+ ) $}xi
+ )
+ {
+ return ( undef, $self->loc("Role already exists") );
+ }
+ }
+ else {
+ # These roles are asset builtin, so avoid any potential confusion
+ if (
+ $name =~ m{^( heldby
+ | contacts?
+ | owner
+ ) $}xi
+ )
+ {
+ return ( undef, $self->loc("Role already exists") );
+ }
}
my $temp = RT::CustomRole->new(RT->SystemUser);
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 6e827ffe28..51c6d2fca8 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -4360,11 +4360,16 @@ sub ProcessAssetRoleMembers {
elsif ($arg =~ /^SetRoleMember-(.+)$/) {
my $role = $1;
my $group = $object->RoleGroup($role);
+ if ( !$group->id ) {
+ $group = $object->_CreateRoleGroup($role);
+ }
next unless $group->id and $group->SingleMemberRoleGroup;
- next if $ARGS{$arg} eq $group->UserMembersObj->First->Name;
+ my $original_user = $group->UserMembersObj->First || RT->Nobody;
+ $ARGS{$arg} ||= 'Nobody';
+ next if $ARGS{$arg} eq $original_user->Name;
my ($ok, $msg) = $object->AddRoleMember(
Type => $role,
- User => $ARGS{$arg} || 'Nobody',
+ User => $ARGS{$arg},
);
push @results, $msg;
}
diff --git a/lib/RT/Principal.pm b/lib/RT/Principal.pm
index 27200c3c0f..48ab66e13f 100644
--- a/lib/RT/Principal.pm
+++ b/lib/RT/Principal.pm
@@ -447,7 +447,7 @@ sub HasRights {
if ( $custom_role->id && !$custom_role->Disabled ) {
my $added;
for my $object ( @{ $args{'EquivObjects'} } ) {
- next unless $object->isa('RT::Queue');
+ next unless $object->isa('RT::Queue') || $object->isa('RT::Catalog');
if ( $custom_role->IsAdded( $object->id ) ) {
$added = 1;
last;
@@ -699,7 +699,7 @@ sub RolesWithRight {
if ( $custom_role->id && !$custom_role->Disabled ) {
my $added;
for my $object ( @{ $args{'EquivObjects'} } ) {
- next unless $object->isa('RT::Queue');
+ next unless $object->isa('RT::Queue') || $object->isa('RT::Catalog');
if ( $custom_role->IsAdded( $object->id ) ) {
$added = 1;
last;
diff --git a/lib/RT/Record/Role/Roles.pm b/lib/RT/Record/Role/Roles.pm
index f865d1258e..e4789e22d1 100644
--- a/lib/RT/Record/Role/Roles.pm
+++ b/lib/RT/Record/Role/Roles.pm
@@ -308,9 +308,9 @@ sub Roles {
map { [ $_, $self->_ROLES->{$_} ] }
keys %{ $self->_ROLES };
- # Cache at ticket/queue object level mainly to reduce calls of
- # custom role's AppliesToObjectPredicate for performance.
- if ( ref($self) =~ /RT::(?:Ticket|Queue)/ ) {
+ # Cache at object level mainly to reduce calls of custom role's
+ # AppliesToObjectPredicate for performance.
+ if ( ref($self) =~ /RT::(?:Ticket|Queue|Asset|Catalog)/ ) {
$self->{_Roles}{$key} = \@roles;
}
return @roles;
diff --git a/share/html/Asset/Create.html b/share/html/Asset/Create.html
index f5e91da737..c71526cc61 100644
--- a/share/html/Asset/Create.html
+++ b/share/html/Asset/Create.html
@@ -65,7 +65,7 @@
<div class="col-6">
<&| /Widgets/TitleBox, title => loc("People"), class => "asset-people", title_class => "inverse" &>
- <& Elements/EditPeople, %ARGS, AssetObj => $asset &>
+ <& Elements/EditPeople, %ARGS, AssetObj => $asset, CatalogObj => $catalog &>
</&>
</div>
</div>
@@ -156,7 +156,7 @@ if ($id eq "new") {
ProcessLinksForCreate( ARGSRef => \%ARGS ),
map {
$_ => $ARGS{$_}
- } $asset->Roles,
+ } $catalog->Roles,
);
# Handle basic fields
diff --git a/share/html/Asset/Elements/AssetSearchPeople b/share/html/Asset/Elements/AssetSearchPeople
index fece788d36..32022d0b1a 100644
--- a/share/html/Asset/Elements/AssetSearchPeople
+++ b/share/html/Asset/Elements/AssetSearchPeople
@@ -46,10 +46,10 @@
%#
%# END BPS TAGGED BLOCK }}}
<&| /Widgets/TitleBox, class => "asset-search-people", title => loc('People') &>
-% for my $role (RT::Asset->Roles) {
+% for my $role ($CatalogObj->Roles) {
<div class="asset-role-<% CSSClass($role) %> form-row">
<div class="label col-2">
- <% loc($role) %>
+ <% RT::Asset->LabelForRole($role) %>
</div>
<div class="value col-4">
<input class="form-control" type="text" id="Role.<% $role %>" name="Role.<% $role %>"
diff --git a/share/html/Asset/Elements/EditCatalogPeople b/share/html/Asset/Elements/EditCatalogPeople
index 08c7e00bc7..d52663c439 100644
--- a/share/html/Asset/Elements/EditCatalogPeople
+++ b/share/html/Asset/Elements/EditCatalogPeople
@@ -52,8 +52,8 @@ $Object
</%init>
% for my $role ($Object->Roles( ACLOnly => 0 )) {
<div class="role-<% CSSClass($role) %> role">
- <h3><% loc($role) %></h3>
- <& EditRoleMembers, Group => $Object->RoleGroup($role) &>
+ <h3><% $Object->LabelForRole($role) %></h3>
+ <& EditRoleMembers, Object => $Object, Role => $role &>
</div>
% }
diff --git a/share/html/Asset/Elements/EditPeople b/share/html/Asset/Elements/EditPeople
index 8db9a7f1f9..79120caa6b 100644
--- a/share/html/Asset/Elements/EditPeople
+++ b/share/html/Asset/Elements/EditPeople
@@ -45,12 +45,19 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-% for my $role ( $AssetObj->Roles ) {
- <&| /Elements/LabeledValue, Label => loc($role), Class => "asset-people-".CSSClass($role) &>
- <& /Elements/EmailInput, Name => $role, Size => undef, Default => $ARGS{$role}, Autocomplete => 1, ($AssetObj->Role($role)->{Single} ? () : (AutocompleteType => 'Principals', AutocompleteMultiple => 1)) &>
+% for my $role ( $object->Roles ) {
+% my $custom_role = $object->CustomRoleObj($role);
+% my $hint = $custom_role ? $custom_role->EntryHint : '';
+ <&| /Elements/LabeledValue, Label => $object->LabelForRole($role), Class => "asset-people-".CSSClass($role), LabelTooltip => $hint &>
+ <& /Elements/EmailInput, Name => $role, Size => undef, Default => $ARGS{$role}, Autocomplete => 1, ($object->Role($role)->{Single} ? () : (AutocompleteType => 'Principals', AutocompleteMultiple => 1)) &>
</&>
% }
+<%init>
+my $object = $AssetObj->Id ? $AssetObj : $CatalogObj;
+</%init>
+
<%args>
$AssetObj
+$CatalogObj
</%args>
diff --git a/share/html/Asset/Elements/EditRoleMembers b/share/html/Asset/Elements/EditRoleMembers
index a99b66e322..e0b109529b 100644
--- a/share/html/Asset/Elements/EditRoleMembers
+++ b/share/html/Asset/Elements/EditRoleMembers
@@ -46,17 +46,20 @@
%#
%# END BPS TAGGED BLOCK }}}
<%args>
-$Group => undef
+$Object
+$Role
$Recursively => 0
</%args>
<%init>
+my $Group = $Object->RoleGroup($Role);
my $field_name = "RemoveRoleMember-" . $Group->Name;
</%init>
<ul class="role-members list-group list-group-compact">
% my $Users = $Group->UserMembersObj( Recursively => $Recursively );
-% if ($Group->SingleMemberRoleGroup) {
+% if ($Object->Role($Role)->{Single}) {
+% my $user = $Users->First || RT->Nobody;
<li class="list-group-item">
- <input class="form-control selectpicker" type="text" value="<% $Users->First->Name %>" name="SetRoleMember-<% $Group->Name %>" id="SetRoleMember-<% $Group->Name %>" data-autocomplete="Users" data-autocomplete-return="Name" />
+ <input class="form-control selectpicker" type="text" value="<% $user->Name %>" name="SetRoleMember-<% $Group->Name %>" id="SetRoleMember-<% $Group->Name %>" data-autocomplete="Users" data-autocomplete-return="Name" />
</li>
% } else {
% while ( my $user = $Users->Next ) {
diff --git a/share/html/Asset/Elements/SelectRoleType b/share/html/Asset/Elements/SelectRoleType
index 17f296d813..953232f483 100644
--- a/share/html/Asset/Elements/SelectRoleType
+++ b/share/html/Asset/Elements/SelectRoleType
@@ -55,6 +55,6 @@ $AllowNull => 0
<option value=""></option>
% }
% for my $role ($Object->Roles( ACLOnly => 0, Single => 0 )) {
- <option value="<% $role %>"><% loc($role) %></option>
+ <option value="<% $role %>"><% $Object->LabelForRole($role) %></option>
% }
</select>
diff --git a/share/html/Asset/Elements/ShowPeople b/share/html/Asset/Elements/ShowPeople
index 6b35fdf2e6..fb505decae 100644
--- a/share/html/Asset/Elements/ShowPeople
+++ b/share/html/Asset/Elements/ShowPeople
@@ -54,14 +54,14 @@ my $CatalogObj = $AssetObj->CatalogObj;
% for my $role ($AssetObj->Roles) {
<div class="form-row">
<div class="label col-3">
- <% loc($role) %>:
+ <% $AssetObj->LabelForRole($role) %>:
</div>
<div class="value col-9">
<div class="user-accordion accordion">
% if ($AssetObj->Role($role)->{Single}) {
% my $users = $AssetObj->RoleGroup($role)->UserMembersObj(Recursively => 0);
% $users->FindAllRows;
-% my $user = $users->Next;
+% my $user = $users->Next || RT->Nobody;
% if ( $user->id != RT->Nobody->id ) {
<& ShowRoleMembers, Group => $AssetObj->RoleGroup($role), Role => $role &>
% } else {
diff --git a/share/html/Asset/Elements/ShowRoleMembers b/share/html/Asset/Elements/ShowRoleMembers
index e050b9117e..ab134f2d1a 100644
--- a/share/html/Asset/Elements/ShowRoleMembers
+++ b/share/html/Asset/Elements/ShowRoleMembers
@@ -51,7 +51,7 @@
% next if $user->id == RT->Nobody->id;
<div class="accordion-item">
- <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="#<% $Role %>-user-<% $user->id %>" aria-expanded="false" aria-controls="<% $Role %>-user-<% $user->id %>" id="<% $Role %>-user-<% $user->id %>-title" >
+ <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="[id='<% $Role %>-user-<% $user->id %>']" aria-expanded="false" aria-controls="<% $Role %>-user-<% $user->id %>" id="<% $Role %>-user-<% $user->id %>-title" >
% if ($Title) {
<& /Elements/ShowUser, User => $user, Link => 1 &>