Files
scripts/Perl OTRS/Kernel/Modules/AdminUser.pm
2024-10-14 00:08:40 +02:00

696 lines
21 KiB
Perl

# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::Modules::AdminUser;
use strict;
use warnings;
use Kernel::Language qw(Translatable);
our $ObjectManagerDisabled = 1;
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {%Param};
bless( $Self, $Type );
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
# get needed objects
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $LogObject = $Kernel::OM->Get('Kernel::System::Log');
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
my $CheckItemObject = $Kernel::OM->Get('Kernel::System::CheckItem');
my $Search = $ParamObject->GetParam( Param => 'Search' ) || '';
my $Notification = $ParamObject->GetParam( Param => 'Notification' ) || '';
# Get list of valid IDs.
my @ValidIDList = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet();
# ------------------------------------------------------------ #
# switch to user
# ------------------------------------------------------------ #
if (
$Self->{Subaction} eq 'Switch'
&& $ConfigObject->Get('SwitchToUser')
)
{
# challenge token check for write action
$LayoutObject->ChallengeTokenCheck();
my $UserID = $ParamObject->GetParam( Param => 'UserID' ) || '';
my %UserData = $UserObject->GetUserData(
UserID => $UserID,
NoOutOfOffice => 1,
);
my $SessionObject = $Kernel::OM->Get('Kernel::System::AuthSession');
my $NewSessionID = $SessionObject->CreateSessionID(
%UserData,
UserLastRequest => $Kernel::OM->Create('Kernel::System::DateTime')->ToEpoch(),
UserType => 'User',
SessionSource => 'AgentInterface',
);
# create a new LayoutObject with SessionIDCookie
my $Expires = '+' . $ConfigObject->Get('SessionMaxTime') . 's';
if ( !$ConfigObject->Get('SessionUseCookieAfterBrowserClose') ) {
$Expires = '';
}
my $SecureAttribute;
if ( $ConfigObject->Get('HttpType') eq 'https' ) {
# Restrict Cookie to HTTPS if it is used.
$SecureAttribute = 1;
}
$Kernel::OM->ObjectParamAdd(
'Kernel::Output::HTML::Layout' => {
%UserData,
SetCookies => {
SessionIDCookie => $ParamObject->SetCookie(
Key => $ConfigObject->Get('SessionName'),
Value => $NewSessionID,
Expires => $Expires,
Path => $ConfigObject->Get('ScriptAlias'),
Secure => scalar $SecureAttribute,
HTTPOnly => 1,
),
},
SessionID => $NewSessionID,
SessionName => $ConfigObject->Get('SessionName'),
}
);
$Kernel::OM->ObjectsDiscard( Objects => ['Kernel::Output::HTML::Layout'] );
my $LayoutObjectSession = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# log event
$LogObject->Log(
Priority => 'notice',
Message => "Switched to User ($Self->{UserLogin} -=> $UserData{UserLogin})",
);
# Delete old session, see bug#14322 (https://bugs.otrs.org/show_bug.cgi?id=14322);
$SessionObject->RemoveSessionID(
SessionID => $LayoutObject->{SessionID}
);
# redirect with new session id
return $LayoutObjectSession->Redirect( OP => '' );
}
# ------------------------------------------------------------ #
# change
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'Change' ) {
my $UserID = $ParamObject->GetParam( Param => 'UserID' )
|| $ParamObject->GetParam( Param => 'ID' )
|| '';
my %UserData = $UserObject->GetUserData(
UserID => $UserID,
NoOutOfOffice => 1,
);
my $Output = $LayoutObject->Header();
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Notify( Info => Translatable('Agent updated!') )
if ( $Notification && $Notification eq 'Update' );
$Self->_Edit(
Action => 'Change',
Search => $Search,
%UserData,
);
$Output .= $LayoutObject->Output(
TemplateFile => 'AdminUser',
Data => \%Param,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
# ------------------------------------------------------------ #
# change action
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'ChangeAction' ) {
# challenge token check for write action
$LayoutObject->ChallengeTokenCheck();
my $Note = '';
my ( %GetParam, %Errors );
for my $Parameter (
qw(UserID UserTitle UserLogin UserFirstname UserLastname UserEmail UserPw UserMobile ValidID Search)
)
{
$GetParam{$Parameter} = $ParamObject->GetParam( Param => $Parameter ) || '';
}
for my $Needed (qw(UserID UserFirstname UserLastname UserLogin ValidID)) {
if ( !$GetParam{$Needed} ) {
$Errors{ $Needed . 'Invalid' } = 'ServerError';
}
}
# check email address
if (
$GetParam{UserEmail}
&& !$CheckItemObject->CheckEmail( Address => $GetParam{UserEmail} )
&& grep { $_ eq $GetParam{ValidID} } @ValidIDList
)
{
$Errors{UserEmailInvalid} = 'ServerError';
$Errors{ErrorType} = $CheckItemObject->CheckErrorType();
}
# check if a user with this login (username) already exits
my $UserLoginExists = $UserObject->UserLoginExistsCheck(
UserLogin => $GetParam{UserLogin},
UserID => $GetParam{UserID}
);
if ($UserLoginExists) {
$Errors{UserLoginExists} = 1;
$Errors{'UserLoginInvalid'} = 'ServerError';
}
# if no errors occurred
if ( !%Errors )
{
# update user
my $Update = $UserObject->UserUpdate(
%GetParam,
ChangeUserID => $Self->{UserID},
);
if ($Update) {
# if the user would like to continue editing the agent, just redirect to the edit screen
# otherwise return to overview
if (
defined $ParamObject->GetParam( Param => 'ContinueAfterSave' )
&& ( $ParamObject->GetParam( Param => 'ContinueAfterSave' ) eq '1' )
)
{
my $ID = $ParamObject->GetParam( Param => 'ID' ) || '';
return $LayoutObject->Redirect(
OP => "Action=$Self->{Action};Subaction=Change;UserID=$GetParam{UserID};Notification=Update"
);
}
else {
return $LayoutObject->Redirect( OP => "Action=$Self->{Action};Notification=Update" );
}
}
else {
$Note = $LogObject->GetLogEntry(
Type => 'Error',
What => 'Message',
);
}
}
my $Output = $LayoutObject->Header();
$Output .= $Note
? $LayoutObject->Notify(
Priority => 'Error',
Info => $Note,
)
: '';
$Output .= $LayoutObject->NavigationBar();
$Self->_Edit(
Action => 'Change',
Search => $Search,
ErrorType => $Errors{ErrorType} || '',
%GetParam,
%Errors,
);
$Output .= $LayoutObject->Output(
TemplateFile => 'AdminUser',
Data => \%Param,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
# ------------------------------------------------------------ #
# add
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'Add' ) {
my %GetParam = ();
$GetParam{UserLogin} = $ParamObject->GetParam( Param => 'UserLogin' );
my $Output = $LayoutObject->Header();
$Output .= $LayoutObject->NavigationBar();
$Self->_Edit(
Action => 'Add',
Search => $Search,
%GetParam,
);
$Output .= $LayoutObject->Output(
TemplateFile => 'AdminUser',
Data => \%Param,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
# ------------------------------------------------------------ #
# add action
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'AddAction' ) {
# challenge token check for write action
$LayoutObject->ChallengeTokenCheck();
my $Note = '';
my ( %GetParam, %Errors );
for my $Parameter (
qw(UserTitle UserLogin UserFirstname UserLastname UserEmail UserPw UserMobile ValidID Search)
)
{
$GetParam{$Parameter} = $ParamObject->GetParam( Param => $Parameter ) || '';
}
for my $Needed (qw(UserFirstname UserLastname UserLogin UserEmail ValidID)) {
if ( !$GetParam{$Needed} ) {
$Errors{ $Needed . 'Invalid' } = 'ServerError';
}
}
# check email address
if (
$GetParam{UserEmail}
&& !$CheckItemObject->CheckEmail( Address => $GetParam{UserEmail} )
&& grep { $_ eq $GetParam{ValidID} } @ValidIDList
)
{
$Errors{UserEmailInvalid} = 'ServerError';
$Errors{ErrorType} = $CheckItemObject->CheckErrorType();
}
# check if a user with this login (username) already exits
my $UserLoginExists = $UserObject->UserLoginExistsCheck( UserLogin => $GetParam{UserLogin} );
if ($UserLoginExists) {
$Errors{UserLoginExists} = 1;
$Errors{'UserLoginInvalid'} = 'ServerError';
}
# if no errors occurred
if ( !%Errors )
{
# add user
my $UserID = $UserObject->UserAdd(
%GetParam,
ChangeUserID => $Self->{UserID}
);
if ($UserID) {
# redirect
if (
!$ConfigObject->Get('Frontend::Module')->{AdminUserGroup}
&& $ConfigObject->Get('Frontend::Module')->{AdminRoleUser}
)
{
return $LayoutObject->Redirect(
OP => "Action=AdminRoleUser;Subaction=User;ID=$UserID",
);
}
if ( $ConfigObject->Get('Frontend::Module')->{AdminUserGroup} ) {
return $LayoutObject->Redirect(
OP => "Action=AdminUserGroup;Subaction=User;ID=$UserID",
);
}
else {
return $LayoutObject->Redirect(
OP => 'Action=AdminUser',
);
}
}
else {
$Note = $LogObject->GetLogEntry(
Type => 'Error',
What => 'Message',
);
}
}
my $Output = $LayoutObject->Header();
$Output .= $Note
? $LayoutObject->Notify(
Priority => 'Error',
Info => $Note,
)
: '';
$Output .= $LayoutObject->NavigationBar();
$Self->_Edit(
Action => 'Add',
Search => $Search,
ErrorType => $Errors{ErrorType} || '',
%GetParam,
%Errors,
);
$Output .= $LayoutObject->Output(
TemplateFile => 'AdminUser',
Data => \%Param,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
# ------------------------------------------------------------ #
# overview
# ------------------------------------------------------------ #
else {
$Self->_Overview( Search => $Search );
my $Output = $LayoutObject->Header();
$Output .= $LayoutObject->NavigationBar();
$Output .= $LayoutObject->Notify( Info => Translatable('Agent updated!') )
if ( $Notification && $Notification eq 'Update' );
$Output .= $LayoutObject->Output(
TemplateFile => 'AdminUser',
Data => \%Param,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
}
sub _Edit {
my ( $Self, %Param ) = @_;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
$LayoutObject->Block(
Name => 'Overview',
Data => \%Param,
);
$LayoutObject->Block( Name => 'ActionList' );
$LayoutObject->Block( Name => 'ActionOverview' );
# check if the current user has the permissions to edit another users preferences
if ( $Param{Action} eq 'Change' ) {
my $GroupObject = $Kernel::OM->Get('Kernel::System::Group');
my $EditAnotherUsersPreferencesGroup = $GroupObject->GroupLookup(
Group => $Kernel::OM->Get('Kernel::Config')->Get('EditAnotherUsersPreferencesGroup'),
);
# get user groups, where the user has the rw privilege
my %Groups = $GroupObject->PermissionUserGet(
UserID => $Self->{UserID},
Type => 'rw',
);
# if the user is a member in this group he can access the feature
if ( $Groups{$EditAnotherUsersPreferencesGroup} ) {
$LayoutObject->Block(
Name => 'ActionEditPreferences',
Data => {
UserID => $Param{UserID},
},
);
}
}
# get valid list
my %ValidList = $Kernel::OM->Get('Kernel::System::Valid')->ValidList();
my %ValidListReverse = reverse %ValidList;
$Param{ValidOption} = $LayoutObject->BuildSelection(
Data => \%ValidList,
Name => 'ValidID',
SelectedID => $Param{ValidID} || $ValidListReverse{valid},
Class => 'Modernize',
);
$LayoutObject->Block(
Name => 'OverviewUpdate',
Data => \%Param,
);
if ( $Param{Action} eq 'Change' ) {
# shows edit header
$LayoutObject->Block( Name => 'HeaderEdit' );
# shows effective permissions matrix
$Self->_EffectivePermissions(%Param);
}
else {
# shows add header and hints
$LayoutObject->Block( Name => 'HeaderAdd' );
$LayoutObject->Block( Name => 'MarkerMandatory' );
$LayoutObject->Block( Name => 'ShowPasswordHint' );
}
# add the correct server error message
if ( $Param{UserEmail} && $Param{ErrorType} ) {
# display server error message according with the occurred email error type
$LayoutObject->Block(
Name => 'UserEmail' . $Param{ErrorType} . 'ServerErrorMsg',
Data => {},
);
}
else {
$LayoutObject->Block(
Name => "UserEmailServerErrorMsg",
Data => {},
);
}
# show appropriate messages for ServerError
if ( defined $Param{UserLoginExists} && $Param{UserLoginExists} == 1 ) {
$LayoutObject->Block( Name => 'ExistUserLoginServerError' );
}
else {
$LayoutObject->Block( Name => 'UserLoginServerError' );
}
return 1;
}
sub _Overview {
my ( $Self, %Param ) = @_;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# when there is no data to show, a message is displayed on the table with this colspan
my $ColSpan = 7;
$LayoutObject->Block(
Name => 'Overview',
Data => \%Param,
);
$LayoutObject->Block( Name => 'ActionList' );
$LayoutObject->Block(
Name => 'ActionSearch',
Data => \%Param,
);
$LayoutObject->Block( Name => 'ActionAdd' );
# get user object
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
# ShownUsers limitation in AdminUser
my $Limit = 400;
my %List = $UserObject->UserSearch(
Search => $Param{Search} . '*',
Limit => $Limit,
Valid => 0,
);
my %ListAllItems = $UserObject->UserSearch(
Search => $Param{Search} . '*',
Limit => $Limit + 1,
Valid => 0,
);
if ( keys %ListAllItems <= $Limit ) {
my $ListAllItems = keys %ListAllItems;
$LayoutObject->Block(
Name => 'OverviewHeader',
Data => {
ListAll => $ListAllItems,
Limit => $Limit,
},
);
}
else {
my $ListAllSize = keys %ListAllItems;
my $SearchListSize = keys %List;
$LayoutObject->Block(
Name => 'OverviewHeader',
Data => {
SearchListSize => $SearchListSize,
ListAll => $ListAllSize,
Limit => $Limit,
},
);
}
$LayoutObject->Block(
Name => 'OverviewResult',
Data => \%Param,
);
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
if ( $ConfigObject->Get('SwitchToUser') ) {
$ColSpan = 8;
$LayoutObject->Block(
Name => 'OverviewResultSwitchToUser',
);
}
# get valid list
my %ValidList = $Kernel::OM->Get('Kernel::System::Valid')->ValidList();
# if there are results to show
if (%List) {
for my $ListKey ( sort { $List{$a} cmp $List{$b} } keys %List ) {
my %UserData = $UserObject->GetUserData(
UserID => $ListKey,
NoOutOfOffice => 1,
);
$LayoutObject->Block(
Name => 'OverviewResultRow',
Data => {
Valid => $ValidList{ $UserData{ValidID} },
Search => $Param{Search},
%UserData,
},
);
if ( $ConfigObject->Get('SwitchToUser') ) {
$LayoutObject->Block(
Name => 'OverviewResultRowSwitchToUser',
Data => {
Search => $Param{Search},
%UserData,
},
);
}
}
}
else {
$LayoutObject->Block(
Name => 'NoDataFoundMsg',
Data => {
ColSpan => $ColSpan,
},
);
}
return 1;
}
sub _EffectivePermissions {
my ( $Self, %Param ) = @_;
# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# show tables
$LayoutObject->Block(
Name => 'EffectivePermissions',
);
my %Groups;
my %Permissions;
# go through permission types
my @Types = @{ $Kernel::OM->Get('Kernel::Config')->Get('System::Permission') };
for my $Type (@Types) {
# show header
$LayoutObject->Block(
Name => 'HeaderGroupPermissionType',
Data => {
Type => $Type,
},
);
# get groups of the user
my %UserGroups = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet(
UserID => $Param{UserID},
Type => $Type,
);
# store data in lookup hashes
for my $GroupID ( sort keys %UserGroups ) {
$Groups{$GroupID} = $UserGroups{$GroupID};
$Permissions{$GroupID}{$Type} = 1;
}
}
# show message if no permissions found
if ( !%Permissions ) {
$LayoutObject->Block(
Name => 'NoGroupPermissionsFoundMsg',
);
return;
}
# go through groups, sort by name
for my $GroupID ( sort { uc( $Groups{$a} ) cmp uc( $Groups{$b} ) } keys %Groups ) {
# show table rows
$LayoutObject->Block(
Name => 'GroupPermissionTableRow',
Data => {
ID => $GroupID,
Name => $Groups{$GroupID},
},
);
# show permission marks
for my $Type (@Types) {
my $PermissionMark = $Permissions{$GroupID}{$Type} ? 'On' : 'Off';
my $HighlightMark = $Type eq 'rw' ? 'Highlight' : '';
$LayoutObject->Block(
Name => 'GroupPermissionMark',
);
$LayoutObject->Block(
Name => 'GroupPermissionMark' . $PermissionMark,
Data => {
Highlight => $HighlightMark,
},
);
}
}
return;
}
1;