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::Web::InterfaceCustomer; 10 11use strict; 12use warnings; 13 14use Kernel::System::DateTime; 15use Kernel::System::Email; 16use Kernel::System::VariableCheck qw(IsArrayRefWithData IsHashRefWithData); 17use Kernel::Language qw(Translatable); 18 19our @ObjectDependencies = ( 20 'Kernel::Config', 21 'Kernel::Output::HTML::Layout', 22 'Kernel::System::AuthSession', 23 'Kernel::System::CustomerAuth', 24 'Kernel::System::CustomerGroup', 25 'Kernel::System::CustomerUser', 26 'Kernel::System::DB', 27 'Kernel::System::Group', 28 'Kernel::System::Log', 29 'Kernel::System::Main', 30 'Kernel::System::Scheduler', 31 'Kernel::System::DateTime', 32 'Kernel::System::Web::Request', 33 'Kernel::System::Valid', 34); 35 36=head1 NAME 37 38Kernel::System::Web::InterfaceCustomer - the customer web interface 39 40=head1 DESCRIPTION 41 42the global customer web interface (authentication, session handling, ...) 43 44=head1 PUBLIC INTERFACE 45 46=head2 new() 47 48create customer web interface object 49 50 use Kernel::System::Web::InterfaceCustomer; 51 52 my $Debug = 0; 53 my $InterfaceCustomer = Kernel::System::Web::InterfaceCustomer->new( 54 Debug => $Debug, 55 WebRequest => CGI::Fast->new(), # optional, e. g. if fast cgi is used, the CGI object is already provided 56 ); 57 58=cut 59 60sub new { 61 my ( $Type, %Param ) = @_; 62 63 # allocate new hash for object 64 my $Self = {}; 65 bless( $Self, $Type ); 66 67 # get debug level 68 $Self->{Debug} = $Param{Debug} || 0; 69 70 # performance log 71 $Self->{PerformanceLogStart} = time(); 72 73 $Kernel::OM->ObjectParamAdd( 74 'Kernel::System::Log' => { 75 LogPrefix => $Kernel::OM->Get('Kernel::Config')->Get('CGILogPrefix'), 76 }, 77 'Kernel::System::Web::Request' => { 78 WebRequest => $Param{WebRequest} || 0, 79 }, 80 ); 81 82 # debug info 83 if ( $Self->{Debug} ) { 84 $Kernel::OM->Get('Kernel::System::Log')->Log( 85 Priority => 'debug', 86 Message => 'Global handle started...', 87 ); 88 } 89 90 return $Self; 91} 92 93=head2 Run() 94 95execute the object 96 97 $InterfaceCustomer->Run(); 98 99=cut 100 101sub Run { 102 my $Self = shift; 103 104 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 105 106 my $QueryString = $ENV{QUERY_STRING} || ''; 107 108 # Check if https forcing is active, and redirect if needed. 109 if ( $ConfigObject->Get('HTTPSForceRedirect') ) { 110 111 # Some web servers do not set HTTPS environment variable, so it's not possible to easily know if we are using 112 # https protocol. Look also for similarly named keys in environment hash, since this should prevent loops in 113 # certain cases. 114 if ( 115 ( 116 !defined $ENV{HTTPS} 117 && !grep {/^HTTPS(?:_|$)/} keys %ENV 118 ) 119 || $ENV{HTTPS} ne 'on' 120 ) 121 { 122 my $Host = $ENV{HTTP_HOST} || $ConfigObject->Get('FQDN'); 123 124 # Redirect with 301 code. Add two new lines at the end, so HTTP headers are validated correctly. 125 print "Status: 301 Moved Permanently\nLocation: https://$Host$ENV{REQUEST_URI}\n\n"; 126 return; 127 } 128 } 129 130 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 131 132 my %Param; 133 134 # get session id 135 $Param{SessionName} = $ConfigObject->Get('CustomerPanelSessionName') || 'CSID'; 136 $Param{SessionID} = $ParamObject->GetParam( Param => $Param{SessionName} ) || ''; 137 138 # drop old session id (if exists) 139 $QueryString =~ s/(\?|&|;|)$Param{SessionName}(=&|=;|=.+?&|=.+?$)/;/g; 140 141 # define framework params 142 my $FrameworkParams = { 143 Lang => '', 144 Action => '', 145 Subaction => '', 146 RequestedURL => $QueryString, 147 }; 148 for my $Key ( sort keys %{$FrameworkParams} ) { 149 $Param{$Key} = $ParamObject->GetParam( Param => $Key ) 150 || $FrameworkParams->{$Key}; 151 } 152 153 # validate language 154 if ( $Param{Lang} && $Param{Lang} !~ m{\A[a-z]{2}(?:_[A-Z]{2})?\z}xms ) { 155 delete $Param{Lang}; 156 } 157 158 my $BrowserHasCookie = 0; 159 160 # Check if the browser sends the SessionID cookie and set the SessionID-cookie 161 # as SessionID! GET or POST SessionID have the lowest priority. 162 if ( $ConfigObject->Get('SessionUseCookie') ) { 163 $Param{SessionIDCookie} = $ParamObject->GetCookie( Key => $Param{SessionName} ); 164 if ( $Param{SessionIDCookie} ) { 165 $Param{SessionID} = $Param{SessionIDCookie}; 166 } 167 } 168 169 my $CookieSecureAttribute; 170 if ( $ConfigObject->Get('HttpType') eq 'https' ) { 171 172 # Restrict Cookie to HTTPS if it is used. 173 $CookieSecureAttribute = 1; 174 } 175 176 $Kernel::OM->ObjectParamAdd( 177 'Kernel::Output::HTML::Layout' => { 178 Lang => $Param{Lang}, 179 }, 180 'Kernel::Language' => { 181 UserLanguage => $Param{Lang}, 182 }, 183 ); 184 185 my $DBCanConnect = $Kernel::OM->Get('Kernel::System::DB')->Connect(); 186 187 if ( !$DBCanConnect || $ParamObject->Error() ) { 188 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 189 if ( !$DBCanConnect ) { 190 $LayoutObject->CustomerFatalError( 191 Comment => Translatable('Please contact the administrator.'), 192 ); 193 return; 194 } 195 if ( $ParamObject->Error() ) { 196 $LayoutObject->CustomerFatalError( 197 Message => $ParamObject->Error(), 198 Comment => Translatable('Please contact the administrator.'), 199 ); 200 return; 201 } 202 } 203 204 my $UserObject = $Kernel::OM->Get('Kernel::System::CustomerUser'); 205 my $SessionObject = $Kernel::OM->Get('Kernel::System::AuthSession'); 206 207 # get common application and add on application params 208 my %CommonObjectParam = %{ $ConfigObject->Get('CustomerFrontend::CommonParam') }; 209 for my $Key ( sort keys %CommonObjectParam ) { 210 $Param{$Key} = $ParamObject->GetParam( Param => $Key ) || $CommonObjectParam{$Key}; 211 } 212 213 # security check Action Param (replace non-word chars) 214 $Param{Action} =~ s/\W//g; 215 216 # check request type 217 if ( $Param{Action} eq 'PreLogin' ) { 218 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 219 220 # login screen 221 $LayoutObject->Print( 222 Output => \$LayoutObject->CustomerLogin( 223 Title => 'Login', 224 Mode => 'PreLogin', 225 %Param, 226 ), 227 ); 228 229 return; 230 } 231 elsif ( $Param{Action} eq 'Login' ) { 232 233 # get params 234 my $PostUser = $ParamObject->GetParam( Param => 'User' ) || ''; 235 my $PostPw = $ParamObject->GetParam( 236 Param => 'Password', 237 Raw => 1 238 ) || ''; 239 my $PostTwoFactorToken = $ParamObject->GetParam( 240 Param => 'TwoFactorToken', 241 Raw => 1 242 ) || ''; 243 244 # create AuthObject 245 my $AuthObject = $Kernel::OM->Get('Kernel::System::CustomerAuth'); 246 247 # check submitted data 248 my $User = $AuthObject->Auth( 249 User => $PostUser, 250 Pw => $PostPw, 251 TwoFactorToken => $PostTwoFactorToken, 252 ); 253 254 my $Expires = '+' . $ConfigObject->Get('SessionMaxTime') . 's'; 255 if ( !$ConfigObject->Get('SessionUseCookieAfterBrowserClose') ) { 256 $Expires = ''; 257 } 258 259 # login is invalid 260 if ( !$User ) { 261 $Kernel::OM->ObjectParamAdd( 262 'Kernel::Output::HTML::Layout' => { 263 SetCookies => { 264 OTRSBrowserHasCookie => $ParamObject->SetCookie( 265 Key => 'OTRSBrowserHasCookie', 266 Value => 1, 267 Expires => $Expires, 268 Path => $ConfigObject->Get('ScriptAlias'), 269 Secure => $CookieSecureAttribute, 270 HTTPOnly => 1, 271 ), 272 }, 273 }, 274 ); 275 276 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 277 278 # redirect to alternate login 279 if ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 280 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 281 print $LayoutObject->Redirect( 282 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 283 . "?Reason=LoginFailed;RequestedURL=$Param{RequestedURL}", 284 ); 285 return; 286 } 287 288 # show normal login 289 $LayoutObject->Print( 290 Output => \$LayoutObject->CustomerLogin( 291 Title => 'Login', 292 Message => $Kernel::OM->Get('Kernel::System::Log')->GetLogEntry( 293 Type => 'Info', 294 What => 'Message', 295 ) 296 || $AuthObject->GetLastErrorMessage() 297 || Translatable('Login failed! Your user name or password was entered incorrectly.'), 298 User => $PostUser, 299 LoginFailed => 1, 300 %Param, 301 ), 302 ); 303 return; 304 } 305 306 # login is successful 307 my %UserData = $UserObject->CustomerUserDataGet( 308 User => $User, 309 Valid => 1 310 ); 311 312 # check if the browser supports cookies 313 if ( $ParamObject->GetCookie( Key => 'OTRSBrowserHasCookie' ) ) { 314 $Kernel::OM->ObjectParamAdd( 315 'Kernel::Output::HTML::Layout' => { 316 BrowserHasCookie => 1, 317 }, 318 ); 319 } 320 321 # check needed data 322 if ( !$UserData{UserID} || !$UserData{UserLogin} ) { 323 324 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 325 326 # redirect to alternate login 327 if ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 328 print $LayoutObject->Redirect( 329 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 330 . '?Reason=SystemError', 331 ); 332 return; 333 } 334 335 # show need user data error message 336 $LayoutObject->Print( 337 Output => \$LayoutObject->CustomerLogin( 338 Title => 'Error', 339 Message => Translatable( 340 'Authentication succeeded, but no customer record is found in the customer backend. Please contact the administrator.' 341 ), 342 %Param, 343 ), 344 ); 345 return; 346 } 347 348 # create datetime object 349 my $SessionDTObject = $Kernel::OM->Create('Kernel::System::DateTime'); 350 351 # Remove certain user attributes that are not needed to be stored in the session. 352 # - SMIME Certificate could be in binary format, if session backend in DB (default) 353 # it wont be possible to be saved in certain databases (see bug#14405). 354 my %UserSessionData = %UserData; 355 delete $UserSessionData{UserSMIMECertificate}; 356 357 # create new session id 358 my $NewSessionID = $SessionObject->CreateSessionID( 359 %UserSessionData, 360 UserLastRequest => $SessionDTObject->ToEpoch(), 361 UserType => 'Customer', 362 SessionSource => 'CustomerInterface', 363 ); 364 365 # show error message if no session id has been created 366 if ( !$NewSessionID ) { 367 368 # get error message 369 my $Error = $SessionObject->SessionIDErrorMessage() || ''; 370 371 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 372 373 # output error message 374 $LayoutObject->Print( 375 Output => \$LayoutObject->CustomerLogin( 376 Title => 'Login', 377 Message => $Error, 378 %Param, 379 ), 380 ); 381 return; 382 } 383 384 # execution in 20 seconds 385 my $ExecutionTimeObj = $Kernel::OM->Create('Kernel::System::DateTime'); 386 $ExecutionTimeObj->Add( Seconds => 20 ); 387 388 # add a asynchronous executor scheduler task to count the concurrent user 389 $Kernel::OM->Get('Kernel::System::Scheduler')->TaskAdd( 390 ExecutionTime => $ExecutionTimeObj->ToString(), 391 Type => 'AsynchronousExecutor', 392 Name => 'PluginAsynchronous::ConcurrentUser', 393 MaximumParallelInstances => 1, 394 Data => { 395 Object => 'Kernel::System::SupportDataCollector::PluginAsynchronous::OTRS::ConcurrentUsers', 396 Function => 'RunAsynchronous', 397 }, 398 ); 399 400 my $UserTimeZone = $Self->_UserTimeZoneGet(%UserData); 401 402 $SessionObject->UpdateSessionID( 403 SessionID => $NewSessionID, 404 Key => 'UserTimeZone', 405 Value => $UserTimeZone, 406 ); 407 408 # check if the time zone offset reported by the user's browser differs from that 409 # of the OTRS user's time zone offset 410 my $DateTimeObject = $Kernel::OM->Create( 411 'Kernel::System::DateTime', 412 ObjectParams => { 413 TimeZone => $UserTimeZone, 414 }, 415 ); 416 my $OTRSUserTimeZoneOffset = $DateTimeObject->Format( Format => '%{offset}' ) / 60; 417 my $BrowserTimeZoneOffset = ( $ParamObject->GetParam( Param => 'TimeZoneOffset' ) || 0 ) * -1; 418 419 # TimeZoneOffsetDifference contains the difference of the time zone offset between 420 # the user's OTRS time zone setting and the one reported by the user's browser. 421 # If there is a difference it can be evaluated later to e. g. show a message 422 # for the user to check his OTRS time zone setting. 423 my $UserTimeZoneOffsetDifference = abs( $OTRSUserTimeZoneOffset - $BrowserTimeZoneOffset ); 424 $SessionObject->UpdateSessionID( 425 SessionID => $NewSessionID, 426 Key => 'UserTimeZoneOffsetDifference', 427 Value => $UserTimeZoneOffsetDifference, 428 ); 429 430 $Kernel::OM->ObjectParamAdd( 431 'Kernel::Output::HTML::Layout' => { 432 SetCookies => { 433 SessionIDCookie => $ParamObject->SetCookie( 434 Key => $Param{SessionName}, 435 Value => $NewSessionID, 436 Expires => $Expires, 437 Path => $ConfigObject->Get('ScriptAlias'), 438 Secure => scalar $CookieSecureAttribute, 439 HTTPOnly => 1, 440 ), 441 OTRSBrowserHasCookie => $ParamObject->SetCookie( 442 Key => 'OTRSBrowserHasCookie', 443 Value => '', 444 Expires => '-1y', 445 Path => $ConfigObject->Get('ScriptAlias'), 446 Secure => $CookieSecureAttribute, 447 HTTPOnly => 1, 448 ), 449 450 }, 451 SessionID => $NewSessionID, 452 SessionName => $Param{SessionName}, 453 }, 454 ); 455 456 # redirect with new session id and old params 457 # prepare old redirect URL -- do not redirect to Login or Logout (loop)! 458 if ( $Param{RequestedURL} =~ /Action=(Logout|Login|LostPassword|PreLogin)/ ) { 459 $Param{RequestedURL} = ''; 460 } 461 462 # redirect with new session id 463 print $Kernel::OM->Get('Kernel::Output::HTML::Layout')->Redirect( 464 OP => $Param{RequestedURL}, 465 Login => 1, 466 ); 467 return 1; 468 } 469 470 # logout 471 elsif ( $Param{Action} eq 'Logout' ) { 472 473 # check session id 474 if ( !$SessionObject->CheckSessionID( SessionID => $Param{SessionID} ) ) { 475 476 # new layout object 477 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 478 479 # redirect to alternate login 480 if ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 481 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 482 print $LayoutObject->Redirect( 483 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 484 . "?Reason=InvalidSessionID;RequestedURL=$Param{RequestedURL}", 485 ); 486 } 487 488 # show login screen 489 print $LayoutObject->CustomerLogin( 490 Title => 'Logout', 491 Message => Translatable('Session invalid. Please log in again.'), 492 %Param, 493 ); 494 return; 495 } 496 497 # get session data 498 my %UserData = $SessionObject->GetSessionIDData( 499 SessionID => $Param{SessionID}, 500 ); 501 502 $UserData{UserTimeZone} = $Self->_UserTimeZoneGet(%UserData); 503 504 # create new LayoutObject with new '%Param' and '%UserData' 505 $Kernel::OM->ObjectParamAdd( 506 'Kernel::Output::HTML::Layout' => { 507 SetCookies => { 508 SessionIDCookie => $ParamObject->SetCookie( 509 Key => $Param{SessionName}, 510 Value => '', 511 Expires => '-1y', 512 Path => $ConfigObject->Get('ScriptAlias'), 513 Secure => scalar $CookieSecureAttribute, 514 HTTPOnly => 1, 515 ), 516 }, 517 %Param, 518 %UserData, 519 }, 520 ); 521 522 $Kernel::OM->ObjectsDiscard( Objects => ['Kernel::Output::HTML::Layout'] ); 523 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 524 525 # remove session id 526 if ( !$SessionObject->RemoveSessionID( SessionID => $Param{SessionID} ) ) { 527 $LayoutObject->CustomerFatalError( 528 Comment => Translatable('Please contact the administrator.') 529 ); 530 return; 531 } 532 533 # redirect to alternate login 534 if ( $ConfigObject->Get('CustomerPanelLogoutURL') ) { 535 print $LayoutObject->Redirect( 536 ExtURL => $ConfigObject->Get('CustomerPanelLogoutURL'), 537 ); 538 } 539 540 # show logout screen 541 my $LogoutMessage = $LayoutObject->{LanguageObject}->Translate('Logout successful.'); 542 543 $LayoutObject->Print( 544 Output => \$LayoutObject->CustomerLogin( 545 Title => 'Logout', 546 Message => $LogoutMessage, 547 MessageType => 'Success', 548 %Param, 549 ), 550 ); 551 return 1; 552 } 553 554 # CustomerLostPassword 555 elsif ( $Param{Action} eq 'CustomerLostPassword' ) { 556 557 # new layout object 558 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 559 560 # check feature 561 if ( !$ConfigObject->Get('CustomerPanelLostPassword') ) { 562 563 # show normal login 564 $LayoutObject->Print( 565 Output => \$LayoutObject->CustomerLogin( 566 Title => 'Login', 567 Message => Translatable('Feature not active!'), 568 ), 569 ); 570 return; 571 } 572 573 # get params 574 my $User = $ParamObject->GetParam( Param => 'User' ) || ''; 575 my $Token = $ParamObject->GetParam( Param => 'Token' ) || ''; 576 577 # get user login by token 578 if ( !$User && $Token ) { 579 580 # Prevent extracting password reset token character-by-character via wildcard injection 581 # The wild card characters "%" and "_" could be used to match arbitrary character. 582 if ( $Token !~ m{\A (?: [a-zA-Z] | \d )+ \z}xms ) { 583 584 # Security: pretend that password reset instructions were actually sent to 585 # make sure that users cannot find out valid usernames by 586 # just trying and checking the result message. 587 $LayoutObject->Print( 588 Output => \$LayoutObject->Login( 589 Title => 'Login', 590 Message => Translatable('Sent password reset instructions. Please check your email.'), 591 MessageType => 'Success', 592 %Param, 593 ), 594 ); 595 return; 596 } 597 598 my %UserList = $UserObject->SearchPreferences( 599 Key => 'UserToken', 600 Value => $Token, 601 ); 602 USER_ID: 603 for my $UserID ( sort keys %UserList ) { 604 my %UserData = $UserObject->CustomerUserDataGet( 605 User => $UserID, 606 Valid => 1, 607 ); 608 if (%UserData) { 609 $User = $UserData{UserLogin}; 610 last USER_ID; 611 } 612 } 613 } 614 615 # get user data 616 my %UserData = $UserObject->CustomerUserDataGet( User => $User ); 617 618 # verify customer user is valid when requesting password reset 619 my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet(); 620 my $UserIsValid = grep { $UserData{ValidID} && $UserData{ValidID} == $_ } @ValidIDs; 621 if ( !$UserData{UserID} || !$UserIsValid ) { 622 623 # Security: pretend that password reset instructions were actually sent to 624 # make sure that users cannot find out valid usernames by 625 # just trying and checking the result message. 626 $LayoutObject->Print( 627 Output => \$LayoutObject->CustomerLogin( 628 Title => 'Login', 629 Message => Translatable('Sent password reset instructions. Please check your email.'), 630 MessageType => 'Success', 631 ), 632 ); 633 return; 634 } 635 636 # create email object 637 my $EmailObject = Kernel::System::Email->new( %{$Self} ); 638 639 # send password reset token 640 if ( !$Token ) { 641 642 # generate token 643 $UserData{Token} = $UserObject->TokenGenerate( 644 UserID => $UserData{UserID}, 645 ); 646 647 # send token notify email with link 648 my $Body = $ConfigObject->Get('CustomerPanelBodyLostPasswordToken') 649 || 'ERROR: CustomerPanelBodyLostPasswordToken is missing!'; 650 my $Subject = $ConfigObject->Get('CustomerPanelSubjectLostPasswordToken') 651 || 'ERROR: CustomerPanelSubjectLostPasswordToken is missing!'; 652 for ( sort keys %UserData ) { 653 $Body =~ s/<OTRS_$_>/$UserData{$_}/gi; 654 } 655 my $Sent = $EmailObject->Send( 656 To => $UserData{UserEmail}, 657 Subject => $Subject, 658 Charset => $LayoutObject->{UserCharset}, 659 MimeType => 'text/plain', 660 Body => $Body 661 ); 662 if ( !$Sent->{Success} ) { 663 $LayoutObject->FatalError( 664 Comment => Translatable('Please contact the administrator.'), 665 ); 666 return; 667 } 668 $LayoutObject->Print( 669 Output => \$LayoutObject->CustomerLogin( 670 Title => 'Login', 671 Message => Translatable('Sent password reset instructions. Please check your email.'), 672 %Param, 673 MessageType => 'Success', 674 ), 675 ); 676 return 1; 677 678 } 679 680 # reset password 681 # check if token is valid 682 my $TokenValid = $UserObject->TokenCheck( 683 Token => $Token, 684 UserID => $UserData{UserID}, 685 ); 686 if ( !$TokenValid ) { 687 $LayoutObject->Print( 688 Output => \$LayoutObject->CustomerLogin( 689 Title => 'Login', 690 Message => Translatable('Invalid Token!'), 691 %Param, 692 ), 693 ); 694 return; 695 } 696 697 # get new password 698 $UserData{NewPW} = $UserObject->GenerateRandomPassword(); 699 700 # update new password 701 my $Success = $UserObject->SetPassword( 702 UserLogin => $User, 703 PW => $UserData{NewPW} 704 ); 705 706 if ( !$Success ) { 707 $LayoutObject->Print( 708 Output => \$LayoutObject->CustomerLogin( 709 Title => 'Login', 710 Message => Translatable('Reset password unsuccessful. Please contact the administrator.'), 711 User => $User, 712 ), 713 ); 714 return; 715 } 716 717 # send notify email 718 my $Body = $ConfigObject->Get('CustomerPanelBodyLostPassword') 719 || 'New Password is: <OTRS_NEWPW>'; 720 my $Subject = $ConfigObject->Get('CustomerPanelSubjectLostPassword') 721 || 'New Password!'; 722 for ( sort keys %UserData ) { 723 $Body =~ s/<OTRS_$_>/$UserData{$_}/gi; 724 } 725 my $Sent = $EmailObject->Send( 726 To => $UserData{UserEmail}, 727 Subject => $Subject, 728 Charset => $LayoutObject->{UserCharset}, 729 MimeType => 'text/plain', 730 Body => $Body 731 ); 732 if ( !$Sent->{Success} ) { 733 $LayoutObject->CustomerFatalError( 734 Comment => Translatable('Please contact the administrator.') 735 ); 736 return; 737 } 738 my $Message = $LayoutObject->{LanguageObject}->Translate( 739 'Sent new password to %s. Please check your email.', 740 $UserData{UserEmail}, 741 ); 742 $LayoutObject->Print( 743 Output => \$LayoutObject->CustomerLogin( 744 Title => 'Login', 745 Message => $Message, 746 User => $User, 747 MessageType => 'Success', 748 ), 749 ); 750 return 1; 751 } 752 753 # create new customer account 754 elsif ( $Param{Action} eq 'CustomerCreateAccount' ) { 755 756 # new layout object 757 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 758 759 # check feature 760 if ( !$ConfigObject->Get('CustomerPanelCreateAccount') ) { 761 762 # show normal login 763 $LayoutObject->Print( 764 Output => \$LayoutObject->CustomerLogin( 765 Title => 'Login', 766 Message => Translatable('Feature not active!'), 767 ), 768 ); 769 return; 770 } 771 772 # get params 773 my %GetParams; 774 for my $Entry ( @{ $ConfigObject->Get('CustomerUser')->{Map} } ) { 775 $GetParams{ $Entry->[0] } = $ParamObject->GetParam( Param => $Entry->[1] ) 776 || ''; 777 } 778 $GetParams{ValidID} = 1; 779 780 # check needed params 781 if ( !$GetParams{UserCustomerID} ) { 782 $GetParams{UserCustomerID} = $GetParams{UserEmail}; 783 } 784 if ( !$GetParams{UserLogin} ) { 785 $GetParams{UserLogin} = $GetParams{UserEmail}; 786 } 787 788 # get new password 789 $GetParams{UserPassword} = $UserObject->GenerateRandomPassword(); 790 791 # get user data 792 my %UserData = $UserObject->CustomerUserDataGet( User => $GetParams{UserLogin} ); 793 if ( $UserData{UserID} || !$GetParams{UserLogin} ) { 794 795 # send data to JS 796 $LayoutObject->AddJSData( 797 Key => 'SignupError', 798 Value => 1, 799 ); 800 801 $LayoutObject->Print( 802 Output => \$LayoutObject->CustomerLogin( 803 Title => 'Login', 804 Message => 805 Translatable('This e-mail address already exists. Please log in or reset your password.'), 806 UserTitle => $GetParams{UserTitle}, 807 UserFirstname => $GetParams{UserFirstname}, 808 UserLastname => $GetParams{UserLastname}, 809 UserEmail => $GetParams{UserEmail}, 810 ), 811 ); 812 return; 813 } 814 815 # check for mail address restrictions 816 my @Whitelist = @{ 817 $ConfigObject->Get('CustomerPanelCreateAccount::MailRestrictions::Whitelist') // [] 818 }; 819 my @Blacklist = @{ 820 $ConfigObject->Get('CustomerPanelCreateAccount::MailRestrictions::Blacklist') // [] 821 }; 822 823 my $WhitelistMatched; 824 for my $WhitelistEntry (@Whitelist) { 825 my $Regex = eval {qr/$WhitelistEntry/i}; 826 if ($@) { 827 $Kernel::OM->Get('Kernel::System::Log')->Log( 828 Priority => 'error', 829 Message => 830 $LayoutObject->{LanguageObject}->Translate( 831 'The customer panel mail address whitelist contains the invalid regular expression $WhitelistEntry, please check and correct it.' 832 ), 833 ); 834 } 835 elsif ( $GetParams{UserEmail} =~ $Regex ) { 836 $WhitelistMatched++; 837 } 838 } 839 my $BlacklistMatched; 840 for my $BlacklistEntry (@Blacklist) { 841 my $Regex = eval {qr/$BlacklistEntry/i}; 842 if ($@) { 843 $Kernel::OM->Get('Kernel::System::Log')->Log( 844 Priority => 'error', 845 Message => 846 $LayoutObject->{LanguageObject}->Translate( 847 'The customer panel mail address blacklist contains the invalid regular expression $BlacklistEntry, please check and correct it.' 848 ), 849 ); 850 } 851 elsif ( $GetParams{UserEmail} =~ $Regex ) { 852 $BlacklistMatched++; 853 } 854 } 855 856 if ( ( @Whitelist && !$WhitelistMatched ) || ( @Blacklist && $BlacklistMatched ) ) { 857 858 # send data to JS 859 $LayoutObject->AddJSData( 860 Key => 'SignupError', 861 Value => 1, 862 ); 863 864 $LayoutObject->Print( 865 Output => \$LayoutObject->CustomerLogin( 866 Title => 'Login', 867 Message => 868 Translatable('This email address is not allowed to register. Please contact support staff.'), 869 UserTitle => $GetParams{UserTitle}, 870 UserFirstname => $GetParams{UserFirstname}, 871 UserLastname => $GetParams{UserLastname}, 872 UserEmail => $GetParams{UserEmail}, 873 ), 874 ); 875 876 return; 877 } 878 879 # create account 880 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 881 882 my $Now = $DateTimeObject->ToString(); 883 884 my $Add = $UserObject->CustomerUserAdd( 885 %GetParams, 886 Comment => $LayoutObject->{LanguageObject}->Translate( 'Added via Customer Panel (%s)', $Now ), 887 ValidID => 1, 888 UserID => $ConfigObject->Get('CustomerPanelUserID'), 889 ); 890 if ( !$Add ) { 891 892 # send data to JS 893 $LayoutObject->AddJSData( 894 Key => 'SignupError', 895 Value => 1, 896 ); 897 898 $LayoutObject->Print( 899 Output => \$LayoutObject->CustomerLogin( 900 Title => 'Login', 901 Message => Translatable('Customer user can\'t be added!'), 902 UserTitle => $GetParams{UserTitle}, 903 UserFirstname => $GetParams{UserFirstname}, 904 UserLastname => $GetParams{UserLastname}, 905 UserEmail => $GetParams{UserEmail}, 906 ), 907 ); 908 return; 909 } 910 911 # send notify email 912 my $EmailObject = Kernel::System::Email->new( %{$Self} ); 913 my $Body = $ConfigObject->Get('CustomerPanelBodyNewAccount') 914 || 'No Config Option found!'; 915 my $Subject = $ConfigObject->Get('CustomerPanelSubjectNewAccount') 916 || 'New OTRS Account!'; 917 for ( sort keys %GetParams ) { 918 $Body =~ s/<OTRS_$_>/$GetParams{$_}/gi; 919 } 920 921 # send account info 922 my $Sent = $EmailObject->Send( 923 To => $GetParams{UserEmail}, 924 Subject => $Subject, 925 Charset => $LayoutObject->{UserCharset}, 926 MimeType => 'text/plain', 927 Body => $Body 928 ); 929 if ( !$Sent->{Success} ) { 930 my $Output = $LayoutObject->CustomerHeader( 931 Area => 'Core', 932 Title => 'Error' 933 ); 934 $Output .= $LayoutObject->CustomerWarning( 935 Comment => Translatable('Can\'t send account info!') 936 ); 937 $Output .= $LayoutObject->CustomerFooter(); 938 $LayoutObject->Print( Output => \$Output ); 939 return; 940 } 941 942 # show sent account info 943 if ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 944 945 # redirect to alternate login 946 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 947 print $LayoutObject->Redirect( 948 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 949 . "?RequestedURL=$Param{RequestedURL};User=$GetParams{UserLogin};" 950 . "Email=$GetParams{UserEmail};Reason=NewAccountCreated", 951 ); 952 return 1; 953 } 954 955 my $AccountCreatedMessage = $LayoutObject->{LanguageObject}->Translate( 956 'New account created. Sent login information to %s. Please check your email.', 957 $GetParams{UserEmail}, 958 ); 959 960 # login screen 961 $LayoutObject->Print( 962 Output => \$LayoutObject->CustomerLogin( 963 Title => 'Login', 964 Message => $AccountCreatedMessage, 965 User => $GetParams{UserLogin}, 966 MessageType => 'Success', 967 ), 968 ); 969 return 1; 970 } 971 972 # show login site 973 elsif ( !$Param{SessionID} ) { 974 975 # new layout object 976 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 977 978 # create AuthObject 979 my $AuthObject = $Kernel::OM->Get('Kernel::System::CustomerAuth'); 980 if ( $AuthObject->GetOption( What => 'PreAuth' ) ) { 981 982 # automatic login 983 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 984 print $LayoutObject->Redirect( 985 OP => "Action=PreLogin;RequestedURL=$Param{RequestedURL}", 986 ); 987 return; 988 } 989 elsif ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 990 991 # redirect to alternate login 992 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 993 print $LayoutObject->Redirect( 994 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 995 . "?RequestedURL=$Param{RequestedURL}", 996 ); 997 return; 998 } 999 1000 # login screen 1001 $LayoutObject->Print( 1002 Output => \$LayoutObject->CustomerLogin( 1003 Title => 'Login', 1004 %Param, 1005 ), 1006 ); 1007 return 1; 1008 } 1009 1010 # run modules if a version value exists 1011 elsif ( $Kernel::OM->Get('Kernel::System::Main')->Require("Kernel::Modules::$Param{Action}") ) { 1012 1013 # check session id 1014 if ( !$SessionObject->CheckSessionID( SessionID => $Param{SessionID} ) ) { 1015 1016 # create new LayoutObject with new '%Param' 1017 $Kernel::OM->ObjectParamAdd( 1018 'Kernel::Output::HTML::Layout' => { 1019 SetCookies => { 1020 SessionIDCookie => $ParamObject->SetCookie( 1021 Key => $Param{SessionName}, 1022 Value => '', 1023 Expires => '-1y', 1024 Path => $ConfigObject->Get('ScriptAlias'), 1025 Secure => scalar $CookieSecureAttribute, 1026 HTTPOnly => 1, 1027 ), 1028 }, 1029 %Param, 1030 } 1031 ); 1032 1033 $Kernel::OM->ObjectsDiscard( Objects => ['Kernel::Output::HTML::Layout'] ); 1034 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1035 1036 # create AuthObject 1037 my $AuthObject = $Kernel::OM->Get('Kernel::System::CustomerAuth'); 1038 if ( $AuthObject->GetOption( What => 'PreAuth' ) ) { 1039 1040 # automatic re-login 1041 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 1042 print $LayoutObject->Redirect( 1043 OP => "?Action=PreLogin&RequestedURL=$Param{RequestedURL}", 1044 ); 1045 return; 1046 } 1047 1048 # redirect to alternate login 1049 elsif ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 1050 1051 # redirect to alternate login 1052 $Param{RequestedURL} = $LayoutObject->LinkEncode( $Param{RequestedURL} ); 1053 print $LayoutObject->Redirect( 1054 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 1055 . "?Reason=InvalidSessionID;RequestedURL=$Param{RequestedURL}", 1056 ); 1057 return; 1058 } 1059 1060 # show login 1061 $LayoutObject->Print( 1062 Output => \$LayoutObject->CustomerLogin( 1063 Title => 'Login', 1064 Message => 1065 $LayoutObject->{LanguageObject}->Translate( $SessionObject->SessionIDErrorMessage() ), 1066 %Param, 1067 ), 1068 ); 1069 return; 1070 } 1071 1072 # get session data 1073 my %UserData = $SessionObject->GetSessionIDData( 1074 SessionID => $Param{SessionID}, 1075 ); 1076 1077 $UserData{UserTimeZone} = $Self->_UserTimeZoneGet(%UserData); 1078 1079 # check needed data 1080 if ( !$UserData{UserID} || !$UserData{UserLogin} || $UserData{UserType} ne 'Customer' ) { 1081 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1082 1083 # redirect to alternate login 1084 if ( $ConfigObject->Get('CustomerPanelLoginURL') ) { 1085 print $LayoutObject->Redirect( 1086 ExtURL => $ConfigObject->Get('CustomerPanelLoginURL') 1087 . "?Reason=SystemError", 1088 ); 1089 return; 1090 } 1091 1092 # show login screen 1093 $LayoutObject->Print( 1094 Output => \$LayoutObject->CustomerLogin( 1095 Title => 'Error', 1096 Message => Translatable('Error: invalid session.'), 1097 %Param, 1098 ), 1099 ); 1100 return; 1101 } 1102 1103 # module registry 1104 my $ModuleReg = $ConfigObject->Get('CustomerFrontend::Module')->{ $Param{Action} }; 1105 if ( !$ModuleReg ) { 1106 1107 # new layout object 1108 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1109 $Kernel::OM->Get('Kernel::System::Log')->Log( 1110 Priority => 'error', 1111 Message => 1112 "Module Kernel::Modules::$Param{Action} not registered in Kernel/Config.pm!", 1113 ); 1114 $LayoutObject->CustomerFatalError( 1115 Comment => Translatable('Please contact the administrator.'), 1116 ); 1117 return; 1118 } 1119 1120 # module permission check for action 1121 if ( 1122 ref $ModuleReg->{GroupRo} eq 'ARRAY' 1123 && !scalar @{ $ModuleReg->{GroupRo} } 1124 && ref $ModuleReg->{Group} eq 'ARRAY' 1125 && !scalar @{ $ModuleReg->{Group} } 1126 ) 1127 { 1128 $Param{AccessRo} = 1; 1129 $Param{AccessRw} = 1; 1130 } 1131 else { 1132 1133 ( $Param{AccessRo}, $Param{AccessRw} ) = $Self->_CheckModulePermission( 1134 ModuleReg => $ModuleReg, 1135 %UserData, 1136 ); 1137 1138 if ( !$Param{AccessRo} ) { 1139 1140 # new layout object 1141 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1142 $Kernel::OM->Get('Kernel::System::Log')->Log( 1143 Priority => 'error', 1144 Message => 'No Permission to use this frontend action module!' 1145 ); 1146 $LayoutObject->CustomerFatalError( 1147 Comment => Translatable('Please contact the administrator.'), 1148 ); 1149 return; 1150 } 1151 1152 } 1153 1154 my $NavigationConfig = $ConfigObject->Get('CustomerFrontend::Navigation')->{ $Param{Action} }; 1155 1156 # module permission check for submenu item 1157 if ( IsHashRefWithData($NavigationConfig) ) { 1158 1159 KEY: 1160 for my $Key ( sort keys %{$NavigationConfig} ) { 1161 next KEY if $Key !~ m/^\d+/i; 1162 next KEY if $Param{RequestedURL} !~ m/Subaction/i; 1163 1164 my @ModuleNavigationConfigs; 1165 1166 # FIXME: Support both old (HASH) and new (ARRAY of HASH) navigation configurations, for reasons of 1167 # backwards compatibility. Once we are sure everything has been migrated correctly, support for 1168 # HASH-only configuration can be dropped in future major release. 1169 if ( IsHashRefWithData( $NavigationConfig->{$Key} ) ) { 1170 push @ModuleNavigationConfigs, $NavigationConfig->{$Key}; 1171 } 1172 elsif ( IsArrayRefWithData( $NavigationConfig->{$Key} ) ) { 1173 push @ModuleNavigationConfigs, @{ $NavigationConfig->{$Key} }; 1174 } 1175 1176 # Skip incompatible configuration. 1177 else { 1178 next KEY; 1179 } 1180 1181 ITEM: 1182 for my $Item (@ModuleNavigationConfigs) { 1183 if ( 1184 $Item->{Link} =~ m/Subaction=/i 1185 && $Item->{Link} !~ m/$Param{Subaction}/i 1186 ) 1187 { 1188 next ITEM; 1189 } 1190 $Param{AccessRo} = 0; 1191 $Param{AccessRw} = 0; 1192 1193 # module permission check for submenu item 1194 if ( 1195 ref $Item->{GroupRo} eq 'ARRAY' 1196 && !scalar @{ $Item->{GroupRo} } 1197 && ref $Item->{Group} eq 'ARRAY' 1198 && !scalar @{ $Item->{Group} } 1199 ) 1200 { 1201 $Param{AccessRo} = 1; 1202 $Param{AccessRw} = 1; 1203 } 1204 else { 1205 1206 ( $Param{AccessRo}, $Param{AccessRw} ) = $Self->_CheckModulePermission( 1207 ModuleReg => $Item, 1208 %UserData, 1209 ); 1210 1211 if ( !$Param{AccessRo} ) { 1212 1213 # new layout object 1214 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1215 $Kernel::OM->Get('Kernel::System::Log')->Log( 1216 Priority => 'error', 1217 Message => 'No Permission to use this frontend subaction module!' 1218 ); 1219 $LayoutObject->CustomerFatalError( 1220 Comment => Translatable('Please contact the administrator.') 1221 ); 1222 return; 1223 } 1224 } 1225 } 1226 } 1227 } 1228 1229 # create new LayoutObject with new '%Param' and '%UserData' 1230 $Kernel::OM->ObjectParamAdd( 1231 'Kernel::Output::HTML::Layout' => { 1232 %Param, 1233 %UserData, 1234 ModuleReg => $ModuleReg, 1235 }, 1236 ); 1237 1238 $Kernel::OM->ObjectsDiscard( Objects => ['Kernel::Output::HTML::Layout'] ); 1239 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1240 1241 # update last request time 1242 if ( 1243 !$ParamObject->IsAJAXRequest() 1244 || $Param{Action} eq 'CustomerVideoChat' 1245 ) 1246 { 1247 my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime'); 1248 1249 $SessionObject->UpdateSessionID( 1250 SessionID => $Param{SessionID}, 1251 Key => 'UserLastRequest', 1252 Value => $DateTimeObject->ToEpoch(), 1253 ); 1254 } 1255 1256 # pre application module 1257 my $PreModule = $ConfigObject->Get('CustomerPanelPreApplicationModule'); 1258 if ($PreModule) { 1259 my %PreModuleList; 1260 if ( ref $PreModule eq 'HASH' ) { 1261 %PreModuleList = %{$PreModule}; 1262 } 1263 else { 1264 $PreModuleList{Init} = $PreModule; 1265 } 1266 1267 MODULE: 1268 for my $PreModuleKey ( sort keys %PreModuleList ) { 1269 my $PreModule = $PreModuleList{$PreModuleKey}; 1270 next MODULE if !$PreModule; 1271 next MODULE if !$Kernel::OM->Get('Kernel::System::Main')->Require($PreModule); 1272 1273 # debug info 1274 if ( $Self->{Debug} ) { 1275 $Kernel::OM->Get('Kernel::System::Log')->Log( 1276 Priority => 'debug', 1277 Message => "CustomerPanelPreApplication module $PreModule is used.", 1278 ); 1279 } 1280 1281 # use module 1282 my $PreModuleObject = $PreModule->new( 1283 %Param, 1284 %UserData, 1285 1286 ); 1287 my $Output = $PreModuleObject->PreRun(); 1288 if ($Output) { 1289 $LayoutObject->Print( Output => \$Output ); 1290 return 1; 1291 } 1292 } 1293 } 1294 1295 # debug info 1296 if ( $Self->{Debug} ) { 1297 $Kernel::OM->Get('Kernel::System::Log')->Log( 1298 Priority => 'debug', 1299 Message => 'Kernel::Modules::' . $Param{Action} . '->new', 1300 ); 1301 } 1302 1303 my $FrontendObject = ( 'Kernel::Modules::' . $Param{Action} )->new( 1304 %Param, 1305 %UserData, 1306 ModuleReg => $ModuleReg, 1307 Debug => $Self->{Debug}, 1308 ); 1309 1310 # debug info 1311 if ( $Self->{Debug} ) { 1312 $Kernel::OM->Get('Kernel::System::Log')->Log( 1313 Priority => 'debug', 1314 Message => 'Kernel::Modules::' . $Param{Action} . '->run', 1315 ); 1316 } 1317 1318 # ->Run $Action with $FrontendObject 1319 $LayoutObject->Print( Output => \$FrontendObject->Run() ); 1320 1321 # log request time 1322 if ( $ConfigObject->Get('PerformanceLog') ) { 1323 if ( ( !$QueryString && $Param{Action} ) || $QueryString !~ /Action=/ ) { 1324 $QueryString = 'Action=' . $Param{Action} . ';Subaction=' . $Param{Subaction}; 1325 } 1326 my $File = $ConfigObject->Get('PerformanceLog::File'); 1327 ## no critic 1328 if ( open my $Out, '>>', $File ) { 1329 ## use critic 1330 print $Out time() 1331 . '::Customer::' 1332 . ( time() - $Self->{PerformanceLogStart} ) 1333 . "::$UserData{UserLogin}::$QueryString\n"; 1334 close $Out; 1335 $Kernel::OM->Get('Kernel::System::Log')->Log( 1336 Priority => 'debug', 1337 Message => 'Response::Customer: ' 1338 . ( time() - $Self->{PerformanceLogStart} ) 1339 . "s taken (URL:$QueryString:$UserData{UserLogin})", 1340 ); 1341 } 1342 else { 1343 $Kernel::OM->Get('Kernel::System::Log')->Log( 1344 Priority => 'error', 1345 Message => "Can't write $File: $!", 1346 ); 1347 } 1348 } 1349 return 1; 1350 } 1351 1352 # print an error screen 1353 my %Data = $SessionObject->GetSessionIDData( 1354 SessionID => $Param{SessionID}, 1355 ); 1356 $Data{UserTimeZone} = $Self->_UserTimeZoneGet(%Data); 1357 $Kernel::OM->ObjectParamAdd( 1358 'Kernel::Output::HTML::Layout' => { 1359 %Param, 1360 %Data, 1361 }, 1362 ); 1363 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 1364 $LayoutObject->CustomerFatalError( 1365 Comment => Translatable('Please contact the administrator.'), 1366 ); 1367 return; 1368} 1369 1370=begin Internal: 1371 1372=head2 _CheckModulePermission() 1373 1374module permission check 1375 1376 ($AccessRo, $AccessRw = $AutoResponseObject->_CheckModulePermission( 1377 ModuleReg => $ModuleReg, 1378 %UserData, 1379 ); 1380 1381=cut 1382 1383sub _CheckModulePermission { 1384 my ( $Self, %Param ) = @_; 1385 1386 my $AccessRo = 0; 1387 my $AccessRw = 0; 1388 1389 PERMISSION: 1390 for my $Permission (qw(GroupRo Group)) { 1391 my $AccessOk = 0; 1392 my $Group = $Param{ModuleReg}->{$Permission}; 1393 1394 next PERMISSION if !$Group; 1395 1396 my $GroupObject = $Kernel::OM->Get('Kernel::System::CustomerGroup'); 1397 1398 if ( IsArrayRefWithData($Group) ) { 1399 GROUP: 1400 for my $Item ( @{$Group} ) { 1401 next GROUP if !$Item; 1402 next GROUP if !$GroupObject->PermissionCheck( 1403 UserID => $Param{UserID}, 1404 GroupName => $Item, 1405 Type => $Permission eq 'GroupRo' ? 'ro' : 'rw', 1406 ); 1407 1408 $AccessOk = 1; 1409 last GROUP; 1410 } 1411 } 1412 else { 1413 my $HasPermission = $GroupObject->PermissionCheck( 1414 UserID => $Param{UserID}, 1415 GroupName => $Group, 1416 Type => $Permission eq 'GroupRo' ? 'ro' : 'rw', 1417 ); 1418 if ($HasPermission) { 1419 $AccessOk = 1; 1420 } 1421 } 1422 if ( $Permission eq 'Group' && $AccessOk ) { 1423 $AccessRo = 1; 1424 $AccessRw = 1; 1425 } 1426 elsif ( $Permission eq 'GroupRo' && $AccessOk ) { 1427 $AccessRo = 1; 1428 } 1429 } 1430 1431 return ( $AccessRo, $AccessRw ); 1432} 1433 1434=head2 _UserTimeZoneGet() 1435 1436Get time zone for the current user. This function will validate passed time zone parameter and return default user time 1437zone if it's not valid. 1438 1439 my $UserTimeZone = $Self->_UserTimeZoneGet( 1440 UserTimeZone => 'Europe/Berlin', 1441 ); 1442 1443=cut 1444 1445sub _UserTimeZoneGet { 1446 my ( $Self, %Param ) = @_; 1447 1448 my $UserTimeZone; 1449 1450 # Return passed time zone only if it's valid. It can happen that user preferences or session store an old-style 1451 # offset which is not valid anymore. In this case, return the default value. 1452 # Please see bug#13374 for more information. 1453 if ( 1454 $Param{UserTimeZone} 1455 && Kernel::System::DateTime->IsTimeZoneValid( TimeZone => $Param{UserTimeZone} ) 1456 ) 1457 { 1458 $UserTimeZone = $Param{UserTimeZone}; 1459 } 1460 1461 $UserTimeZone ||= Kernel::System::DateTime->UserDefaultTimeZoneGet(); 1462 1463 return $UserTimeZone; 1464} 1465 1466=end Internal: 1467 1468=cut 1469 1470sub DESTROY { 1471 my $Self = shift; 1472 1473 # debug info 1474 if ( $Self->{Debug} ) { 1475 $Kernel::OM->Get('Kernel::System::Log')->Log( 1476 Priority => 'debug', 1477 Message => 'Global handle stopped.', 1478 ); 1479 } 1480 1481 return 1; 1482} 1483 14841; 1485 1486=head1 TERMS AND CONDITIONS 1487 1488This software is part of the OTRS project (L<https://otrs.org/>). 1489 1490This software comes with ABSOLUTELY NO WARRANTY. For details, see 1491the enclosed file COPYING for license information (GPL). If you 1492did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>. 1493 1494=cut 1495