1# -- 2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ 3# -- 4# This software comes with ABSOLUTELY NO WARRANTY. For details, see 5# the enclosed file COPYING for license information (GPL). If you 6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. 7# -- 8 9package Kernel::System::CustomerGroup; 10 11use strict; 12use warnings; 13 14use Kernel::System::VariableCheck qw(:all); 15 16our @ObjectDependencies = ( 17 'Kernel::Config', 18 'Kernel::System::Cache', 19 'Kernel::System::CustomerCompany', 20 'Kernel::System::CustomerGroup', 21 'Kernel::System::CustomerUser', 22 'Kernel::System::DB', 23 'Kernel::System::Group', 24 'Kernel::System::Log', 25 'Kernel::System::Valid', 26); 27 28=head1 NAME 29 30Kernel::System::CustomerGroup - customer group lib 31 32=head1 DESCRIPTION 33 34All customer group functions. E. g. to add groups or to get a member list of a group. 35 36=head1 PUBLIC INTERFACE 37 38=head2 new() 39 40Don't use the constructor directly, use the ObjectManager instead: 41 42 my $CustomerGroupObject = $Kernel::OM->Get('Kernel::System::CustomerGroup'); 43 44=cut 45 46sub new { 47 my ( $Type, %Param ) = @_; 48 49 # allocate new hash for object 50 my $Self = {}; 51 bless( $Self, $Type ); 52 53 $Self->{CacheType} = 'CustomerGroup'; 54 $Self->{CacheTTL} = 60 * 60 * 24 * 20; 55 56 return $Self; 57} 58 59=head2 GroupMemberAdd() 60 61to add a member to a group 62 63 Permission: ro,move_into,priority,create,rw 64 65 my $Success = $CustomerGroupObject->GroupMemberAdd( 66 GID => 12, 67 UID => 6, 68 Permission => { 69 ro => 1, 70 move_into => 1, 71 create => 1, 72 owner => 1, 73 priority => 0, 74 rw => 0, 75 }, 76 UserID => 123, 77 ); 78 79=cut 80 81sub GroupMemberAdd { 82 my ( $Self, %Param ) = @_; 83 84 # check needed stuff 85 for (qw(UID GID UserID Permission)) { 86 if ( !$Param{$_} ) { 87 $Kernel::OM->Get('Kernel::System::Log')->Log( 88 Priority => 'error', 89 Message => "Need $_!", 90 ); 91 return; 92 } 93 } 94 95 # check rw rule (set only rw and remove rest, because it's including all in rw) 96 if ( $Param{Permission}->{rw} ) { 97 $Param{Permission} = { rw => 1 }; 98 } 99 100 # get database object 101 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 102 103 # update permission 104 TYPE: 105 for my $Type ( sort keys %{ $Param{Permission} } ) { 106 107 # delete existing permission 108 $DBObject->Do( 109 SQL => 'DELETE FROM group_customer_user WHERE ' 110 . ' group_id = ? AND user_id = ? AND permission_key = ?', 111 Bind => [ \$Param{GID}, \$Param{UID}, \$Type ], 112 ); 113 114 # debug 115 if ( $Self->{Debug} ) { 116 $Kernel::OM->Get('Kernel::System::Log')->Log( 117 Priority => 'notice', 118 Message => 119 "Add UID:$Param{UID} to GID:$Param{GID}, $Type:$Param{Permission}->{$Type}!", 120 ); 121 } 122 123 # insert new permission (if needed) 124 next TYPE if !$Param{Permission}->{$Type}; 125 126 $DBObject->Do( 127 SQL => 'INSERT INTO group_customer_user ' 128 . '(user_id, group_id, permission_key, permission_value, ' 129 . 'create_time, create_by, change_time, change_by) ' 130 . 'VALUES (?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)', 131 Bind => [ 132 \$Param{UID}, \$Param{GID}, \$Type, \$Param{Permission}->{$Type}, \$Param{UserID}, 133 \$Param{UserID}, 134 ], 135 ); 136 } 137 138 # delete cache 139 # remove complete CustomerGroup cache because 140 # GroupMemberList() cache is CustomerUserID based 141 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 142 Type => $Self->{CacheType}, 143 ); 144 145 return 1; 146} 147 148=head2 GroupMemberList() 149 150Get users of the given group. 151 152 my %Users = $CustomerGroupObject->GroupMemberList( 153 GroupID => '123', 154 Type => 'move_into', # ro|move_into|priority|create|rw 155 Result => 'HASH', # return hash of user id => user name entries 156 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 157 # 1 (return only direct permissions) 158 ); 159 160or 161 162 my @UserIDs = $CustomerGroupObject->GroupMemberList( 163 GroupID => '123', 164 Type => 'move_into', # ro|move_into|priority|create|rw 165 Result => 'ID', # return array of user ids 166 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 167 # 1 (return only direct permissions) 168 ); 169 170or 171 172 my @UserNames = $CustomerGroupObject->GroupMemberList( 173 GroupID => '123', 174 Type => 'move_into', # ro|move_into|priority|create|rw 175 Result => 'Name', # return array of user names 176 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 177 # 1 (return only direct permissions) 178 ); 179 180Get groups of given user. 181 182 my %Groups = $CustomerGroupObject->GroupMemberList( 183 UserID => '123', 184 Type => 'move_into', # ro|move_into|priority|create|rw 185 Result => 'HASH', # return hash of group id => group name entries 186 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 187 # 1 (return only direct permissions) 188 ); 189 190or 191 192 my @GroupIDs = $CustomerGroupObject->GroupMemberList( 193 UserID => '123', 194 Type => 'move_into', # ro|move_into|priority|create|rw 195 Result => 'ID', # return array of group ids 196 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 197 # 1 (return only direct permissions) 198 ); 199 200or 201 202 my @GroupNames = $CustomerGroupObject->GroupMemberList( 203 UserID => '123', 204 Type => 'move_into', # ro|move_into|priority|create|rw 205 Result => 'Name', # return array of group names 206 RawPermissions => 0, # 0 (return inherited permissions from CustomerCompany), default 207 # 1 (return only direct permissions) 208 ); 209 210=cut 211 212sub GroupMemberList { 213 my ( $Self, %Param ) = @_; 214 215 # check needed stuff 216 for my $Needed (qw(Result Type)) { 217 if ( !$Param{$Needed} ) { 218 $Kernel::OM->Get('Kernel::System::Log')->Log( 219 Priority => 'error', 220 Message => "Need $Needed!", 221 ); 222 return; 223 } 224 } 225 if ( !$Param{UserID} && !$Param{GroupID} ) { 226 $Kernel::OM->Get('Kernel::System::Log')->Log( 227 Priority => 'error', 228 Message => 'Need UserID or GroupID!' 229 ); 230 return; 231 } 232 233 # create cache key 234 my $CacheKey = 'GroupMemberList::' . $Param{Type} . '::'; 235 if ( $Param{RawPermissions} ) { 236 $CacheKey .= "Raw::"; 237 } 238 if ( $Param{UserID} ) { 239 $CacheKey .= "UserID::$Param{UserID}"; 240 } 241 else { 242 $CacheKey .= "GroupID::$Param{GroupID}"; 243 } 244 245 # check cache 246 my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get( 247 Type => $Self->{CacheType}, 248 Key => $CacheKey, 249 ); 250 251 if ($Cache) { 252 if ( $Param{Result} eq 'HASH' ) { 253 return %{$Cache}; 254 } 255 elsif ( $Param{Result} eq 'ID' ) { 256 return ( sort keys %{$Cache} ); 257 } 258 elsif ( $Param{Result} eq 'Name' ) { 259 return ( sort values %{$Cache} ); 260 } 261 return; 262 } 263 264 my %Data; 265 266 # check if customer group feature is active, if not, return all groups 267 if ( !$Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupSupport') ) { 268 269 # get permissions 270 %Data = $Kernel::OM->Get('Kernel::System::Group')->GroupList( Valid => 1 ); 271 } 272 else { 273 # get database object 274 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 275 276 # if it's active, return just the permitted groups 277 my $SQL = 278 'SELECT g.id, g.name, gu.permission_key, gu.permission_value, gu.user_id' 279 . ' FROM groups g, group_customer_user gu' 280 . ' WHERE g.valid_id IN ( ' . join ', ', $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet() . ')' 281 . ' AND g.id = gu.group_id AND gu.permission_value = 1' 282 . " AND gu.permission_key IN (?, 'rw')"; 283 my @Bind = ( \$Param{Type} ); 284 285 if ( $Param{UserID} ) { 286 $SQL .= ' AND gu.user_id = ?'; 287 push @Bind, \$Param{UserID}; 288 } 289 else { 290 $SQL .= ' AND gu.group_id = ?'; 291 push @Bind, \$Param{GroupID}; 292 } 293 294 $DBObject->Prepare( 295 SQL => $SQL, 296 Bind => \@Bind, 297 ); 298 299 while ( my @Row = $DBObject->FetchrowArray() ) { 300 if ( $Param{UserID} ) { 301 $Data{ $Row[0] } = $Row[1]; 302 } 303 else { 304 $Data{ $Row[4] } = $Row[1]; 305 } 306 } 307 308 my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser'); 309 310 for my $Key ( sort keys %Data ) { 311 312 # Bugfix #12285 - Check if customer user is valid. 313 if ( $Param{GroupID} ) { 314 315 my %User = $CustomerUserObject->CustomerUserDataGet( 316 User => $Key, 317 ); 318 319 if ( defined $User{ValidID} && $User{ValidID} != 1 ) { 320 delete $Data{$Key}; 321 } 322 } 323 } 324 325 # add customer company groups 326 if ( !$Param{RawPermissions} && $Param{UserID} ) { 327 my @CustomerIDs = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerIDs( 328 User => $Param{UserID}, 329 ); 330 331 for my $CustomerID (@CustomerIDs) { 332 my %CustomerGroups = $Self->GroupCustomerList( 333 CustomerID => $CustomerID, 334 Type => $Param{Type}, 335 Result => 'HASH', 336 ); 337 GROUPID: 338 for my $GroupID ( sort keys %CustomerGroups ) { 339 next GROUPID if $Data{$GroupID}; 340 $Data{$GroupID} = $CustomerGroups{$GroupID}; 341 } 342 } 343 } 344 elsif ( !$Param{RawPermissions} ) { 345 my %CustomerGroups = $Self->GroupCustomerList( 346 GroupID => $Param{GroupID}, 347 Type => $Param{Type}, 348 Result => 'HASH', 349 ); 350 351 my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser'); 352 for my $CustomerID ( sort keys %CustomerGroups ) { 353 my %CustomerUsers = $CustomerUserObject->CustomerSearch( 354 CustomerIDRaw => $CustomerID, 355 Valid => 1, 356 ); 357 CUSTOMERUSERID: 358 for my $CustomerUserID ( sort keys %CustomerUsers ) { 359 next CUSTOMERUSERID if $Data{$CustomerUserID}; 360 $Data{$CustomerUserID} = $CustomerGroups{$CustomerID}; 361 } 362 } 363 } 364 } 365 366 # add always groups if groups are requested 367 if ( 368 $Param{UserID} 369 && $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupAlwaysGroups') 370 ) 371 { 372 my %Groups = $Kernel::OM->Get('Kernel::System::Group')->GroupList( Valid => 1 ); 373 my %GroupsReverse = reverse %Groups; 374 ALWAYSGROUP: 375 for my $AlwaysGroup ( @{ $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupAlwaysGroups') } ) { 376 next ALWAYSGROUP if !$GroupsReverse{$AlwaysGroup}; 377 next ALWAYSGROUP if $Data{ $GroupsReverse{$AlwaysGroup} }; 378 $Data{ $GroupsReverse{$AlwaysGroup} } = $AlwaysGroup; 379 } 380 } 381 382 # set cache 383 $Kernel::OM->Get('Kernel::System::Cache')->Set( 384 Type => $Self->{CacheType}, 385 TTL => $Self->{CacheTTL}, 386 Key => $CacheKey, 387 Value => \%Data, 388 ); 389 390 # return data depending on requested result 391 if ( $Param{Result} eq 'HASH' ) { 392 return %Data; 393 } 394 elsif ( $Param{Result} eq 'ID' ) { 395 return ( sort keys %Data ); 396 } 397 elsif ( $Param{Result} eq 'Name' ) { 398 return ( sort values %Data ); 399 } 400 return; 401} 402 403=head2 GroupCustomerAdd() 404 405to add a customer to a group 406 407 Permission types: e.g. ro,move_into,priority,create,rw 408 Permission context: e.g. Ticket::CustomerID::Same, Ticket::CustomerID::Other 409 410 my $Success = $CustomerGroupObject->GroupCustomerAdd( 411 GID => 12, 412 CustomerID => 'customer-company', 413 Permission => { 414 'Ticket::CustomerID::Same' => { 415 ro => 1, 416 move_into => 1, 417 create => 1, 418 owner => 1, 419 priority => 0, 420 rw => 0, 421 }, 422 'Ticket::CustomerID::Other' => { 423 ro => 1, 424 move_into => 1, 425 create => 1, 426 owner => 1, 427 priority => 0, 428 rw => 0, 429 }, 430 ... 431 }, 432 UserID => 123, 433 ); 434 435=cut 436 437sub GroupCustomerAdd { 438 my ( $Self, %Param ) = @_; 439 440 # check needed stuff 441 for my $Needed (qw(CustomerID GID UserID Permission)) { 442 if ( !$Param{$Needed} ) { 443 $Kernel::OM->Get('Kernel::System::Log')->Log( 444 Priority => 'error', 445 Message => "Need $Needed!", 446 ); 447 return; 448 } 449 } 450 451 # check rw rule (set only rw and remove rest, because it's including all in rw) 452 my @Contexts = $Self->GroupContextNameList(); 453 CONTEXT: 454 for my $Context (@Contexts) { 455 next CONTEXT if !$Param{Permission}->{$Context}->{rw}; 456 $Param{Permission}->{$Context} = { rw => 1 }; 457 } 458 459 # get database object 460 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 461 my $Permissions = $Kernel::OM->Get('Kernel::Config')->Get('System::Customer::Permission'); 462 463 # update permission 464 CONTEXT: 465 for my $Context (@Contexts) { 466 next CONTEXT if !IsHashRefWithData( $Param{Permission}->{$Context} ); 467 468 # delete existing permission 469 $DBObject->Do( 470 SQL => 'DELETE FROM group_customer WHERE ' 471 . ' group_id = ? AND customer_id = ? AND ' 472 . ' permission_context = ?', 473 Bind => [ \$Param{GID}, \$Param{CustomerID}, \$Context ], 474 ); 475 476 # insert new permission (if needed) 477 TYPE: 478 for my $Type ( @{$Permissions} ) { 479 next TYPE if !$Param{Permission}->{$Context}->{$Type}; 480 481 # debug 482 if ( $Self->{Debug} ) { 483 $Kernel::OM->Get('Kernel::System::Log')->Log( 484 Priority => 'notice', 485 Message => 486 "Add CustomerID:$Param{CustomerID} to GID:$Param{GID}, $Type:$Param{Permission}->{$Context}->{$Type}, Context:$Context!", 487 ); 488 } 489 490 $DBObject->Do( 491 SQL => 'INSERT INTO group_customer ' 492 . '(customer_id, group_id, permission_key, permission_value, ' 493 . 'permission_context, create_time, create_by, change_time, change_by) ' 494 . 'VALUES (?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)', 495 Bind => [ 496 \$Param{CustomerID}, \$Param{GID}, \$Type, \$Param{Permission}->{$Context}->{$Type}, 497 \$Context, \$Param{UserID}, \$Param{UserID}, 498 ], 499 ); 500 } 501 } 502 503 # delete cache 504 # remove complete CustomerGroup cache because 505 # it affects GroupMemberList() which is CustomerUserID based 506 $Kernel::OM->Get('Kernel::System::Cache')->CleanUp( 507 Type => $Self->{CacheType}, 508 ); 509 510 return 1; 511} 512 513=head2 GroupCustomerList() 514 515Get customers of the given group. 516 517 my %Customers = $CustomerGroupObject->GroupCustomerList( 518 GroupID => '123', 519 Type => 'ro', # ro|move_into|priority|create|owner|rw 520 Context => 'Ticket::CustomerID::Same', 521 # permissions to same company tickets, default context 522 Result => 'HASH', # return hash of customer id => group name entries 523 ); 524 525or 526 527 my @CustomerIDs = $CustomerGroupObject->GroupCustomerList( 528 GroupID => '123', 529 Type => 'ro', # ro|move_into|priority|create|owner|rw 530 Context => 'Ticket::CustomerID::Same', 531 # permissions to same company tickets, default context 532 Result => 'ID', # return array of customer ids 533 ); 534 535or 536 537 my @CustomerNames = $CustomerGroupObject->GroupCustomerList( 538 GroupID => '123', 539 Type => 'ro', # ro|move_into|priority|create|owner|rw 540 Context => 'Ticket::CustomerID::Same', 541 # permissions to same company tickets, default context 542 Result => 'Name', # return array of customer ids 543 ); 544 545Get groups of given customer. 546 547 my %Groups = $CustomerGroupObject->GroupCustomerList( 548 CustomerID => '123', 549 Type => 'ro', # ro|move_into|priority|create|owner|rw 550 Context => 'Ticket::CustomerID::Same', 551 # permissions to same company tickets, default context 552 Result => 'HASH', # return hash of group id => group name entries 553 ); 554 555or 556 557 my @GroupIDs = $CustomerGroupObject->GroupCustomerList( 558 CustomerID => '123', 559 Type => 'ro', # ro|move_into|priority|create|owner|rw 560 Context => 'Ticket::CustomerID::Same', 561 # permissions to same company tickets, default context 562 Result => 'ID', # return array of group ids 563 ); 564 565or 566 567 my @GroupNames = $CustomerGroupObject->GroupCustomerList( 568 CustomerID => '123', 569 Type => 'ro', # ro|move_into|priority|create|owner|rw 570 Context => 'Ticket::CustomerID::Same', 571 # permissions to same company tickets, default context 572 Result => 'Name', # return array of group names 573 ); 574 575=cut 576 577sub GroupCustomerList { 578 my ( $Self, %Param ) = @_; 579 580 # check needed stuff 581 for my $Needed (qw(Result Type)) { 582 if ( !$Param{$Needed} ) { 583 $Kernel::OM->Get('Kernel::System::Log')->Log( 584 Priority => 'error', 585 Message => "Need $Needed!", 586 ); 587 return; 588 } 589 } 590 if ( !$Param{CustomerID} && !$Param{GroupID} ) { 591 $Kernel::OM->Get('Kernel::System::Log')->Log( 592 Priority => 'error', 593 Message => 'Need CustomerID or GroupID!', 594 ); 595 return; 596 } 597 598 # fallback to the default context 599 if ( !$Param{Context} ) { 600 $Param{Context} = $Self->GroupContextNameGet( 601 SysConfigName => '001-CustomerID-same', 602 ); 603 } 604 605 # create cache key 606 my $CacheKey = 'GroupCustomerList::' . $Param{Type} . '::' . $Param{Context} . '::'; 607 if ( $Param{CustomerID} ) { 608 $CacheKey .= 'CustomerID::' . $Param{CustomerID}; 609 } 610 else { 611 $CacheKey .= 'GroupID::' . $Param{GroupID}; 612 } 613 614 # check cache 615 my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get( 616 Type => $Self->{CacheType}, 617 Key => $CacheKey, 618 ); 619 if ($Cache) { 620 if ( $Param{Result} eq 'HASH' ) { 621 return %{$Cache}; 622 } 623 elsif ( $Param{Result} eq 'ID' ) { 624 return ( sort keys %{$Cache} ); 625 } 626 elsif ( $Param{Result} eq 'Name' ) { 627 return ( sort values %{$Cache} ); 628 } 629 return; 630 } 631 632 my %Data; 633 634 # check if customer group feature is active, if not, return all groups 635 if ( !$Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupSupport') ) { 636 637 # get permissions 638 %Data = $Kernel::OM->Get('Kernel::System::Group')->GroupList( Valid => 1 ); 639 } 640 else { 641 # get database object 642 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 643 644 # if it's active, return just the permitted groups 645 my $SQL = 646 'SELECT g.id, g.name, gc.permission_key, gc.permission_value, gc.customer_id' 647 . ' FROM groups g, group_customer gc' 648 . ' WHERE g.valid_id IN ( ' . join ', ', $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet() . ')' 649 . ' AND g.id = gc.group_id AND gc.permission_value = 1' 650 . " AND gc.permission_key IN (?, 'rw')" 651 . ' AND gc.permission_context = ?'; 652 my @Bind = ( \$Param{Type}, \$Param{Context} ); 653 654 if ( $Param{CustomerID} ) { 655 $SQL .= ' AND gc.customer_id = ?'; 656 push @Bind, \$Param{CustomerID}; 657 } 658 else { 659 $SQL .= ' AND gc.group_id = ?'; 660 push @Bind, \$Param{GroupID}; 661 } 662 $DBObject->Prepare( 663 SQL => $SQL, 664 Bind => \@Bind, 665 ); 666 while ( my @Row = $DBObject->FetchrowArray() ) { 667 if ( $Param{CustomerID} ) { 668 $Data{ $Row[0] } = $Row[1]; 669 } 670 else { 671 $Data{ $Row[4] } = $Row[1]; 672 } 673 } 674 } 675 676 # add always groups if groups are requested 677 # don't add them for non-default context (same CustomerID permission) requests 678 my $DefaultContextName = $Self->GroupContextNameGet( 679 SysConfigName => '001-CustomerID-same', 680 ); 681 if ( 682 $Param{CustomerID} 683 && $Param{Context} eq $DefaultContextName 684 && $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupCompanyAlwaysGroups') 685 ) 686 { 687 my %Groups = $Kernel::OM->Get('Kernel::System::Group')->GroupList( Valid => 1 ); 688 my %GroupsReverse = reverse %Groups; 689 ALWAYSGROUP: 690 for my $AlwaysGroup ( @{ $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupCompanyAlwaysGroups') } ) { 691 next ALWAYSGROUP if !$GroupsReverse{$AlwaysGroup}; 692 next ALWAYSGROUP if $Data{ $GroupsReverse{$AlwaysGroup} }; 693 $Data{ $GroupsReverse{$AlwaysGroup} } = $AlwaysGroup; 694 } 695 } 696 697 # set cache 698 $Kernel::OM->Get('Kernel::System::Cache')->Set( 699 Type => $Self->{CacheType}, 700 TTL => $Self->{CacheTTL}, 701 Key => $CacheKey, 702 Value => \%Data, 703 ); 704 705 # return data depending on requested result 706 if ( $Param{Result} eq 'HASH' ) { 707 return %Data; 708 } 709 elsif ( $Param{Result} eq 'ID' ) { 710 return ( sort keys %Data ); 711 } 712 elsif ( $Param{Result} eq 'Name' ) { 713 return ( sort values %Data ); 714 } 715 return; 716} 717 718=head2 GroupContextNameGet() 719 720Helper function to get currently configured name of a specific group access context 721 722 my $ContextName = $CustomerGroupObject->GroupContextNameGet( 723 SysConfigName => '100-CustomerID-other', # optional, defaults to '001-CustomerID-same' 724 ); 725 726=cut 727 728sub GroupContextNameGet { 729 my ( $Self, %Param ) = @_; 730 731 # get config name 732 # fallback to 'normal' group permission config 733 $Param{SysConfigName} ||= '001-CustomerID-same'; 734 735 my $ContextConfig = $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupPermissionContext'); 736 return if !IsHashRefWithData($ContextConfig); 737 return if !IsHashRefWithData( $ContextConfig->{ $Param{SysConfigName} } ); 738 739 return $ContextConfig->{ $Param{SysConfigName} }->{Value}; 740} 741 742=head2 GroupContextNameList() 743 744Helper function to get the names of all configured group access contexts 745 746 my @ContextNames = $CustomerGroupObject->GroupContextNameList(); 747 748=cut 749 750sub GroupContextNameList { 751 my ( $Self, %Param ) = @_; 752 753 my $ContextConfig = $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupPermissionContext'); 754 return () if !IsHashRefWithData($ContextConfig); 755 756 # fill list 757 my @ContextNames; 758 CONTEXT: 759 for my $Item ( sort keys %{$ContextConfig} ) { 760 next CONTEXT if !IsHashRefWithData( $ContextConfig->{$Item} ); 761 next CONTEXT if !$ContextConfig->{$Item}->{Value}; 762 763 push @ContextNames, $ContextConfig->{$Item}->{Value}; 764 } 765 766 return @ContextNames; 767} 768 769=head2 GroupContextCustomers() 770 771Get all customer companies of the given customer user, 772including those associated via context based permissions. 773 774 my %Customers = $CustomerGroupObject->GroupContextCustomers( 775 CustomerUserID => '123', 776 ); 777 778Returns hash with Customer IDs as key and Customer Company Name as value: 779 780 %Customers = { 781 '001' => 'Customer Company 1', 782 '002' => 'Customer Company 2', 783 }; 784 785=cut 786 787sub GroupContextCustomers { 788 my ( $Self, %Param ) = @_; 789 790 # check needed stuff 791 if ( !$Param{CustomerUserID} ) { 792 $Kernel::OM->Get('Kernel::System::Log')->Log( 793 Priority => 'error', 794 Message => 'Need CustomerUserID!', 795 ); 796 return; 797 } 798 799 # no cache is used because of too many factors outside our control 800 801 # get customer ids from backend 802 my @CustomerIDs = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerIDs( 803 User => $Param{CustomerUserID}, 804 ); 805 806 # check for access to other CustomerIDs via group assignment 807 # add all combinations based on context bases group access 808 my $ExtraPermissionContext = $Self->GroupContextNameGet( 809 SysConfigName => '100-CustomerID-other', 810 ); 811 if ( 812 $Kernel::OM->Get('Kernel::Config')->Get('CustomerGroupSupport') 813 && $ExtraPermissionContext 814 ) 815 { 816 817 # for all CustomerIDs get groups with extra access 818 my %ExtraPermissionGroups; 819 CUSTOMERID: 820 for my $CustomerID (@CustomerIDs) { 821 my %GroupList = $Self->GroupCustomerList( 822 CustomerID => $CustomerID, 823 Type => 'ro', 824 Context => $ExtraPermissionContext, 825 Result => 'HASH', 826 ); 827 next CUSTOMERID if !%GroupList; 828 829 # add to groups 830 %ExtraPermissionGroups = ( 831 %ExtraPermissionGroups, 832 %GroupList, 833 ); 834 } 835 836 # add all accessible CustomerIDs 837 GROUPID: 838 for my $GroupID ( sort keys %ExtraPermissionGroups ) { 839 my @ExtraCustomerIDs = $Self->GroupCustomerList( 840 GroupID => $GroupID, 841 Type => 'ro', 842 Result => 'ID', 843 ); 844 next GROUPID if !@ExtraCustomerIDs; 845 846 # add to CustomerIDs 847 push @CustomerIDs, @ExtraCustomerIDs; 848 } 849 } 850 851 # get all customer companies for quick name lookup 852 my %AllCustomers = $Kernel::OM->Get('Kernel::System::CustomerCompany')->CustomerCompanyList( 853 Valid => 1, 854 Limit => 0, 855 ); 856 857 # filter results using valid customers, add customer name to results 858 my %Customers; 859 CUSTOMERID: 860 for my $CustomerID (@CustomerIDs) { 861 next CUSTOMERID if !$AllCustomers{$CustomerID}; 862 next CUSTOMERID if $Customers{$CustomerID}; 863 $Customers{$CustomerID} = $AllCustomers{$CustomerID}; 864 } 865 866 return %Customers; 867} 868 869=head2 GroupLookup() 870 871get id or name for group 872 873 my $Group = $CustomerGroupObject->GroupLookup(GroupID => $GroupID); 874 875 my $GroupID = $CustomerGroupObject->GroupLookup(Group => $Group); 876 877=cut 878 879sub GroupLookup { 880 my ( $Self, %Param ) = @_; 881 882 # check needed stuff 883 if ( !$Param{Group} && !$Param{GroupID} ) { 884 $Kernel::OM->Get('Kernel::System::Log')->Log( 885 Priority => 'error', 886 Message => 'Got no Group or GroupID!', 887 ); 888 return; 889 } 890 891 # check if result is cached 892 my $CacheKey; 893 if ( $Param{GroupID} ) { 894 $CacheKey = "GroupLookup::ID::$Param{GroupID}"; 895 } 896 elsif ( $Param{Group} ) { 897 $CacheKey = "GroupLookup::Name::$Param{Group}"; 898 } 899 900 my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get( 901 Type => $Self->{CacheType}, 902 Key => $CacheKey, 903 ); 904 return ${$Cache} if ( ref $Cache eq 'SCALAR' ); 905 906 # get database object 907 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 908 909 # get data 910 my $SQL; 911 my @Bind; 912 my $Suffix; 913 if ( $Param{Group} ) { 914 $Param{What} = $Param{Group}; 915 $Suffix = 'GroupID'; 916 $SQL = 'SELECT id FROM groups WHERE name = ?'; 917 push @Bind, \$Param{Group}; 918 } 919 else { 920 $Param{What} = $Param{GroupID}; 921 $Suffix = 'Group'; 922 $SQL = 'SELECT name FROM groups WHERE id = ?'; 923 push @Bind, \$Param{GroupID}; 924 } 925 return if !$DBObject->Prepare( 926 SQL => $SQL, 927 Bind => \@Bind, 928 ); 929 930 my $Result; 931 while ( my @Row = $DBObject->FetchrowArray() ) { 932 933 # store result 934 $Result = $Row[0]; 935 } 936 937 # check if data exists 938 if ( !$Result ) { 939 $Kernel::OM->Get('Kernel::System::Log')->Log( 940 Priority => 'error', 941 Message => "Found no \$$Suffix for $Param{What}!", 942 ); 943 return; 944 } 945 946 # set cache 947 $Kernel::OM->Get('Kernel::System::Cache')->Set( 948 Type => $Self->{CacheType}, 949 TTL => $Self->{CacheTTL}, 950 Key => $CacheKey, 951 Value => \$Result, 952 ); 953 954 return $Result; 955} 956 957=head2 PermissionCheck() 958 959Check if a customer user has a certain permission for a certain group. 960 961 my $HasPermission = $CustomerGroupObject->PermissionCheck( 962 UserID => $UserID, 963 GroupName => $GroupName, 964 Type => 'move_into', 965 ); 966 967=cut 968 969sub PermissionCheck { 970 my ( $Self, %Param ) = @_; 971 972 # check needed stuff 973 for (qw(UserID GroupName Type)) { 974 if ( !$Param{$_} ) { 975 $Kernel::OM->Get('Kernel::System::Log')->Log( 976 Priority => 'error', 977 Message => "Need $_!", 978 ); 979 return; 980 } 981 } 982 983 my %GroupMemberList = reverse $Self->GroupMemberList( 984 UserID => $Param{UserID}, 985 Type => $Param{Type}, 986 Result => 'HASH', 987 ); 988 989 return $GroupMemberList{ $Param{GroupName} } ? 1 : 0; 990} 991 9921; 993 994=head1 TERMS AND CONDITIONS 995 996This software is part of the OTRS project (L<https://otrs.org/>). 997 998This software comes with ABSOLUTELY NO WARRANTY. For details, see 999the enclosed file COPYING for license information (GPL). If you 1000did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 1001 1002=cut 1003