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::OTRSBusiness; 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::CloudService::Backend::Run', 20 'Kernel::System::DynamicField', 21 'Kernel::System::DynamicField::Backend', 22 'Kernel::System::Log', 23 'Kernel::System::DateTime', 24 'Kernel::System::DB', 25 'Kernel::System::Package', 26 'Kernel::System::SystemData', 27); 28 29=head1 NAME 30 31Kernel::System::OTRSBusiness - OTRSBusiness deployment backend 32 33=head1 PUBLIC INTERFACE 34 35=head2 new() 36 37create an object. Do not use it directly, instead use: 38 39 use Kernel::System::ObjectManager; 40 local $Kernel::OM = Kernel::System::ObjectManager->new(); 41 my $RegistrationObject = $Kernel::OM->Get('Kernel::System::OTRSBusiness'); 42 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->{APIVersion} = 1; 54 55 # Get config object 56 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 57 58 # Get OTRSBusiness::ReleaseChannel from SysConfig (Stable = 1, Development = 0) 59 $Self->{OnlyStable} = $ConfigObject->Get('OTRSBusiness::ReleaseChannel') // 1; 60 61 # Set cache params 62 $Self->{CacheType} = 'OTRSBusiness'; 63 $Self->{CacheTTL} = 60 * 60 * 24 * 30; # 30 days 64 65 # Check if cloud services are disabled 66 $Self->{CloudServicesDisabled} = $ConfigObject->Get('CloudServices::Disabled') || 0; 67 68 # If we cannot connect to cloud.otrs.com for more than the second period, show an error. 69 $Self->{NoConnectErrorPeriod} = 60 * 60 * 24 * 15; # 15 days 70 71 # If we cannot connect to cloud.otrs.com for more than the second period, block the system. 72 $Self->{NoConnectBlockPeriod} = 60 * 60 * 24 * 25; # 25 days 73 74 # If the contract is about to expire in less than this time, show a hint 75 $Self->{ContractExpiryWarningPeriod} = 60 * 60 * 24 * 28; # 28 days 76 77 return $Self; 78} 79 80=head2 OTRSBusinessIsInstalled() 81 82checks if OTRSBusiness is installed in the current system. 83That does not necessarily mean that it is also active, for 84example if the package is only on the database but not on 85the file system. 86 87=cut 88 89sub OTRSBusinessIsInstalled { 90 my ( $Self, %Param ) = @_; 91 92 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 93 94 # as the check for installed packages can be 95 # very expensive, we want to use caching here 96 my $Cache = $CacheObject->Get( 97 Type => $Self->{CacheType}, 98 TTL => $Self->{CacheTTL}, 99 Key => 'OTRSBusinessIsInstalled', 100 ); 101 102 return $Cache if defined $Cache; 103 104 my $IsInstalled = $Self->_GetOTRSBusinessPackageFromRepository() ? 1 : 0; 105 106 # set cache 107 $CacheObject->Set( 108 Type => $Self->{CacheType}, 109 TTL => $Self->{CacheTTL}, 110 Key => 'OTRSBusinessIsInstalled', 111 Value => $IsInstalled, 112 ); 113 114 return $IsInstalled; 115} 116 117=head2 OTRSSTORMIsInstalled() 118 119checks if OTRSStorm is installed in the current system. 120That does not necessarily mean that it is also active, for 121example if the package is only on the database but not on 122the file system. 123 124=cut 125 126sub OTRSSTORMIsInstalled { 127 my ( $Self, %Param ) = @_; 128 129 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 130 131 # as the check for installed packages can be 132 # very expensive, we want to use caching here 133 my $Cache = $CacheObject->Get( 134 Type => $Self->{CacheType}, 135 TTL => $Self->{CacheTTL}, 136 Key => 'OTRSSTORMIsInstalled', 137 ); 138 139 return $Cache if defined $Cache; 140 141 my $IsInstalled = $Self->_GetSTORMPackageFromRepository() ? 1 : 0; 142 143 # set cache 144 $CacheObject->Set( 145 Type => $Self->{CacheType}, 146 TTL => $Self->{CacheTTL}, 147 Key => 'OTRSSTORMIsInstalled', 148 Value => $IsInstalled, 149 ); 150 151 return $IsInstalled; 152} 153 154=head2 OTRSCONTROLIsInstalled() 155 156checks if OTRSControl is installed in the current system. 157That does not necessarily mean that it is also active, for 158example if the package is only on the database but not on 159the file system. 160 161=cut 162 163sub OTRSCONTROLIsInstalled { 164 my ( $Self, %Param ) = @_; 165 166 my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache'); 167 168 # as the check for installed packages can be 169 # very expensive, we want to use caching here 170 my $Cache = $CacheObject->Get( 171 Type => $Self->{CacheType}, 172 TTL => $Self->{CacheTTL}, 173 Key => 'OTRSCONTROLIsInstalled', 174 ); 175 176 return $Cache if defined $Cache; 177 178 my $IsInstalled = $Self->_GetCONTROLPackageFromRepository() ? 1 : 0; 179 180 # set cache 181 $CacheObject->Set( 182 Type => $Self->{CacheType}, 183 TTL => $Self->{CacheTTL}, 184 Key => 'OTRSCONTROLIsInstalled', 185 Value => $IsInstalled, 186 ); 187 188 return $IsInstalled; 189} 190 191=head2 OTRSBusinessIsAvailable() 192 193checks with C<cloud.otrs.com> if OTRSBusiness is available for the current framework. 194 195=cut 196 197sub OTRSBusinessIsAvailable { 198 my ( $Self, %Param ) = @_; 199 200 return if $Self->{CloudServicesDisabled}; 201 202 my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run'); 203 my $RequestResult = $CloudServiceObject->Request( 204 RequestData => { 205 OTRSBusiness => [ 206 { 207 Operation => 'BusinessVersionCheck', 208 Data => { 209 OnlyStable => $Self->{OnlyStable}, 210 }, 211 }, 212 ], 213 }, 214 ); 215 216 my $OperationResult; 217 if ( IsHashRefWithData($RequestResult) ) { 218 $OperationResult = $CloudServiceObject->OperationResultGet( 219 RequestResult => $RequestResult, 220 CloudService => 'OTRSBusiness', 221 Operation => 'BusinessVersionCheck', 222 ); 223 224 if ( $OperationResult->{Success} ) { 225 $Self->HandleBusinessVersionCheckCloudServiceResult( 226 OperationResult => $OperationResult, 227 ); 228 229 if ( $OperationResult->{Data}->{LatestVersionForCurrentFramework} ) { 230 return 1; 231 } 232 } 233 } 234 return; 235} 236 237=head2 OTRSBusinessIsAvailableOffline() 238 239retrieves the latest result of the BusinessVersionCheck cloud service 240that was stored in the system_data table. 241 242returns 1 if available. 243 244=cut 245 246sub OTRSBusinessIsAvailableOffline { 247 my ( $Self, %Param ) = @_; 248 249 my %BusinessVersionCheck = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet( 250 Group => 'OTRSBusiness', 251 ); 252 253 return $BusinessVersionCheck{LatestVersionForCurrentFramework} ? 1 : 0; 254} 255 256=head2 OTRSBusinessIsCorrectlyDeployed() 257 258checks if the OTRSBusiness package is correctly 259deployed or if it needs to be reinstalled. 260 261=cut 262 263sub OTRSBusinessIsCorrectlyDeployed { 264 my ( $Self, %Param ) = @_; 265 266 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 267 268 # Package not found -> return failure 269 return if !$Package; 270 271 # first check the regular way if the files are present and the package 272 # itself is installed correctly 273 return if !$Kernel::OM->Get('Kernel::System::Package')->DeployCheck( 274 Name => $Package->{Name}->{Content}, 275 Version => $Package->{Version}->{Content}, 276 ); 277 278 # check if all tables have been created correctly 279 # we can't rely on any .opm file here, so we just check 280 # the list of tables manually 281 my $DBObject = $Kernel::OM->Get('Kernel::System::DB'); 282 283 TABLES: 284 for my $Table (qw(chat chat_participant chat_message)) { 285 286 # if a table does not exist, $TablePresent will be 'undef' for this table 287 my $TablePresent = $DBObject->Do( 288 SQL => "SELECT * FROM $Table", 289 Limit => 1, 290 ); 291 292 return if !$TablePresent; 293 } 294 295 return 1; 296} 297 298=head2 OTRSBusinessIsReinstallable() 299 300checks if the OTRSBusiness package can be reinstalled 301(if it supports the current framework version). If not, 302an update might be needed. 303 304=cut 305 306sub OTRSBusinessIsReinstallable { 307 my ( $Self, %Param ) = @_; 308 309 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 310 311 # Package not found -> return failure 312 return if !$Package; 313 314 my %Check = $Kernel::OM->Get('Kernel::System::Package')->AnalyzePackageFrameworkRequirements( 315 Framework => $Package->{Framework}, 316 ); 317 return $Check{Success}; 318} 319 320=head2 OTRSBusinessIsUpdateable() 321 322checks with C<cloud.otrs.com> if the OTRSBusiness package is available in a newer version 323than the one currently installed. The result of this check will be stored in the 324system_data table for offline usage. 325 326=cut 327 328sub OTRSBusinessIsUpdateable { 329 my ( $Self, %Param ) = @_; 330 331 return 0 if $Self->{CloudServicesDisabled}; 332 333 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 334 return if !$Package; 335 336 my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run'); 337 my $RequestResult = $CloudServiceObject->Request( 338 RequestData => { 339 OTRSBusiness => [ 340 { 341 Operation => 'BusinessVersionCheck', 342 Data => { 343 OnlyStable => $Self->{OnlyStable}, 344 }, 345 }, 346 ], 347 }, 348 ); 349 350 my $OperationResult; 351 if ( IsHashRefWithData($RequestResult) ) { 352 $OperationResult = $CloudServiceObject->OperationResultGet( 353 RequestResult => $RequestResult, 354 CloudService => 'OTRSBusiness', 355 Operation => 'BusinessVersionCheck', 356 ); 357 358 if ( $OperationResult && $OperationResult->{Success} ) { 359 360 $Self->HandleBusinessVersionCheckCloudServiceResult( OperationResult => $OperationResult ); 361 362 if ( $OperationResult->{Data}->{LatestVersionForCurrentFramework} ) { 363 return $Kernel::OM->Get('Kernel::System::Package')->_CheckVersion( 364 VersionNew => $OperationResult->{Data}->{LatestVersionForCurrentFramework}, 365 VersionInstalled => $Package->{Version}->{Content}, 366 Type => 'Max', 367 ); 368 } 369 } 370 } 371 372 return 0; 373} 374 375=head2 OTRSBusinessVersionCheckOffline() 376 377retrieves the latest result of the BusinessVersionCheck cloud service 378that was stored in the system_data table. 379 380 my %Result = $OTRSBusinessObject->OTRSBusinessVersionCheckOffline(); 381 382returns 383 384 $Result = ( 385 OTRSBusinessUpdateAvailable => 1, # if applicable 386 FrameworkUpdateAvailable => 1, # if applicable 387 ); 388 389=cut 390 391sub OTRSBusinessVersionCheckOffline { 392 my ( $Self, %Param ) = @_; 393 394 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 395 396 return if !$Package; 397 398 my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet( 399 Group => 'OTRSBusiness', 400 ); 401 402 my %Result = ( 403 FrameworkUpdateAvailable => $EntitlementData{FrameworkUpdateAvailable} // '', 404 ); 405 406 if ( $EntitlementData{LatestVersionForCurrentFramework} ) { 407 $Result{OTRSBusinessUpdateAvailable} = $Kernel::OM->Get('Kernel::System::Package')->_CheckVersion( 408 VersionNew => $EntitlementData{LatestVersionForCurrentFramework}, 409 VersionInstalled => $Package->{Version}->{Content}, 410 Type => 'Max', 411 ); 412 } 413 414 return %Result; 415} 416 417=head2 OTRSBusinessGetDependencies() 418 419checks if there are any active dependencies on OTRSBusiness. 420 421=cut 422 423sub OTRSBusinessGetDependencies { 424 my ( $Self, %Param ) = @_; 425 426 my @Packages = $Kernel::OM->Get('Kernel::System::Package')->RepositoryList(); 427 428 my @DependentPackages; 429 PACKAGE: 430 for my $Package (@Packages) { 431 432 next PACKAGE if !IsHashRefWithData($Package); 433 next PACKAGE if !IsArrayRefWithData( $Package->{PackageRequired} ); 434 435 DEPENDENCY: 436 for my $Dependency ( @{ $Package->{PackageRequired} } ) { 437 438 next DEPENDENCY if !IsHashRefWithData($Dependency); 439 next DEPENDENCY if !$Dependency->{Content}; 440 next DEPENDENCY if $Dependency->{Content} ne 'OTRSBusiness'; 441 442 push @DependentPackages, { 443 Name => $Package->{Name}->{Content}, 444 Vendor => $Package->{Vendor}->{Content}, 445 Version => $Package->{Version}->{Content}, 446 Description => $Package->{Description}, 447 }; 448 449 last DEPENDENCY; 450 } 451 } 452 453 return \@DependentPackages; 454} 455 456=head2 OTRSBusinessEntitlementCheck() 457 458determines the OTRSBusiness entitlement status of this system as reported by C<cloud.otrs.com> 459and stores it in the system_data cache. 460 461Returns 1 if the cloud call was successful. 462 463=cut 464 465sub OTRSBusinessEntitlementCheck { 466 my ( $Self, %Param ) = @_; 467 468 # If OTRSSTORM package is installed, system is able to do a Cloud request even if CloudService is disabled. 469 if ( 470 !$Self->OTRSSTORMIsInstalled() 471 && $Self->{CloudServicesDisabled} 472 ) 473 { 474 return; 475 } 476 477 my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run'); 478 my $RequestResult = $CloudServiceObject->Request( 479 RequestData => { 480 OTRSBusiness => [ 481 { 482 Operation => 'BusinessPermission', 483 Data => {}, 484 }, 485 ], 486 }, 487 ); 488 489 my $OperationResult; 490 if ( IsHashRefWithData($RequestResult) ) { 491 $OperationResult = $CloudServiceObject->OperationResultGet( 492 RequestResult => $RequestResult, 493 CloudService => 'OTRSBusiness', 494 Operation => 'BusinessPermission', 495 ); 496 } 497 498 # OK, so we got a successful cloud call result. Then we will use it and remember it. 499 if ( IsHashRefWithData($OperationResult) && $OperationResult->{Success} ) { 500 501 # Store it in the SystemData so that it is also available for the notification modules, 502 # even before the first run of RegistrationUpdate. 503 $Self->HandleBusinessPermissionCloudServiceResult( 504 OperationResult => $OperationResult, 505 ); 506 return 1; 507 } 508 509 if ( !IsHashRefWithData($RequestResult) || !$RequestResult->{Success} ) { 510 my $Message = "BusinessPermission - Can't contact cloud.otrs.com server"; 511 $Kernel::OM->Get('Kernel::System::Log')->Log( 512 Priority => 'error', 513 Message => $Message 514 ); 515 } 516 517 if ( !IsHashRefWithData($OperationResult) || !$OperationResult->{Success} ) { 518 my $Message = "BusinessPermission - could not perform BusinessPermission check"; 519 if ( IsHashRefWithData($OperationResult) ) { 520 $Message .= $OperationResult->{ErrorMessage}; 521 } 522 $Kernel::OM->Get('Kernel::System::Log')->Log( 523 Priority => 'error', 524 Message => $Message 525 ); 526 } 527 528 return 0; 529} 530 531=head2 OTRSBusinessEntitlementStatus() 532 533Returns the current entitlement status. 534 535 my $Status = $OTRSBusinessObject->OTRSBusinessEntitlementStatus( 536 CallCloudService => 1, # 0 or 1, call the cloud service before looking at the cache 537 ); 538 539 $Status = 'entitled'; # everything is OK 540 $Status = 'warning'; # last check was OK, and we are in the waiting period - show warning 541 $Status = 'warning-error'; # last check was OK, and we are past waiting period - show error message 542 $Status = 'forbidden'; # not entitled (either because the server said so or because the last check was too long ago) 543 544=cut 545 546sub OTRSBusinessEntitlementStatus { 547 my ( $Self, %Param ) = @_; 548 549 # If the system is not registered, it cannot have an OB permission. 550 # Also, the BusinessPermissionChecks will not work any more, so the permission 551 # would expire after our waiting period. But in this case we can immediately deny 552 # the permission. 553 my $RegistrationState = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGet( 554 Key => 'Registration::State', 555 ); 556 if ( !$RegistrationState || $RegistrationState ne 'registered' ) { 557 return 'forbidden'; 558 } 559 560 # Cloud service is called and if cannot be connected, it must return 'forbidden'. 561 if ( $Param{CallCloudService} ) { 562 my $Check = $Self->OTRSBusinessEntitlementCheck(); 563 return 'forbidden' if $Check == 0; 564 } 565 566 # OK. Let's look at the system_data cache now and use it if appropriate 567 my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet( 568 Group => 'OTRSBusiness', 569 ); 570 571 if ( !%EntitlementData || !$EntitlementData{BusinessPermission} ) { 572 return 'forbidden'; 573 } 574 575 # Check when the last successful BusinessPermission check was made. 576 my $DateTimeObject = $Kernel::OM->Create( 577 'Kernel::System::DateTime', 578 ObjectParams => { 579 String => $EntitlementData{LastUpdateTime}, 580 }, 581 ); 582 583 my $Delta = $Kernel::OM->Create('Kernel::System::DateTime')->Delta( 584 DateTimeObject => $DateTimeObject, 585 ); 586 587 if ( $Delta->{AbsoluteSeconds} > $Self->{NoConnectBlockPeriod} ) { 588 return 'forbidden'; 589 } 590 if ( $Delta->{AbsoluteSeconds} > $Self->{NoConnectErrorPeriod} ) { 591 return 'warning-error'; 592 } 593 594 # If we cannot connect to cloud.otrs.com for more than the first period, show a warning. 595 my $NoConnectWarningPeriod = 60 * 60 * 24 * 5; # 5 days 596 if ( $Self->OTRSSTORMIsInstalled() ) { 597 $NoConnectWarningPeriod = 60 * 60 * 24 * 10; # 10 days 598 } 599 600 if ( $Delta->{AbsoluteSeconds} > $NoConnectWarningPeriod ) { 601 return 'warning'; 602 } 603 604 return 'entitled'; 605} 606 607=head2 OTRSBusinessContractExpiryDateCheck() 608 609checks for the warning period before the contract expires 610 611 my $ExpiryDate = $OTRSBusinessObject->OTRSBusinessContractExpiryDateCheck(); 612 613returns the ExpiryDate if a warning should be displayed 614 615 $ExpiryDate = undef; # everything is OK, no warning 616 $ExpiryDate = '2012-12-12 12:12:12' # contract is about to expire, issue warning 617 618=cut 619 620sub OTRSBusinessContractExpiryDateCheck { 621 my ( $Self, %Param ) = @_; 622 623 if ( $Param{CallCloudService} ) { 624 $Self->OTRSBusinessEntitlementCheck(); 625 } 626 627 # OK. Let's look at the system_data cache now and use it if appropriate 628 my %EntitlementData = $Kernel::OM->Get('Kernel::System::SystemData')->SystemDataGroupGet( 629 Group => 'OTRSBusiness', 630 ); 631 632 if ( !%EntitlementData || !$EntitlementData{ExpiryDate} ) { 633 return; 634 } 635 636 my $ExpiryDateTimeObj = $Kernel::OM->Create( 637 'Kernel::System::DateTime', 638 ObjectParams => { 639 String => $EntitlementData{ExpiryDate}, 640 } 641 ); 642 643 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 644 645 my $Delta = $ExpiryDateTimeObj->Delta( 646 DateTimeObject => $DateTimeObject 647 ); 648 649 if ( $Delta->{AbsoluteSeconds} < $Self->{ContractExpiryWarningPeriod} ) { 650 return $EntitlementData{ExpiryDate}; 651 } 652 653 return; 654} 655 656sub HandleBusinessPermissionCloudServiceResult { 657 my ( $Self, %Param ) = @_; 658 659 my $OperationResult = $Param{OperationResult}; 660 661 return if !$OperationResult->{Success}; 662 663 # We store the current time as LastUpdateTime so that we know when the last 664 # permission check could be successfully made with the server. This is needed 665 # to determine if the results can still be used later, if a connection to 666 # cloud.otrs.com cannot be made temporarily. 667 my %StoreData = ( 668 BusinessPermission => $OperationResult->{Data}->{BusinessPermission} // 0, 669 ExpiryDate => $OperationResult->{Data}->{ExpiryDate} // '', 670 LastUpdateTime => $Kernel::OM->Create('Kernel::System::DateTime')->ToString(), 671 AgentSessionLimit => $OperationResult->{Data}->{AgentSessionLimit} // 0, 672 AgentSessionLimitPriorWarning => $OperationResult->{Data}->{AgentSessionLimitPriorWarning} // 0, 673 ); 674 675 my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData'); 676 677 KEY: 678 for my $Key ( sort keys %StoreData ) { 679 next KEY if !defined $StoreData{$Key}; 680 681 my $FullKey = 'OTRSBusiness::' . $Key; 682 683 if ( defined $SystemDataObject->SystemDataGet( Key => $FullKey ) ) { 684 $SystemDataObject->SystemDataUpdate( 685 Key => $FullKey, 686 Value => $StoreData{$Key}, 687 UserID => 1, 688 ); 689 } 690 else { 691 $SystemDataObject->SystemDataAdd( 692 Key => $FullKey, 693 Value => $StoreData{$Key}, 694 UserID => 1, 695 ); 696 } 697 } 698 699 return 1; 700} 701 702sub HandleBusinessVersionCheckCloudServiceResult { 703 my ( $Self, %Param ) = @_; 704 705 my $OperationResult = $Param{OperationResult}; 706 707 return if !$OperationResult->{Success}; 708 709 my %StoreData = ( 710 LatestVersionForCurrentFramework => $OperationResult->{Data}->{LatestVersionForCurrentFramework} // '', 711 FrameworkUpdateAvailable => $OperationResult->{Data}->{FrameworkUpdateAvailable} // '', 712 ); 713 714 my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData'); 715 716 for my $Key ( sort keys %StoreData ) { 717 my $FullKey = 'OTRSBusiness::' . $Key; 718 719 if ( defined $SystemDataObject->SystemDataGet( Key => $FullKey ) ) { 720 $SystemDataObject->SystemDataUpdate( 721 Key => $FullKey, 722 Value => $StoreData{$Key}, 723 UserID => 1, 724 ); 725 } 726 else { 727 $SystemDataObject->SystemDataAdd( 728 Key => $FullKey, 729 Value => $StoreData{$Key}, 730 UserID => 1, 731 ); 732 } 733 } 734 735 return 1; 736} 737 738sub _OTRSBusinessFileGet { 739 my ( $Self, %Param ) = @_; 740 741 return if $Self->{CloudServicesDisabled}; 742 743 my $CloudServiceObject = $Kernel::OM->Get('Kernel::System::CloudService::Backend::Run'); 744 my $RequestResult = $CloudServiceObject->Request( 745 RequestData => { 746 OTRSBusiness => [ 747 { 748 Operation => 'BusinessFileGet', 749 Data => { 750 OnlyStable => $Self->{OnlyStable}, 751 }, 752 }, 753 ], 754 }, 755 ); 756 757 my $OperationResult; 758 if ( IsHashRefWithData($RequestResult) ) { 759 $OperationResult = $CloudServiceObject->OperationResultGet( 760 RequestResult => $RequestResult, 761 CloudService => 'OTRSBusiness', 762 Operation => 'BusinessFileGet', 763 ); 764 765 if ( $OperationResult->{Success} && $OperationResult->{Data}->{Package} ) { 766 return $OperationResult->{Data}->{Package}; 767 } 768 } 769 770 return; 771} 772 773=head2 OTRSBusinessInstall() 774 775downloads and installs OTRSBusiness. 776 777=cut 778 779sub OTRSBusinessInstall { 780 my ( $Self, %Param ) = @_; 781 782 my %Response = ( 783 Success => 0, 784 ); 785 786 my $PackageString = $Self->_OTRSBusinessFileGet(); 787 return %Response if !$PackageString; 788 789 my $PackageObject = $Kernel::OM->Get('Kernel::System::Package'); 790 791 # Parse package structure. 792 my %Structure = $PackageObject->PackageParse( 793 String => $PackageString, 794 FromCloud => 1, 795 ); 796 797 my %FrameworkCheck = $PackageObject->AnalyzePackageFrameworkRequirements( 798 Framework => $Structure{Framework}, 799 NoLog => 1, 800 ); 801 802 if ( !$FrameworkCheck{Success} ) { 803 $FrameworkCheck{ShowBlock} = 'IncompatibleInfo'; 804 return %FrameworkCheck; 805 } 806 807 my $Install = $Kernel::OM->Get('Kernel::System::Package')->PackageInstall( 808 String => $PackageString, 809 FromCloud => 1, 810 ); 811 812 return %Response if !$Install; 813 814 # now that we know that OTRSBusiness has been installed, 815 # we can just preset the cache instead of just swiping it. 816 $Kernel::OM->Get('Kernel::System::Cache')->Set( 817 Type => $Self->{CacheType}, 818 TTL => $Self->{CacheTTL}, 819 Key => 'OTRSBusinessIsInstalled', 820 Value => 1, 821 ); 822 823 $Response{Success} = 1; 824 825 return %Response; 826} 827 828=head2 OTRSBusinessReinstall() 829 830re-installs OTRSBusiness from local repository. 831 832=cut 833 834sub OTRSBusinessReinstall { 835 my ( $Self, %Param ) = @_; 836 837 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 838 839 # Package not found -> return failure 840 return if !$Package; 841 842 my $PackageString = $Kernel::OM->Get('Kernel::System::Package')->RepositoryGet( 843 Name => $Package->{Name}->{Content}, 844 Version => $Package->{Version}->{Content}, 845 ); 846 847 return $Kernel::OM->Get('Kernel::System::Package')->PackageReinstall( 848 String => $PackageString, 849 ); 850} 851 852=head2 OTRSBusinessUpdate() 853 854downloads and updates OTRSBusiness. 855 856=cut 857 858sub OTRSBusinessUpdate { 859 my ( $Self, %Param ) = @_; 860 861 my %Response = ( 862 Success => 0, 863 ); 864 my $PackageString = $Self->_OTRSBusinessFileGet(); 865 return if !$PackageString; 866 867 my $PackageObject = $Kernel::OM->Get('Kernel::System::Package'); 868 869 # Parse package structure. 870 my %Structure = $PackageObject->PackageParse( 871 String => $PackageString, 872 FromCloud => 1, 873 ); 874 875 my %FrameworkCheck = $PackageObject->AnalyzePackageFrameworkRequirements( 876 Framework => $Structure{Framework}, 877 NoLog => 1, 878 ); 879 880 if ( !$FrameworkCheck{Success} ) { 881 $FrameworkCheck{ShowBlock} = 'IncompatibleInfo'; 882 return %FrameworkCheck; 883 } 884 885 my $Upgrade = $Kernel::OM->Get('Kernel::System::Package')->PackageUpgrade( 886 String => $PackageString, 887 FromCloud => 1, 888 ); 889 890 return %Response if !$Upgrade; 891 892 $Response{Success} = 1; 893 return %Response; 894} 895 896=head2 OTRSBusinessUninstall() 897 898removes OTRSBusiness from the system. 899 900=cut 901 902sub OTRSBusinessUninstall { 903 my ( $Self, %Param ) = @_; 904 905 my $Package = $Self->_GetOTRSBusinessPackageFromRepository(); 906 907 # Package not found -> return failure 908 return if !$Package; 909 910 # TODO: the following code is now Deprecated and should be removed in further versions of OTRS 911 # get a list of all dynamic fields for ticket and article 912 my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField'); 913 my $DynamicFieldList = $DynamicFieldObject->DynamicFieldListGet( 914 Valid => 0, 915 ObjectType => [ 'Ticket', 'Article' ], 916 ); 917 918 # filter only dynamic fields added by OTRSBusiness 919 my %OTRSBusinessDynamicFieldTypes = ( 920 ContactWithData => 1, 921 Database => 1, 922 ); 923 924 my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend'); 925 926 DYNAMICFIELD: 927 for my $DynamicFieldConfig ( @{$DynamicFieldList} ) { 928 next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig); 929 next DYNAMICFIELD if !$OTRSBusinessDynamicFieldTypes{ $DynamicFieldConfig->{FieldType} }; 930 931 # remove data from the field 932 my $ValuesDeleteSuccess = $DynamicFieldBackendObject->AllValuesDelete( 933 DynamicFieldConfig => $DynamicFieldConfig, 934 UserID => 1, 935 ); 936 937 if ( !$ValuesDeleteSuccess ) { 938 $Kernel::OM->Get('Kernel::System::Log')->Log( 939 Priority => 'error', 940 Message => "Values from dynamic field $DynamicFieldConfig->{Name} could not be deleted!", 941 ); 942 } 943 944 my $Success = $DynamicFieldObject->DynamicFieldDelete( 945 ID => $DynamicFieldConfig->{ID}, 946 UserID => 1, 947 Reorder => 1, 948 ); 949 950 if ( !$Success ) { 951 $Kernel::OM->Get('Kernel::System::Log')->Log( 952 Priority => 'error', 953 Message => "Dynamic field $DynamicFieldConfig->{Name} could not be deleted!", 954 ); 955 } 956 } 957 958 # TODO: end Deprecated 959 960 my $PackageString = $Kernel::OM->Get('Kernel::System::Package')->RepositoryGet( 961 Name => $Package->{Name}->{Content}, 962 Version => $Package->{Version}->{Content}, 963 ); 964 965 my $Uninstall = $Kernel::OM->Get('Kernel::System::Package')->PackageUninstall( 966 String => $PackageString, 967 ); 968 969 return $Uninstall if !$Uninstall; 970 971 # now that we know that OTRSBusiness has been uninstalled, 972 # we can just preset the cache instead of just swiping it. 973 $Kernel::OM->Get('Kernel::System::Cache')->Set( 974 Type => $Self->{CacheType}, 975 TTL => $Self->{CacheTTL}, 976 Key => 'OTRSBusinessIsInstalled', 977 Value => 0, 978 ); 979 980 return $Uninstall; 981} 982 983=head2 OTRSBusinessCommandNextUpdateTimeSet() 984 985Set the next update time for the given command in the system data table storage. 986 987 my $Success = $OTRSBusinessObject->OTRSBusinessCommandNextUpdateTimeSet( 988 Command => 'AvailabilityCheck', 989 ); 990 991Returns 1 if the next update time was set successfully. 992 993=cut 994 995sub OTRSBusinessCommandNextUpdateTimeSet { 996 my ( $Self, %Param ) = @_; 997 998 return if !$Param{Command}; 999 1000 my $Key = "OTRSBusiness::$Param{Command}::NextUpdateTime"; 1001 1002 my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData'); 1003 1004 my $NextUpdateTime = $SystemDataObject->SystemDataGet( 1005 Key => $Key, 1006 ); 1007 1008 # set the default next update seconds offset 1009 my $NextUpdateSecondsOffset = 60 * 60 * 24; 1010 1011 # generate a random seconds offset, if no next update time exists 1012 if ( !$NextUpdateTime ) { 1013 1014 # create the random numbers 1015 my $RandomHour = int 20 + rand 23 - 20; 1016 my $RandomMinute = int rand 60; 1017 1018 # create the random seconds offset 1019 $NextUpdateSecondsOffset = 60 * 60 * $RandomHour + ( 60 * $RandomMinute ); 1020 } 1021 1022 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1023 $DateTimeObject->Add( Seconds => $NextUpdateSecondsOffset ); 1024 my $CalculatedNextUpdateTime = $DateTimeObject->ToString(); 1025 1026 if ( defined $NextUpdateTime ) { 1027 $SystemDataObject->SystemDataUpdate( 1028 Key => $Key, 1029 Value => $CalculatedNextUpdateTime, 1030 UserID => 1, 1031 ); 1032 } 1033 else { 1034 $SystemDataObject->SystemDataAdd( 1035 Key => $Key, 1036 Value => $CalculatedNextUpdateTime, 1037 UserID => 1, 1038 ); 1039 } 1040 1041 return 1; 1042} 1043 1044sub _GetOTRSBusinessPackageFromRepository { 1045 my ( $Self, %Param ) = @_; 1046 1047 my $PackageObject = $Kernel::OM->Get('Kernel::System::Package'); 1048 1049 my @RepositoryList = $PackageObject->RepositoryList(); 1050 1051 for my $Package (@RepositoryList) { 1052 return $Package if $Package->{Name}->{Content} eq 'OTRSBusiness'; 1053 } 1054 1055 return; 1056} 1057 1058sub _GetSTORMPackageFromRepository { 1059 my ( $Self, %Param ) = @_; 1060 1061 my $PackageObject = $Kernel::OM->Get('Kernel::System::Package'); 1062 1063 my @RepositoryList = $PackageObject->RepositoryList( 1064 Result => 'short', 1065 ); 1066 1067 for my $Package (@RepositoryList) { 1068 1069 return $Package if $Package->{Name} eq 'OTRSSTORM'; 1070 } 1071 1072 return; 1073} 1074 1075sub _GetCONTROLPackageFromRepository { 1076 my ( $Self, %Param ) = @_; 1077 1078 my $PackageObject = $Kernel::OM->Get('Kernel::System::Package'); 1079 1080 my @RepositoryList = $PackageObject->RepositoryList( 1081 Result => 'short', 1082 ); 1083 1084 for my $Package (@RepositoryList) { 1085 1086 return $Package if $Package->{Name} eq 'OTRSCONTROL'; 1087 } 1088 1089 return; 1090} 1091 10921; 1093 1094=head1 TERMS AND CONDITIONS 1095 1096This software is part of the OTRS project (L<https://otrs.org/>). 1097 1098This software comes with ABSOLUTELY NO WARRANTY. For details, see 1099the enclosed file COPYING for license information (GPL). If you 1100did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 1101 1102=cut 1103