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;

}

}

# --