To add move permission, we made these modifications :
<OTRS HOME>/ept/ept.group_user_add_column.sql :
alter table group_user
add column permission_move smallint(6) not null;
alter table group_user
alter column permission_move set default 0;
we just have to set to 0 the flag value :
$Self->{MoveInToAllQueues} = 0;
Concerning functions are : GroupUserList, GroupMemberList (get permissions) and GroupMemberAdd (upate permissions.)
For the function GroupMemberAdd, we have to change the request which make the insert (the function make first a delete and then insert the record because the table group_user contains only couple user/group when a user has at least one permission on the group) because we add a column permission into the table. Then, we have to add the parameter "move permission" which will given by the caller program (here AdminGroupUser.pm) :
# --
sub GroupMemberAdd {
my $Self = shift;
my %Param = @_;
my $count;
# --
# check needed stuff
# --
foreach (qw(UID GID UserID)) {
if (!$Param{$_}) {
$Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
return;
}
}
# --
# sql
# --
my $Ro = defined ($Param{Ro}) ? $Param{Ro} : 1;
my $Rw = defined ($Param{Rw}) ? $Param{Rw} : 1;
my $Mv = defined ($Param{Mv}) ? $Param{Mv} : 1;
$Self->{DBObject}->Do(
SQL => "DELETE FROM group_user WHERE group_id = $Param{GID} AND user_id = $Param{UID}",
);
if ($Ro || $Rw || $Mv) {
my $SQL = "INSERT INTO group_user (user_id, group_id, permission_read, permission_write, ".
" create_time, create_by, change_time, change_by, permission_move)".
" VALUES ".
" ( $Param{UID}, $Param{GID}, $Ro, $Rw, current_timestamp, ".
" $Param{UserID}, current_timestamp, $Param{UserID}, $Mv)";
if ($Self->{DBObject}->Do(SQL => $SQL)) {
return 1;
}
else {
return;
}
}
else {
return;
}
}
# --
For the function GroupMemeberList, we have to change the SQL request because we added a new column permission which we want to retrieve here. Then, we had a new type of permission (which is given in parameters) and to write the rule for this type. In fact, the function returns an array which contains all users who have permission <type> for the group given in parameters. So, when did we insert the user name into this array. We will insert the user when we move permission.
Rq : Don't forget that a new permission added has an impact for other rules.
# --
sub GroupMemberList {
my $Self = shift;
my %Param = @_;
# --
# check needed stuff
# --
foreach (qw(Result Type GroupID)) {
if (!$Param{$_}) {
$Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
return;
}
}
my %Users = ();
my @Name = ();
my @ID = ();
my $SQL = "SELECT u.id, u.login, gu.permission_read, gu.permission_write, gu.permission_move " .
" FROM " .
" $Self->{ConfigObject}->{DatabaseUserTable} u, group_user gu".
" WHERE " .
" u.valid_id in ( ${\(join ', ', $Self->{DBObject}->GetValidIDs())} ) ".
" AND ".
" gu.group_id = $Param{GroupID}".
" AND " .
" u.id = gu.user_id ";
$Self->{DBObject}->Prepare(SQL => $SQL);
while (my @Row = $Self->{DBObject}->FetchrowArray()) {
# read only
# change by EPT - we return the result if we a permission read, write or none
if ($Param{Type} eq 'ro') {
if ($Row[3] || $Row[2] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# read/write
# change by EPT - we return the result if we a permission write or none
elsif ($Param{Type} eq 'rw') {
if ($Row[3] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# move (add by EPT)
elsif ($Param{Type} eq 'mv') {
# EPT - we return the result if we a permission move or none
if ($Row[4] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
else {
$Self->{LogObject}->Log(Priority => 'error', Message => "Type '$Param{Type}' dosn't exist!");
return;
}
}
if ($Param{Result} && $Param{Result} eq 'ID') {
return @ID;
}
if ($Param{Result} && $Param{Result} eq 'Name') {
return @Name;
}
else {
return %Users;
}
}
# --
For the function GroupUserList, It's the same idea except that it returns an array which contains groups.
# --
sub GroupUserList {
my $Self = shift;
my %Param = @_;
# --
# check needed stuff
# --
foreach (qw(Result Type UserID)) {
if (!$Param{$_}) {
$Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
return;
}
}
my %Groups = ();
my @Name = ();
my @ID = ();
my $SQL = "SELECT g.id, g.name, gu.permission_read, gu.permission_write, gu.permission_move " .
" FROM " .
" groups g, group_user gu".
" WHERE " .
" g.valid_id in ( ${\(join ', ', $Self->{DBObject}->GetValidIDs())} ) ".
" AND ".
" gu.user_id = $Param{UserID}".
" AND " .
" g.id = gu.group_id ";
$Self->{DBObject}->Prepare(SQL => $SQL);
while (my @Row = $Self->{DBObject}->FetchrowArray()) {
# read only
# change by EPT - we return the result if we a permission read, write or none
if ($Param{Type} eq 'ro') {
if ($Row[3] || $Row[2] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# read/write
# change by EPT - we return the result if we a permission write or none
elsif ($Param{Type} eq 'rw') {
if ($Row[3] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# move (add by EPT)
elsif ($Param{Type} eq 'mv') {
# EPT - we return the result if we a permission move or none
if ($Row[4] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
else {
$Self->{LogObject}->Log(Priority => 'error', Message => "Type '$Param{Type}' dosn't exist!");
return;
}
}
if ($Param{Result} && $Param{Result} eq 'ID') {
return @ID;
}
if ($Param{Result} && $Param{Result} eq 'Name') {
return @Name;
}
else {
return %Groups;
}
}
# --
We add a mv CheckBoxes column into the "HTML table" :
# --
sub AdminUserGroupChangeForm {
my $Self = shift;
my %Param = @_;
my %Data = %{$Param{Data}};
my $BaseLink = $Self->{Baselink};
my $Type = $Param{Type} || 'User';
my $NeType = 'Group';
$NeType = 'User' if ($Type eq 'Group');
$Param{OptionStrg0} .= "<B>\$Text{\"$Type\"}:</B> <A HREF=\"$BaseLink"."Action=Admin$Type&Subaction=Change&ID=$Param{ID}\">" .
"$Param{Name}</A> (id=$Param{ID})<BR>";
$Param{OptionStrg0} .= '<INPUT TYPE="hidden" NAME="ID" VALUE="'.$Param{ID}.'"><BR>';
$Param{OptionStrg0} .= "<br>\n";
$Param{OptionStrg0} .= "<table>\n";
# Change by EPT -> Permission move
# $Param{OptionStrg0} .= "<tr><th>\$Text{\"$NeType\"}</th><th>ro</th><th>rw</th></tr>\n";
$Param{OptionStrg0} .= "<tr><th>\$Text{\"$NeType\"}</th><th>mv</th><th>ro</th><th>rw</th></tr>\n";
foreach (sort {uc($Data{$a}) cmp uc($Data{$b})} keys %Data){
$Param{OptionStrg0} .= '<tr><td>';
$Param{OptionStrg0} .= "<a href=\"$BaseLink"."Action=Admin$NeType&Subaction=Change&ID=$_\">$Param{Data}->{$_}</a>";
# add by EPT -> permission_move
my $MvSelected = '';
if ($Param{Mv}->{$_}) {
$MvSelected = ' checked';
}
$Param{OptionStrg0} .= '</td><td>';
$Param{OptionStrg0} .= '<input type="checkbox" name="MvIDs" value="'.$_."\"$MvSelected>";
# end add EPT
my $RoSelected = '';
if ($Param{Ro}->{$_}) {
$RoSelected = ' checked';
}
$Param{OptionStrg0} .= '</td><td>';
$Param{OptionStrg0} .= '<input type="checkbox" name="RoIDs" value="'.$_."\"$RoSelected>";
my $RwSelected = '';
if ($Param{Rw}->{$_}) {
$RwSelected = ' checked';
}
$Param{OptionStrg0} .= '</td><td>';
$Param{OptionStrg0} .= '<input type="checkbox" name="RwIDs" value="'.$_."\"$RwSelected>";
$Param{OptionStrg0} .= '</td></tr>';
}
$Param{OptionStrg0} .= "</table>\n";
return $Self->Output(TemplateFile => 'AdminUserGroupChangeForm', Data => \%Param);
}
# --
Rq :
we display the column mv in first position because it's the smallest permission into OTRS.
When there is no subaction, so the program will simply display the list of users and groups. If we click on one of them, we will set the subaction to "User" or "Group".
The subactions "User" or "Group" will call the function AdministrationUserGroupForm for displaying information about permissions.
This function receive in input the complete list of groups (or user, depend of the subaction), all permissions arrays returnin by the function GroupUserList (or GroupMemberList), information about user (or group), and the type of the page to display
So, we just have to retrieve the new move permission array and add it into called function's parameters.
When we click on the submit button, we set subactions to "ChangeUser" or "ChangeGroup". These will call the function GroupMemberAdd for updting permissions.
In fact, for each group (if we update the user) or user (if we update the group) we will call the function GroupMemberAdd after setting permissions for the couple user/group. The permissions are retreive from the HTML page as an array.
So, we just have to another array for move permissions and we add the parameter "move" for the function GroupMemberAdd.
# --
sub Run {
my $Self = shift;
my %Param = @_;
my $Output = '';
my $UserID = $Self->{UserID};
my $ID = $Self->{ParamObject}->GetParam(Param => 'ID') || '';
$Param{NextScreen} = 'AdminUserGroup';
# user <-> group 1:n
if ($Self->{Subaction} eq 'User') {
$Output .= $Self->{LayoutObject}->Header(Title => 'User <-> Group');
$Output .= $Self->{LayoutObject}->AdminNavigationBar();
# get user data
my %UserData = $Self->{UserObject}->GetUserData(UserID => $ID);
# get group data
my %GroupData = $Self->{GroupObject}->GroupList(Valid => 1);
my %Read = $Self->{GroupObject}->GroupUserList(
UserID => $ID,
Type => 'ro',
Result => 'HASH',
);
my %Write = $Self->{GroupObject}->GroupUserList(
UserID => $ID,
Type => 'rw',
Result => 'HASH',
);
# add by EPT -> permission_move
my %Move = $Self->{GroupObject}->GroupUserList(
UserID => $ID,
Type => 'mv',
Result => 'HASH',
);
$Output .= $Self->{LayoutObject}->AdminUserGroupChangeForm(
Data => \%GroupData,
Ro => \%Read,
Rw => \%Write,
Mv => \%Move, # add by EPT -> Permission_move
ID => $UserData{UserID},
Name => $UserData{UserLogin},
Type => 'User',
);
$Output .= $Self->{LayoutObject}->Footer();
}
# group <-> user n:1
elsif ($Self->{Subaction} eq 'Group') {
$Output .= $Self->{LayoutObject}->Header(Title => 'User <-> Group');
$Output .= $Self->{LayoutObject}->AdminNavigationBar();
# get user data
my %UserData = $Self->{UserObject}->UserList(Valid => 1);
foreach (keys %UserData) {
# get user data
my %User = $Self->{UserObject}->GetUserData(UserID => $_, Cached => 1);
if ($User{UserFirstname} && $User{UserLastname}) {
$UserData{$_} .= " ($User{UserFirstname} $User{UserLastname})";
}
}
# get ro list users
my %Read = $Self->{GroupObject}->GroupMemberList(
GroupID => $ID,
Type => 'ro',
Result => 'HASH',
);
# get rw list users
my %Write = $Self->{GroupObject}->GroupMemberList(
GroupID => $ID,
Type => 'rw',
Result => 'HASH',
);
# add by EPT -> get mv list users
my %Move = $Self->{GroupObject}->GroupMemberList(
GroupID => $ID,
Type => 'mv',
Result => 'HASH',
);
# get group data
my %GroupData = $Self->{GroupObject}->GroupGet(ID => $ID);
$Output .= $Self->{LayoutObject}->AdminUserGroupChangeForm(
Ro => \%Read,
Rw => \%Write,
Mv => \%Move, # add by EPT -> Permission_move
Data => \%UserData,
ID => $GroupData{ID},
Name => $GroupData{Name},
Type => 'Group',
);
$Output .= $Self->{LayoutObject}->Footer();
}
# add user to groups
elsif ($Self->{Subaction} eq 'ChangeGroup') {
# get new groups
my @RoIDs = $Self->{ParamObject}->GetArray(Param => 'RoIDs');
my @RwIDs = $Self->{ParamObject}->GetArray(Param => 'RwIDs');
my @MvIDs = $Self->{ParamObject}->GetArray(Param => 'MvIDs'); # add by EPT -> permission_move (cf Admin.pm)
# get group data
my %UserData = $Self->{UserObject}->UserList(Valid => 1);
foreach (keys %UserData) {
my $Ro = 0;
my $Rw = 0;
my $Mv = 0; # add by EPT -> permission move
foreach my $ID (@RoIDs) {
if ($_ == $ID) {
$Ro = 1;
}
}
foreach my $ID (@RwIDs) {
if ($_ == $ID) {
$Rw = 1;
}
}
# add by EPT -> Permission_move
foreach my $ID (@MvIDs) {
if ($_ == $ID) {
$Mv = 1;
}
}
$Self->{GroupObject}->GroupMemberAdd(
UID => $_,
GID => $ID,
Ro => $Ro,
Rw => $Rw,
Mv => $Mv, # add by EPT -> Permission_move
UserID => $Self->{UserID},
);
}
$Output .= $Self->{LayoutObject}->Redirect(OP => "Action=$Param{NextScreen}");
}
# groups to user
elsif ($Self->{Subaction} eq 'ChangeUser') {
# get new groups
my @RoIDs = $Self->{ParamObject}->GetArray(Param => 'RoIDs');
my @RwIDs = $Self->{ParamObject}->GetArray(Param => 'RwIDs');
my @MvIDs = $Self->{ParamObject}->GetArray(Param => 'MvIDs'); # add by EPT -> permission_move (cf Admin.pm)
# get group data
my %GroupData = $Self->{GroupObject}->GroupList(Valid => 1);
foreach (keys %GroupData) {
my $Ro = 0;
my $Rw = 0;
my $Mv = 0; # add by EPT
foreach my $ID (@RoIDs) {
if ($_ == $ID) {
$Ro = 1;
}
}
foreach my $ID (@RwIDs) {
if ($_ == $ID) {
$Rw = 1;
}
}
# add by EPT -> Permission_move
foreach my $ID (@MvIDs) {
if ($_ == $ID) {
$Mv = 1;
}
}
$Self->{GroupObject}->GroupMemberAdd(
UID => $ID,
GID => $_,
Ro => $Ro,
Rw => $Rw,
Mv => $Mv, # add by EPT -> Permission_move
UserID => $Self->{UserID},
);
}
$Output .= $Self->{LayoutObject}->Redirect(OP => "Action=$Param{NextScreen}");
}
# else ! print form
else {
$Output .= $Self->{LayoutObject}->Header(Title => 'User <-> Group');
$Output .= $Self->{LayoutObject}->AdminNavigationBar();
# get user data
my %UserData = $Self->{UserObject}->UserList(Valid => 1);
foreach (keys %UserData) {
# get user data
my %User = $Self->{UserObject}->GetUserData(UserID => $_, Cached => 1);
if ($User{UserFirstname} && $User{UserLastname}) {
$UserData{$_} .= " ($User{UserFirstname} $User{UserLastname})";
}
}
# get group data
my %GroupData = $Self->{GroupObject}->GroupList(Valid => 1);
$Output .= $Self->{LayoutObject}->AdminUserGroupForm(
GroupData => \%GroupData,
UserData => \%UserData,
);
$Output .= $Self->{LayoutObject}->Footer();
}
return $Output;
}
# --
These files are located in the directory /opt/otrs/Kernel/Modules/ : AgentClose.pm, AgentMove.pm, AgentQueueView.pm, AgentZoom.pm
There are the same code part into these programs which get Destination Queues for moving. We just have to change the permission type to move for getting Destination Queues (a Queue is attach to a group, so we get first groups when user has permissions and then the Queues into function GetAllQueues)
my %MoveQueues = ();
if ($Self->{ConfigObject}->Get('MoveInToAllQueues')) {
%MoveQueues = $Self->{QueueObject}->GetAllQueues();
}
else {
%MoveQueues = $Self->{QueueObject}->GetAllQueues(
UserID => $Self->{UserID},
# Change by EPT -> mv permission, we can only move to Queues where we have group permission move
# Type => 'rw',
Type => 'mv',
);
}
As for the Read Only permission type, in the case of move, we will also insert the name when there is a write permission for the couple user/group.
# --
sub GroupMemberList {
my $Self = shift;
my %Param = @_;
# --
# check needed stuff
# --
foreach (qw(Result Type GroupID)) {
if (!$Param{$_}) {
$Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
return;
}
}
my %Users = ();
my @Name = ();
my @ID = ();
my $SQL = "SELECT u.id, u.login, gu.permission_read, gu.permission_write, gu.permission_move " .
" FROM " .
" $Self->{ConfigObject}->{DatabaseUserTable} u, group_user gu".
" WHERE " .
" u.valid_id in ( ${\(join ', ', $Self->{DBObject}->GetValidIDs())} ) ".
" AND ".
" gu.group_id = $Param{GroupID}".
" AND " .
" u.id = gu.user_id ";
$Self->{DBObject}->Prepare(SQL => $SQL);
while (my @Row = $Self->{DBObject}->FetchrowArray()) {
# read only
# change by EPT - we return the result if we a permission read, write or none
if ($Param{Type} eq 'ro') {
if ($Row[3] || $Row[2] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# read/write
# change by EPT - we return the result if we a permission write or none
elsif ($Param{Type} eq 'rw') {
if ($Row[3] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# move (add by EPT)
elsif ($Param{Type} eq 'mv') {
# EPT - we return the result if we a permission write, move or none
if ($Row[3] || $Row[4] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
else {
$Self->{LogObject}->Log(Priority => 'error', Message => "Type '$Param{Type}' dosn't exist!");
return;
}
}
if ($Param{Result} && $Param{Result} eq 'ID') {
return @ID;
}
if ($Param{Result} && $Param{Result} eq 'Name') {
return @Name;
}
else {
return %Users;
}
}
# --
# --
sub GroupUserList {
my $Self = shift;
my %Param = @_;
# --
# check needed stuff
# --
foreach (qw(Result Type UserID)) {
if (!$Param{$_}) {
$Self->{LogObject}->Log(Priority => 'error', Message => "Need $_!");
return;
}
}
my %Groups = ();
my @Name = ();
my @ID = ();
my $SQL = "SELECT g.id, g.name, gu.permission_read, gu.permission_write, gu.permission_move " .
" FROM " .
" groups g, group_user gu".
" WHERE " .
" g.valid_id in ( ${\(join ', ', $Self->{DBObject}->GetValidIDs())} ) ".
" AND ".
" gu.user_id = $Param{UserID}".
" AND " .
" g.id = gu.group_id ";
$Self->{DBObject}->Prepare(SQL => $SQL);
while (my @Row = $Self->{DBObject}->FetchrowArray()) {
# read only
# change by EPT - we return the result if we a permission read, write or none
if ($Param{Type} eq 'ro') {
if ($Row[3] || $Row[2] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# read/write
# change by EPT - we return the result if we a permission write or none
elsif ($Param{Type} eq 'rw') {
if ($Row[3] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
# move (add by EPT)
elsif ($Param{Type} eq 'mv') {
# EPT - we return the result if we a permission write, move or none
if ($Row[3] || $Row[4] || (!$Row[2] && !$Row[3] && !$Row[4])) {
$Users{$Row[0]} = $Row[1];
push (@Name, $Row[1]);
push (@ID, $Row[0]);
}
}
else {
$Self->{LogObject}->Log(Priority => 'error', Message => "Type '$Param{Type}' dosn't exist!");
return;
}
}
if ($Param{Result} && $Param{Result} eq 'ID') {
return @ID;
}
if ($Param{Result} && $Param{Result} eq 'Name') {
return @Name;
}
else {
return %Groups;
}
}
# --