diff options
author | Shawn M Moore <shawn@bestpractical.com> | 2017-04-20 00:04:13 +0300 |
---|---|---|
committer | sunnavy <sunnavy@bestpractical.com> | 2022-10-19 00:25:59 +0300 |
commit | 4598f1a1041c3f2ecb60c2eea6c3a8682665f37d (patch) | |
tree | 5b440719823ef898604fce7bb26d489163ba6e5a | |
parent | fa751b05d04d91341e112f40b9fd629aea1b4039 (diff) |
Add custom roles to assets
-rw-r--r-- | lib/RT/Asset.pm | 44 | ||||
-rw-r--r-- | lib/RT/CustomRole.pm | 25 | ||||
-rw-r--r-- | lib/RT/Interface/Web.pm | 9 | ||||
-rw-r--r-- | lib/RT/Principal.pm | 4 | ||||
-rw-r--r-- | lib/RT/Record/Role/Roles.pm | 6 | ||||
-rw-r--r-- | share/html/Asset/Create.html | 4 | ||||
-rw-r--r-- | share/html/Asset/Elements/AssetSearchPeople | 4 | ||||
-rw-r--r-- | share/html/Asset/Elements/EditCatalogPeople | 4 | ||||
-rw-r--r-- | share/html/Asset/Elements/EditPeople | 13 | ||||
-rw-r--r-- | share/html/Asset/Elements/EditRoleMembers | 9 | ||||
-rw-r--r-- | share/html/Asset/Elements/SelectRoleType | 2 | ||||
-rw-r--r-- | share/html/Asset/Elements/ShowPeople | 4 | ||||
-rw-r--r-- | share/html/Asset/Elements/ShowRoleMembers | 2 |
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 &> |