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::Group;
10
11use strict;
12use warnings;
13
14our @ObjectDependencies = (
15    'Kernel::Config',
16    'Kernel::System::Cache',
17    'Kernel::System::DB',
18    'Kernel::System::Log',
19    'Kernel::System::User',
20    'Kernel::System::Valid',
21);
22
23=head1 NAME
24
25Kernel::System::Group - group and roles lib
26
27=head1 DESCRIPTION
28
29All group and roles functions. E. g. to add groups or to get a member list of a group.
30
31=head1 PUBLIC INTERFACE
32
33=head2 new()
34
35Don't use the constructor directly, use the ObjectManager instead:
36
37    my $GroupObject = $Kernel::OM->Get('Kernel::System::Group');
38
39=cut
40
41sub new {
42    my ( $Type, %Param ) = @_;
43
44    # allocate new hash for object
45    my $Self = {};
46    bless( $Self, $Type );
47
48    return $Self;
49}
50
51=head2 GroupLookup()
52
53get id or name for group
54
55    my $Group = $GroupObject->GroupLookup(
56        GroupID => $GroupID,
57    );
58
59    my $GroupID = $GroupObject->GroupLookup(
60        Group => $Group,
61    );
62
63=cut
64
65sub GroupLookup {
66    my ( $Self, %Param ) = @_;
67
68    # check needed stuff
69    if ( !$Param{Group} && !$Param{GroupID} ) {
70        $Kernel::OM->Get('Kernel::System::Log')->Log(
71            Priority => 'error',
72            Message  => 'Need Group or GroupID!',
73        );
74        return;
75    }
76
77    # get group list
78    my %GroupList = $Self->GroupList(
79        Valid => 0,
80    );
81
82    return $GroupList{ $Param{GroupID} } if $Param{GroupID};
83
84    # create reverse list
85    my %GroupListReverse = reverse %GroupList;
86
87    return $GroupListReverse{ $Param{Group} };
88}
89
90=head2 GroupAdd()
91
92to add a group
93
94    my $ID = $GroupObject->GroupAdd(
95        Name    => 'example-group',
96        Comment => 'comment describing the group',   # optional
97        ValidID => 1,
98        UserID  => 123,
99    );
100
101=cut
102
103sub GroupAdd {
104    my ( $Self, %Param ) = @_;
105
106    # check needed stuff
107    for my $Needed (qw(Name ValidID UserID)) {
108        if ( !$Param{$Needed} ) {
109            $Kernel::OM->Get('Kernel::System::Log')->Log(
110                Priority => 'error',
111                Message  => "Need $Needed!",
112            );
113            return;
114        }
115    }
116
117    my %ExistingGroups = reverse $Self->GroupList( Valid => 0 );
118    if ( defined $ExistingGroups{ $Param{Name} } ) {
119        $Kernel::OM->Get('Kernel::System::Log')->Log(
120            Priority => 'error',
121            Message  => "A group with the name '$Param{Name}' already exists.",
122        );
123        return;
124    }
125
126    # get database object
127    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
128
129    # insert new group
130    return if !$DBObject->Do(
131        SQL => 'INSERT INTO groups (name, comments, valid_id, '
132            . ' create_time, create_by, change_time, change_by)'
133            . ' VALUES (?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
134        Bind => [
135            \$Param{Name}, \$Param{Comment}, \$Param{ValidID}, \$Param{UserID}, \$Param{UserID},
136        ],
137    );
138
139    # get new group id
140    return if !$DBObject->Prepare(
141        SQL  => 'SELECT id FROM groups WHERE name = ?',
142        Bind => [ \$Param{Name} ],
143    );
144
145    my $GroupID;
146    while ( my @Row = $DBObject->FetchrowArray() ) {
147        $GroupID = $Row[0];
148    }
149
150    # get cache object
151    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
152
153    # delete caches
154    $CacheObject->Delete(
155        Type => 'Group',
156        Key  => 'GroupDataList',
157    );
158    $CacheObject->Delete(
159        Type => 'Group',
160        Key  => 'GroupList::0',
161    );
162    $CacheObject->Delete(
163        Type => 'Group',
164        Key  => 'GroupList::1',
165    );
166    $CacheObject->CleanUp(
167        Type => 'CustomerGroup',
168    );
169
170    return $GroupID;
171}
172
173=head2 GroupGet()
174
175returns a hash with group data
176
177    my %GroupData = $GroupObject->GroupGet(
178        ID => 2,
179    );
180
181This returns something like:
182
183    %GroupData = (
184        'Name'       => 'admin',
185        'ID'         => 2,
186        'ValidID'    => '1',
187        'CreateTime' => '2010-04-07 15:41:15',
188        'ChangeTime' => '2010-04-07 15:41:15',
189        'Comment'    => 'Group of all administrators.',
190    );
191
192=cut
193
194sub GroupGet {
195    my ( $Self, %Param ) = @_;
196
197    # check needed stuff
198    if ( !$Param{ID} ) {
199        $Kernel::OM->Get('Kernel::System::Log')->Log(
200            Priority => 'error',
201            Message  => 'Need ID!',
202        );
203        return;
204    }
205
206    # get group list
207    my %GroupList = $Self->GroupDataList(
208        Valid => 0,
209    );
210
211    # extract group data
212    my %Group;
213    if ( $GroupList{ $Param{ID} } && ref $GroupList{ $Param{ID} } eq 'HASH' ) {
214        %Group = %{ $GroupList{ $Param{ID} } };
215    }
216
217    return %Group;
218}
219
220=head2 GroupUpdate()
221
222update of a group
223
224    my $Success = $GroupObject->GroupUpdate(
225        ID      => 123,
226        Name    => 'example-group',
227        Comment => 'comment describing the group',   # optional
228        ValidID => 1,
229        UserID  => 123,
230    );
231
232=cut
233
234sub GroupUpdate {
235    my ( $Self, %Param ) = @_;
236
237    # check needed stuff
238    for my $Needed (qw(ID Name ValidID UserID)) {
239        if ( !$Param{$Needed} ) {
240            $Kernel::OM->Get('Kernel::System::Log')->Log(
241                Priority => 'error',
242                Message  => "Need $Needed!",
243            );
244            return;
245        }
246    }
247
248    my %ExistingGroups = reverse $Self->GroupList( Valid => 0 );
249    if ( defined $ExistingGroups{ $Param{Name} } && $ExistingGroups{ $Param{Name} } != $Param{ID} ) {
250        $Kernel::OM->Get('Kernel::System::Log')->Log(
251            Priority => 'error',
252            Message  => "A group with the name '$Param{Name}' already exists.",
253        );
254        return;
255    }
256
257    # set default value
258    $Param{Comment} ||= '';
259
260    # get current group data
261    my %GroupData = $Self->GroupGet(
262        ID => $Param{ID},
263    );
264
265    # check if update is required
266    my $ChangeRequired;
267    KEY:
268    for my $Key (qw(Name Comment ValidID)) {
269
270        next KEY if defined $GroupData{$Key} && $GroupData{$Key} eq $Param{$Key};
271
272        $ChangeRequired = 1;
273
274        last KEY;
275    }
276
277    return 1 if !$ChangeRequired;
278
279    # get database object
280    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
281
282    # update group in database
283    return if !$DBObject->Do(
284        SQL => 'UPDATE groups SET name = ?, comments = ?, valid_id = ?, '
285            . 'change_time = current_timestamp, change_by = ? WHERE id = ?',
286        Bind => [
287            \$Param{Name}, \$Param{Comment}, \$Param{ValidID}, \$Param{UserID}, \$Param{ID},
288        ],
289    );
290
291    # get cache object
292    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
293
294    # delete caches
295    $CacheObject->Delete(
296        Type => 'Group',
297        Key  => 'GroupDataList',
298    );
299    $CacheObject->Delete(
300        Type => 'Group',
301        Key  => 'GroupList::0',
302    );
303    $CacheObject->Delete(
304        Type => 'Group',
305        Key  => 'GroupList::1',
306    );
307    $CacheObject->CleanUp(
308        Type => 'CustomerGroup',
309    );
310
311    return 1 if $GroupData{ValidID} eq $Param{ValidID};
312
313    $CacheObject->CleanUp(
314        Type => 'GroupPermissionUserGet',
315    );
316    $CacheObject->CleanUp(
317        Type => 'GroupPermissionGroupGet',
318    );
319
320    return 1;
321}
322
323=head2 GroupList()
324
325returns a hash of all groups
326
327    my %Groups = $GroupObject->GroupList(
328        Valid => 1,   # (optional) default 0
329    );
330
331the result looks like
332
333    %Groups = (
334        '1' => 'users',
335        '2' => 'admin',
336        '3' => 'stats',
337        '4' => 'secret',
338    );
339
340=cut
341
342sub GroupList {
343    my ( $Self, %Param ) = @_;
344
345    # set default value
346    my $Valid = $Param{Valid} ? 1 : 0;
347
348    # get cache object
349    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
350
351    # create cache key
352    my $CacheKey = 'GroupList::' . $Valid;
353
354    # read cache
355    my $Cache = $CacheObject->Get(
356        Type => 'Group',
357        Key  => $CacheKey,
358    );
359    return %{$Cache} if $Cache;
360
361    # get valid ids
362    my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet();
363
364    # get group data list
365    my %GroupDataList = $Self->GroupDataList();
366
367    my %GroupListValid;
368    my %GroupListAll;
369    KEY:
370    for my $Key ( sort keys %GroupDataList ) {
371
372        next KEY if !$Key;
373
374        # add group to the list of all groups
375        $GroupListAll{$Key} = $GroupDataList{$Key}->{Name};
376
377        my $Match;
378        VALIDID:
379        for my $ValidID (@ValidIDs) {
380
381            next VALIDID if $ValidID ne $GroupDataList{$Key}->{ValidID};
382
383            $Match = 1;
384
385            last VALIDID;
386        }
387
388        next KEY if !$Match;
389
390        # add group to the list of valid groups
391        $GroupListValid{$Key} = $GroupDataList{$Key}->{Name};
392    }
393
394    # set cache
395    $CacheObject->Set(
396        Type  => 'Group',
397        Key   => 'GroupList::0',
398        TTL   => 60 * 60 * 24 * 20,
399        Value => \%GroupListAll,
400    );
401    $CacheObject->Set(
402        Type  => 'Group',
403        Key   => 'GroupList::1',
404        TTL   => 60 * 60 * 24 * 20,
405        Value => \%GroupListValid,
406    );
407
408    return %GroupListValid if $Valid;
409    return %GroupListAll;
410}
411
412=head2 GroupDataList()
413
414returns a hash of all group data
415
416    my %GroupDataList = $GroupObject->GroupDataList();
417
418the result looks like
419
420    %GroupDataList = (
421        1 => {
422            ID         => 1,
423            Name       => 'Group 1',
424            Comment    => 'The Comment of Group 1',
425            ValidID    => 1,
426            CreateTime => '2014-01-01 00:20:00',
427            CreateBy   => 1,
428            ChangeTime => '2014-01-02 00:10:00',
429            ChangeBy   => 1,
430        },
431        2 => {
432            ID         => 2,
433            Name       => 'Group 2',
434            Comment    => 'The Comment of Group 2',
435            ValidID    => 1,
436            CreateTime => '2014-11-01 10:00:00',
437            CreateBy   => 1,
438            ChangeTime => '2014-11-02 01:00:00',
439            ChangeBy   => 1,
440        },
441    );
442
443=cut
444
445sub GroupDataList {
446    my ( $Self, %Param ) = @_;
447
448    # get cache object
449    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
450
451    # read cache
452    my $Cache = $CacheObject->Get(
453        Type => 'Group',
454        Key  => 'GroupDataList',
455    );
456    return %{$Cache} if $Cache;
457
458    # get database object
459    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
460
461    # get all group data from database
462    return if !$DBObject->Prepare(
463        SQL => 'SELECT id, name, comments, valid_id, create_time, create_by, change_time, change_by FROM groups',
464    );
465
466    # fetch the result
467    my %GroupDataList;
468    while ( my @Row = $DBObject->FetchrowArray() ) {
469
470        $GroupDataList{ $Row[0] } = {
471            ID         => $Row[0],
472            Name       => $Row[1],
473            Comment    => $Row[2] || '',
474            ValidID    => $Row[3],
475            CreateTime => $Row[4],
476            CreateBy   => $Row[5],
477            ChangeTime => $Row[6],
478            ChangeBy   => $Row[7],
479        };
480    }
481
482    # set cache
483    $CacheObject->Set(
484        Type  => 'Group',
485        Key   => 'GroupDataList',
486        TTL   => 60 * 60 * 24 * 20,
487        Value => \%GroupDataList,
488    );
489
490    return %GroupDataList;
491}
492
493=head2 RoleLookup()
494
495get id or name for role
496
497    my $Role = $GroupObject->RoleLookup(
498        RoleID => $RoleID,
499    );
500
501    my $RoleID = $GroupObject->RoleLookup(
502        Role => $Role,
503    );
504
505=cut
506
507sub RoleLookup {
508    my ( $Self, %Param ) = @_;
509
510    # check needed stuff
511    if ( !$Param{Role} && !$Param{RoleID} ) {
512        $Kernel::OM->Get('Kernel::System::Log')->Log(
513            Priority => 'error',
514            Message  => 'Got no Role or RoleID!',
515        );
516        return;
517    }
518
519    # get role list
520    my %RoleList = $Self->RoleList(
521        Valid => 0,
522    );
523
524    return $RoleList{ $Param{RoleID} } if $Param{RoleID};
525
526    # create reverse list
527    my %RoleListReverse = reverse %RoleList;
528
529    return $RoleListReverse{ $Param{Role} };
530}
531
532=head2 RoleGet()
533
534returns a hash with role data
535
536    my %RoleData = $GroupObject->RoleGet(
537        ID => 2,
538    );
539
540This returns something like:
541
542    %RoleData = (
543        'Name'       => 'role_helpdesk_agent',
544        'ID'         => 2,
545        'ValidID'    => '1',
546        'CreateTime' => '2010-04-07 15:41:15',
547        'ChangeTime' => '2010-04-07 15:41:15',
548        'Comment'    => 'Role for help-desk people.',
549    );
550
551=cut
552
553sub RoleGet {
554    my ( $Self, %Param ) = @_;
555
556    # check needed stuff
557    if ( !$Param{ID} ) {
558        $Kernel::OM->Get('Kernel::System::Log')->Log(
559            Priority => 'error',
560            Message  => 'Need ID!'
561        );
562        return;
563    }
564
565    # get role list
566    my %RoleList = $Self->RoleDataList(
567        Valid => 0,
568    );
569
570    # extract role data
571    my %Role;
572    if ( $RoleList{ $Param{ID} } && ref $RoleList{ $Param{ID} } eq 'HASH' ) {
573        %Role = %{ $RoleList{ $Param{ID} } };
574    }
575
576    return %Role;
577}
578
579=head2 RoleAdd()
580
581to add a new role
582
583    my $RoleID = $GroupObject->RoleAdd(
584        Name    => 'example-role',
585        Comment => 'comment describing the role',   # optional
586        ValidID => 1,
587        UserID  => 123,
588    );
589
590=cut
591
592sub RoleAdd {
593    my ( $Self, %Param ) = @_;
594
595    # check needed stuff
596    for my $Needed (qw(Name ValidID UserID)) {
597        if ( !$Param{$Needed} ) {
598            $Kernel::OM->Get('Kernel::System::Log')->Log(
599                Priority => 'error',
600                Message  => "Need $Needed!"
601            );
602            return;
603        }
604    }
605
606    my %ExistingRoles = reverse $Self->RoleList( Valid => 0 );
607    if ( defined $ExistingRoles{ $Param{Name} } ) {
608        $Kernel::OM->Get('Kernel::System::Log')->Log(
609            Priority => 'error',
610            Message  => "A role with the name '$Param{Name}' already exists.",
611        );
612        return;
613    }
614
615    # get database object
616    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
617
618    # insert
619    return if !$DBObject->Do(
620        SQL => 'INSERT INTO roles (name, comments, valid_id, '
621            . 'create_time, create_by, change_time, change_by) '
622            . 'VALUES (?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
623        Bind => [
624            \$Param{Name}, \$Param{Comment}, \$Param{ValidID}, \$Param{UserID}, \$Param{UserID}
625        ],
626    );
627
628    # get new group id
629    my $RoleID;
630    return if !$DBObject->Prepare(
631        SQL  => 'SELECT id FROM roles WHERE name = ?',
632        Bind => [ \$Param{Name}, ],
633    );
634
635    # fetch the result
636    while ( my @Row = $DBObject->FetchrowArray() ) {
637        $RoleID = $Row[0];
638    }
639
640    # get cache object
641    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
642
643    # delete caches
644    $CacheObject->Delete(
645        Type => 'Group',
646        Key  => 'RoleDataList',
647    );
648    $CacheObject->Delete(
649        Type => 'Group',
650        Key  => 'RoleList::0',
651    );
652    $CacheObject->Delete(
653        Type => 'Group',
654        Key  => 'RoleList::1',
655    );
656
657    return $RoleID;
658}
659
660=head2 RoleUpdate()
661
662update of a role
663
664    my $Success = $GroupObject->RoleUpdate(
665        ID      => 123,
666        Name    => 'example-group',
667        Comment => 'comment describing the role',   # optional
668        ValidID => 1,
669        UserID  => 123,
670    );
671
672=cut
673
674sub RoleUpdate {
675    my ( $Self, %Param ) = @_;
676
677    # check needed stuff
678    for (qw(ID Name ValidID UserID)) {
679        if ( !$Param{$_} ) {
680            $Kernel::OM->Get('Kernel::System::Log')->Log(
681                Priority => 'error',
682                Message  => "Need $_!",
683            );
684            return;
685        }
686    }
687
688    my %ExistingRoles = reverse $Self->RoleList( Valid => 0 );
689    if ( defined $ExistingRoles{ $Param{Name} } && $ExistingRoles{ $Param{Name} } != $Param{ID} ) {
690        $Kernel::OM->Get('Kernel::System::Log')->Log(
691            Priority => 'error',
692            Message  => "A role with the name '$Param{Name}' already exists.",
693        );
694        return;
695    }
696
697    # set default value
698    $Param{Comment} ||= '';
699
700    # get current role data
701    my %RoleData = $Self->RoleGet(
702        ID => $Param{ID},
703    );
704
705    # check if update is required
706    my $ChangeRequired;
707    KEY:
708    for my $Key (qw(Name Comment ValidID)) {
709
710        next KEY if defined $RoleData{$Key} && $RoleData{$Key} eq $Param{$Key};
711
712        $ChangeRequired = 1;
713
714        last KEY;
715    }
716
717    return 1 if !$ChangeRequired;
718
719    # update role in database
720    return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
721        SQL => 'UPDATE roles SET name = ?, comments = ?, valid_id = ?, '
722            . 'change_time = current_timestamp, change_by = ? WHERE id = ?',
723        Bind => [
724            \$Param{Name}, \$Param{Comment}, \$Param{ValidID}, \$Param{UserID}, \$Param{ID}
725        ],
726    );
727
728    # get cache object
729    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
730
731    # delete caches
732    $CacheObject->Delete(
733        Type => 'Group',
734        Key  => 'RoleDataList',
735    );
736    $CacheObject->Delete(
737        Type => 'Group',
738        Key  => 'RoleList::0',
739    );
740    $CacheObject->Delete(
741        Type => 'Group',
742        Key  => 'RoleList::1',
743    );
744
745    return 1 if $RoleData{ValidID} eq $Param{ValidID};
746
747    $CacheObject->CleanUp(
748        Type => 'GroupPermissionUserGet',
749    );
750    $CacheObject->CleanUp(
751        Type => 'GroupPermissionGroupGet',
752    );
753
754    return 1;
755}
756
757=head2 RoleList()
758
759returns a hash of all roles
760
761    my %Roles = $GroupObject->RoleList(
762        Valid => 1,
763    );
764
765the result looks like
766
767    %Roles = (
768        '1' => 'role_helpdesk_agent',
769        '2' => 'role_systemsmanagement_agent',
770        '3' => 'role_otrs_admin',
771        '4' => 'role_faq_manager',
772    );
773
774=cut
775
776sub RoleList {
777    my ( $Self, %Param ) = @_;
778
779    # set default value
780    my $Valid = $Param{Valid} ? 1 : 0;
781
782    # get cache object
783    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
784
785    # create cache key
786    my $CacheKey = 'RoleList::' . $Valid;
787
788    # read cache
789    my $Cache = $CacheObject->Get(
790        Type => 'Group',
791        Key  => $CacheKey,
792    );
793    return %{$Cache} if $Cache;
794
795    # get valid ids
796    my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet();
797
798    # get role data list
799    my %RoleDataList = $Self->RoleDataList();
800
801    my %RoleListValid;
802    my %RoleListAll;
803    KEY:
804    for my $Key ( sort keys %RoleDataList ) {
805
806        next KEY if !$Key;
807
808        # add role to the list of all roles
809        $RoleListAll{$Key} = $RoleDataList{$Key}->{Name};
810
811        my $Match;
812        VALIDID:
813        for my $ValidID (@ValidIDs) {
814
815            next VALIDID if $ValidID ne $RoleDataList{$Key}->{ValidID};
816
817            $Match = 1;
818
819            last VALIDID;
820        }
821
822        next KEY if !$Match;
823
824        # add role to the list of valid roles
825        $RoleListValid{$Key} = $RoleDataList{$Key}->{Name};
826    }
827
828    # set cache
829    $CacheObject->Set(
830        Type  => 'Group',
831        Key   => 'RoleList::0',
832        TTL   => 60 * 60 * 24 * 20,
833        Value => \%RoleListAll,
834    );
835    $CacheObject->Set(
836        Type  => 'Group',
837        Key   => 'RoleList::1',
838        TTL   => 60 * 60 * 24 * 20,
839        Value => \%RoleListValid,
840    );
841
842    return %RoleListValid if $Valid;
843    return %RoleListAll;
844}
845
846=head2 RoleDataList()
847
848returns a hash of all role data
849
850    my %RoleDataList = $GroupObject->RoleDataList();
851
852the result looks like
853
854    %RoleDataList = (
855        1 => {
856            ID         => 1,
857            Name       => 'Role 1',
858            Comment    => 'The Comment of Role 1',
859            ValidID    => 1,
860            CreateTime => '2014-01-01 00:20:00',
861            CreateBy   => 1,
862            ChangeTime => '2014-01-02 00:10:00',
863            ChangeBy   => 1,
864        },
865        2 => {
866            ID         => 2,
867            Name       => 'Role 2',
868            Comment    => 'The Comment of Role 2',
869            ValidID    => 1,
870            CreateTime => '2014-11-01 10:00:00',
871            CreateBy   => 1,
872            ChangeTime => '2014-11-02 01:00:00',
873            ChangeBy   => 1,
874        },
875    );
876
877=cut
878
879sub RoleDataList {
880    my ( $Self, %Param ) = @_;
881
882    # get cache object
883    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
884
885    # read cache
886    my $Cache = $CacheObject->Get(
887        Type => 'Group',
888        Key  => 'RoleDataList',
889    );
890    return %{$Cache} if $Cache;
891
892    # get database object
893    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
894
895    # get all roles data from database
896    return if !$DBObject->Prepare(
897        SQL => 'SELECT id, name, comments, valid_id, create_time, create_by, change_time, change_by FROM roles',
898    );
899
900    # fetch the result
901    my %RoleDataList;
902    while ( my @Row = $DBObject->FetchrowArray() ) {
903
904        $RoleDataList{ $Row[0] } = {
905            ID         => $Row[0],
906            Name       => $Row[1],
907            Comment    => $Row[2] || '',
908            ValidID    => $Row[3],
909            CreateTime => $Row[4],
910            CreateBy   => $Row[5],
911            ChangeTime => $Row[6],
912            ChangeBy   => $Row[7],
913        };
914    }
915
916    # set cache
917    $CacheObject->Set(
918        Type  => 'Group',
919        Key   => 'RoleDataList',
920        TTL   => 60 * 60 * 24 * 20,
921        Value => \%RoleDataList,
922    );
923
924    return %RoleDataList;
925}
926
927=head2 PermissionCheck()
928
929Check if a user has a certain permission for a certain group.
930
931    my $HasPermission = $GroupObject->PermissionCheck(
932        UserID    => $UserID,
933        GroupName => $GroupName,
934        Type      => 'move_into', # ro|move_into|create|note|owner|priority|rw
935    );
936
937=cut
938
939sub PermissionCheck {
940    my ( $Self, %Param ) = @_;
941
942    # check needed stuff
943    for (qw(UserID GroupName Type)) {
944        if ( !$Param{$_} ) {
945            $Kernel::OM->Get('Kernel::System::Log')->Log(
946                Priority => 'error',
947                Message  => "Need $_!",
948            );
949            return;
950        }
951    }
952
953    # PermissionUserGet already has in-memory caching enabled, so don't cache again here.
954    return { reverse $Self->PermissionUserGet(%Param) }->{ $Param{GroupName} } ? 1 : 0;
955}
956
957=head2 PermissionUserInvolvedGet()
958
959returns a list of users with the given permissions
960
961    my %Users = $GroupObject->PermissionUserInvolvedGet(
962        UserID => $ID,
963        Type   => 'move_into', # ro|move_into|create|note|owner|priority|rw
964    );
965
966=cut
967
968sub PermissionUserInvolvedGet {
969    my ( $Self, %Param ) = @_;
970
971    # check needed stuff
972    for (qw(UserID Type)) {
973        if ( !$Param{$_} ) {
974            $Kernel::OM->Get('Kernel::System::Log')->Log(
975                Priority => 'error',
976                Message  => "Need $_!",
977            );
978            return;
979        }
980    }
981
982    # get all groups of the given user
983    my %Groups = $Self->PermissionUserGet(
984        UserID => $Param{UserID},
985        Type   => $Param{Type},
986    );
987
988    my %Users;
989    for my $GroupID ( sort keys %Groups ) {
990
991        # get all users of this group
992        my %UsersOne = $Self->PermissionGroupGet(
993            GroupID => $GroupID,
994            Type    => $Param{Type},
995        );
996
997        %Users = ( %Users, %UsersOne );
998    }
999
1000    return %Users;
1001}
1002
1003=head2 PermissionUserGet()
1004
1005Get groups of the given user.
1006
1007    my %Groups = $GroupObject->PermissionUserGet(
1008        UserID => $ID,
1009        Type   => 'move_into', # ro|move_into|create|note|owner|priority|rw
1010    );
1011
1012=cut
1013
1014sub PermissionUserGet {
1015    my ( $Self, %Param ) = @_;
1016
1017    # check needed stuff
1018    for (qw(UserID Type)) {
1019        if ( !$Param{$_} ) {
1020            $Kernel::OM->Get('Kernel::System::Log')->Log(
1021                Priority => 'error',
1022                Message  => "Need $_!",
1023            );
1024            return;
1025        }
1026    }
1027
1028    # get cache object
1029    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
1030
1031    my $CacheKey = 'PermissionUserGet::' . $Param{UserID} . '::' . $Param{Type};
1032
1033    # read cache
1034    my $Cache = $CacheObject->Get(
1035        Type => 'GroupPermissionUserGet',
1036        Key  => $CacheKey,
1037    );
1038    return %{$Cache} if $Cache;
1039
1040    # get groups a user is member of
1041    my %GroupList = $Self->PermissionUserGroupGet(
1042        UserID => $Param{UserID},
1043        Type   => $Param{Type},
1044    );
1045
1046    # get roles a user is member of
1047    my %RoleList = $Self->PermissionUserRoleGet(
1048        UserID => $Param{UserID},
1049    );
1050
1051    if (%RoleList) {
1052        ROLEID:
1053        for my $RoleID ( sort keys %RoleList ) {
1054
1055            next ROLEID if !$RoleID;
1056
1057            # get groups of the role
1058            my %RoleGroupList = $Self->PermissionRoleGroupGet(
1059                RoleID => $RoleID,
1060                Type   => $Param{Type},
1061            );
1062
1063            %GroupList = ( %GroupList, %RoleGroupList );
1064        }
1065    }
1066
1067    # set cache
1068    $CacheObject->Set(
1069        Type  => 'GroupPermissionUserGet',
1070        Key   => $CacheKey,
1071        TTL   => 60 * 60 * 24 * 20,
1072        Value => \%GroupList,
1073    );
1074
1075    return %GroupList;
1076}
1077
1078=head2 PermissionGroupGet()
1079
1080Get users of the given group.
1081
1082    my %Users = $GroupObject->PermissionGroupGet(
1083        GroupID => $ID,
1084        Type    => 'move_into', # ro|move_into|create|note|owner|priority|rw
1085    );
1086
1087=cut
1088
1089sub PermissionGroupGet {
1090    my ( $Self, %Param ) = @_;
1091
1092    # check needed stuff
1093    for (qw(GroupID Type)) {
1094        if ( !$Param{$_} ) {
1095            $Kernel::OM->Get('Kernel::System::Log')->Log(
1096                Priority => 'error',
1097                Message  => "Need $_!",
1098            );
1099            return;
1100        }
1101    }
1102
1103    # get cache object
1104    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
1105
1106    my $CacheKey = 'PermissionGroupGet::' . $Param{GroupID} . '::' . $Param{Type};
1107
1108    # read cache
1109    my $Cache = $CacheObject->Get(
1110        Type => 'GroupPermissionGroupGet',
1111        Key  => $CacheKey,
1112    );
1113    return %{$Cache} if $Cache;
1114
1115    # get users of a given group
1116    my %UserList = $Self->PermissionGroupUserGet(
1117        GroupID => $Param{GroupID},
1118        Type    => $Param{Type},
1119    );
1120
1121    # get roles of the given group
1122    my %RoleList = $Self->PermissionGroupRoleGet(
1123        GroupID => $Param{GroupID},
1124        Type    => $Param{Type},
1125    );
1126
1127    return %UserList if !%RoleList;
1128
1129    ROLEID:
1130    for my $RoleID ( sort keys %RoleList ) {
1131
1132        next ROLEID if !$RoleID;
1133
1134        # get users of the role
1135        my %RoleUserList = $Self->PermissionRoleUserGet(
1136            RoleID => $RoleID,
1137        );
1138
1139        %UserList = ( %UserList, %RoleUserList );
1140    }
1141
1142    # set cache
1143    $CacheObject->Set(
1144        Type  => 'GroupPermissionGroupGet',
1145        Key   => $CacheKey,
1146        TTL   => 60 * 60 * 24 * 20,
1147        Value => \%UserList,
1148    );
1149
1150    return %UserList;
1151}
1152
1153=head2 PermissionGroupUserAdd()
1154
1155add new permissions or update existing one to the given group of a given user
1156
1157    my $Success = $GroupObject->PermissionGroupUserAdd(
1158        GID => 12,
1159        UID => 6,
1160        Permission => {
1161            ro        => 1,
1162            move_into => 1,
1163            create    => 1,
1164            note      => 1,
1165            owner     => 1,
1166            priority  => 0,
1167            rw        => 0,
1168        },
1169        UserID => 123,
1170    );
1171
1172=cut
1173
1174sub PermissionGroupUserAdd {
1175    my ( $Self, %Param ) = @_;
1176
1177    # check needed stuff
1178    for (qw(UID GID UserID Permission)) {
1179        if ( !$Param{$_} ) {
1180            $Kernel::OM->Get('Kernel::System::Log')->Log(
1181                Priority => 'error',
1182                Message  => "Need $_!",
1183            );
1184            return;
1185        }
1186    }
1187    if ( ref $Param{Permission} ne 'HASH' ) {
1188        $Kernel::OM->Get('Kernel::System::Log')->Log(
1189            Priority => 'error',
1190            Message  => "Permission needs to be a hash reference!",
1191        );
1192        return;
1193    }
1194
1195    # get group user data
1196    my %DBGroupUser = $Self->_DBGroupUserGet(
1197        Type => 'UserGroupPerm',
1198    );
1199
1200    # extract data from given user id and group id
1201    my @CurrentPermissions;
1202    if (
1203        $DBGroupUser{ $Param{UID} }
1204        && ref $DBGroupUser{ $Param{UID} } eq 'HASH'
1205        && $DBGroupUser{ $Param{UID} }->{ $Param{GID} }
1206        && ref $DBGroupUser{ $Param{UID} }->{ $Param{GID} } eq 'ARRAY'
1207        )
1208    {
1209        @CurrentPermissions = @{ $DBGroupUser{ $Param{UID} }->{ $Param{GID} } };
1210    }
1211
1212    # check rw rule (set only rw and remove the rest, because all other are included in rw)
1213    my @NewPermissions;
1214    if ( $Param{Permission}->{rw} ) {
1215        @NewPermissions = ('rw');
1216    }
1217    else {
1218
1219        # get permission type list
1220        my %PermissionTypeList = $Self->_PermissionTypeList();
1221
1222        # create new permission array
1223        TYPE:
1224        for my $Type ( sort keys %{ $Param{Permission} } ) {
1225
1226            next TYPE if !$Type;
1227            next TYPE if !$PermissionTypeList{$Type};
1228            next TYPE if !$Param{Permission}->{$Type};
1229
1230            push @NewPermissions, $Type;
1231        }
1232    }
1233
1234    # generate strings to compare the both arrays
1235    my $CurrentPermissionString = join '-', sort @CurrentPermissions;
1236    my $NewPermissionString     = join '-', sort @NewPermissions;
1237
1238    return 1 if $CurrentPermissionString eq $NewPermissionString;
1239
1240    # get database object
1241    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
1242
1243    # delete existing permissions from database
1244    $DBObject->Do(
1245        SQL  => 'DELETE FROM group_user WHERE user_id = ? AND group_id = ?',
1246        Bind => [ \$Param{UID}, \$Param{GID} ],
1247    );
1248
1249    # insert new permissions
1250    TYPE:
1251    for my $Type (@NewPermissions) {
1252
1253        # add to database
1254        $DBObject->Do(
1255            SQL => 'INSERT INTO group_user '
1256                . '(user_id, group_id, permission_key, '
1257                . 'create_time, create_by, change_time, change_by) '
1258                . 'VALUES (?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
1259            Bind => [
1260                \$Param{UID},
1261                \$Param{GID},
1262                \$Type,
1263                \$Param{UserID},
1264                \$Param{UserID},
1265            ],
1266        );
1267    }
1268
1269    # reset cache
1270    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
1271
1272    $CacheObject->CleanUp(
1273        Type => 'DBGroupUserGet',
1274    );
1275
1276    $CacheObject->CleanUp(
1277        Type => 'GroupPermissionUserGet',
1278    );
1279
1280    $CacheObject->CleanUp(
1281        Type => 'GroupPermissionGroupGet',
1282    );
1283
1284    return 1;
1285}
1286
1287=head2 PermissionGroupUserGet()
1288
1289returns a list with all users of a group
1290
1291    my %UserList = $GroupObject->PermissionGroupUserGet(
1292        GroupID => $GroupID,
1293        Type    => 'move_into',  # ro|move_into|create|note|owner|priority|rw
1294    );
1295
1296    %UserList = (
1297        1 => 'User1',
1298        2 => 'User2',
1299        3 => 'User3',
1300    );
1301
1302=cut
1303
1304sub PermissionGroupUserGet {
1305    my ( $Self, %Param ) = @_;
1306
1307    # check needed stuff
1308    for (qw(GroupID Type)) {
1309        if ( !$Param{$_} ) {
1310            $Kernel::OM->Get('Kernel::System::Log')->Log(
1311                Priority => 'error',
1312                Message  => "Need $_!",
1313            );
1314            return;
1315        }
1316    }
1317
1318    # get permission type list
1319    my %PermissionTypeList = $Self->_PermissionTypeList(
1320        Type => $Param{Type},
1321    );
1322
1323    return if !%PermissionTypeList;
1324
1325    # get valid group list
1326    my %GroupList = $Self->GroupList(
1327        Valid => 1,
1328    );
1329
1330    return if !$GroupList{ $Param{GroupID} };
1331
1332    # get group user data
1333    my %Permissions = $Self->_DBGroupUserGet(
1334        Type => 'GroupPermUser',
1335    );
1336
1337    return if !$Permissions{ $Param{GroupID} };
1338    return if ref $Permissions{ $Param{GroupID} } ne 'HASH';
1339
1340    # extract users
1341    my $UsersRaw   = $Permissions{ $Param{GroupID} }->{ $Param{Type} } || [];
1342    my $UsersRawRw = $Permissions{ $Param{GroupID} }->{rw}             || [];
1343
1344    if ( ref $UsersRaw ne 'ARRAY' ) {
1345        $UsersRaw = [];
1346    }
1347    if ( ref $UsersRawRw ne 'ARRAY' ) {
1348        $UsersRawRw = [];
1349    }
1350
1351    # get valid user list
1352    my %UserList = $Kernel::OM->Get('Kernel::System::User')->UserList(
1353        Type => 'Short',
1354    );
1355
1356    # calculate users
1357    my %Users;
1358    USERID:
1359    for my $UserID ( @{$UsersRaw}, @{$UsersRawRw} ) {
1360
1361        next USERID if !$UserID;
1362        next USERID if !$UserList{$UserID};
1363
1364        $Users{$UserID} = $UserList{$UserID};
1365    }
1366
1367    return %Users;
1368}
1369
1370=head2 PermissionUserGroupGet()
1371
1372returns a list of groups a user is member of
1373
1374    my %GroupList = $GroupObject->PermissionUserGroupGet(
1375        UserID => 123,
1376        Type   => 'move_into',  # ro|move_into|create|note|owner|priority|rw
1377    );
1378
1379    %GroupList = (
1380        1 => 'Group1',
1381        2 => 'Group2',
1382        3 => 'Group3',
1383    );
1384
1385=cut
1386
1387sub PermissionUserGroupGet {
1388    my ( $Self, %Param ) = @_;
1389
1390    # check needed stuff
1391    for (qw(UserID Type)) {
1392        if ( !$Param{$_} ) {
1393            $Kernel::OM->Get('Kernel::System::Log')->Log(
1394                Priority => 'error',
1395                Message  => "Need $_!",
1396            );
1397            return;
1398        }
1399    }
1400
1401    # get permission type list
1402    my %PermissionTypeList = $Self->_PermissionTypeList(
1403        Type => $Param{Type},
1404    );
1405
1406    return if !%PermissionTypeList;
1407
1408    # check if user is valid
1409    return if !$Kernel::OM->Get('Kernel::System::User')->GetUserData(
1410        UserID => $Param{UserID},
1411        Valid  => 1,
1412    );
1413
1414    # get group user data
1415    my %Permissions = $Self->_DBGroupUserGet(
1416        Type => 'UserPermGroup',
1417    );
1418
1419    return if !$Permissions{ $Param{UserID} };
1420    return if ref $Permissions{ $Param{UserID} } ne 'HASH';
1421
1422    # extract groups
1423    my $GroupsRaw   = $Permissions{ $Param{UserID} }->{ $Param{Type} } || [];
1424    my $GroupsRawRw = $Permissions{ $Param{UserID} }->{rw}             || [];
1425
1426    if ( ref $GroupsRaw ne 'ARRAY' ) {
1427        $GroupsRaw = [];
1428    }
1429    if ( ref $GroupsRawRw ne 'ARRAY' ) {
1430        $GroupsRawRw = [];
1431    }
1432
1433    # get valid group list
1434    my %GroupList = $Self->GroupList(
1435        Valid => 1,
1436    );
1437
1438    # calculate groups
1439    my %Groups;
1440    GROUPID:
1441    for my $GroupID ( @{$GroupsRaw}, @{$GroupsRawRw} ) {
1442
1443        next GROUPID if !$GroupID;
1444        next GROUPID if !$GroupList{$GroupID};
1445
1446        $Groups{$GroupID} = $GroupList{$GroupID};
1447    }
1448
1449    return %Groups;
1450}
1451
1452=head2 PermissionGroupRoleAdd()
1453
1454add new permissions or update existing one to the given group of a given role
1455
1456    my $Success = $GroupObject->PermissionGroupRoleAdd(
1457        GID => 12,
1458        RID => 6,
1459        Permission => {
1460            ro        => 1,
1461            move_into => 1,
1462            create    => 1,
1463            note      =  1,
1464            owner     => 1,
1465            priority  => 0,
1466            rw        => 0,
1467        },
1468        UserID => 123,
1469    );
1470
1471=cut
1472
1473sub PermissionGroupRoleAdd {
1474    my ( $Self, %Param ) = @_;
1475
1476    # check needed stuff
1477    for (qw(RID GID UserID Permission)) {
1478        if ( !$Param{$_} ) {
1479            $Kernel::OM->Get('Kernel::System::Log')->Log(
1480                Priority => 'error',
1481                Message  => "Need $_!",
1482            );
1483            return;
1484        }
1485    }
1486    if ( ref $Param{Permission} ne 'HASH' ) {
1487        $Kernel::OM->Get('Kernel::System::Log')->Log(
1488            Priority => 'error',
1489            Message  => "Permission needs to be a hash reference!",
1490        );
1491        return;
1492    }
1493
1494    # get group role data
1495    my %DBGroupRole = $Self->_DBGroupRoleGet(
1496        Type => 'RoleGroupPerm',
1497    );
1498
1499    # extract data from given user id and group id
1500    my @CurrentPermissions;
1501    if (
1502        $DBGroupRole{ $Param{RID} }
1503        && ref $DBGroupRole{ $Param{RID} } eq 'HASH'
1504        && $DBGroupRole{ $Param{RID} }->{ $Param{GID} }
1505        && ref $DBGroupRole{ $Param{RID} }->{ $Param{GID} } eq 'ARRAY'
1506        )
1507    {
1508        @CurrentPermissions = @{ $DBGroupRole{ $Param{RID} }->{ $Param{GID} } };
1509    }
1510
1511    # check rw rule (set only rw and remove the rest, because all other are included in rw)
1512    my @NewPermissions;
1513    if ( $Param{Permission}->{rw} ) {
1514        @NewPermissions = ('rw');
1515    }
1516    else {
1517
1518        # get permission type list
1519        my %PermissionTypeList = $Self->_PermissionTypeList();
1520
1521        # create new permission array
1522        TYPE:
1523        for my $Type ( sort keys %{ $Param{Permission} } ) {
1524
1525            next TYPE if !$Type;
1526            next TYPE if !$PermissionTypeList{$Type};
1527            next TYPE if !$Param{Permission}->{$Type};
1528
1529            push @NewPermissions, $Type;
1530        }
1531    }
1532
1533    # generate strings to compare the both arrays
1534    my $CurrentPermissionString = join '-', sort @CurrentPermissions;
1535    my $NewPermissionString     = join '-', sort @NewPermissions;
1536
1537    return 1 if $CurrentPermissionString eq $NewPermissionString;
1538
1539    # get database object
1540    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
1541
1542    # delete existing permissions from database
1543    $DBObject->Do(
1544        SQL  => 'DELETE FROM group_role WHERE role_id = ? AND group_id = ?',
1545        Bind => [ \$Param{RID}, \$Param{GID} ],
1546    );
1547
1548    # insert new permissions
1549    TYPE:
1550    for my $Type (@NewPermissions) {
1551
1552        my $ValueNew = 1;
1553
1554        # add to database
1555        $DBObject->Do(
1556            SQL => 'INSERT INTO group_role '
1557                . '(role_id, group_id, permission_key, permission_value, '
1558                . 'create_time, create_by, change_time, change_by) '
1559                . 'VALUES (?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
1560            Bind => [
1561                \$Param{RID},
1562                \$Param{GID},
1563                \$Type,
1564                \$ValueNew,
1565                \$Param{UserID},
1566                \$Param{UserID},
1567            ],
1568        );
1569    }
1570
1571    # reset cache
1572    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
1573
1574    $CacheObject->CleanUp(
1575        Type => 'DBGroupRoleGet',
1576    );
1577
1578    $CacheObject->CleanUp(
1579        Type => 'GroupPermissionUserGet',
1580    );
1581
1582    $CacheObject->CleanUp(
1583        Type => 'GroupPermissionGroupGet',
1584    );
1585
1586    return 1;
1587}
1588
1589=head2 PermissionGroupRoleGet()
1590
1591returns a list with all roles of a group
1592
1593    my %RoleList = $GroupObject->PermissionGroupRoleGet(
1594        GroupID => $GroupID,
1595        Type    => 'move_into',  # ro|move_into|create|note|owner|priority|rw
1596    );
1597
1598    %RoleList = (
1599        1 => 'Role1',
1600        2 => 'Role2',
1601        3 => 'Role3',
1602    );
1603
1604=cut
1605
1606sub PermissionGroupRoleGet {
1607    my ( $Self, %Param ) = @_;
1608
1609    # check needed stuff
1610    for (qw(GroupID Type)) {
1611        if ( !$Param{$_} ) {
1612            $Kernel::OM->Get('Kernel::System::Log')->Log(
1613                Priority => 'error',
1614                Message  => "Need $_!",
1615            );
1616            return;
1617        }
1618    }
1619
1620    # get permission type list
1621    my %PermissionTypeList = $Self->_PermissionTypeList(
1622        Type => $Param{Type},
1623    );
1624
1625    return if !%PermissionTypeList;
1626
1627    # get valid group list
1628    my %GroupList = $Self->GroupList(
1629        Valid => 1,
1630    );
1631
1632    return if !$GroupList{ $Param{GroupID} };
1633
1634    # get group role data
1635    my %Permissions = $Self->_DBGroupRoleGet(
1636        Type => 'GroupPermRole',
1637    );
1638
1639    return if !$Permissions{ $Param{GroupID} };
1640    return if ref $Permissions{ $Param{GroupID} } ne 'HASH';
1641
1642    # extract roles
1643    my $RolesRaw   = $Permissions{ $Param{GroupID} }->{ $Param{Type} } || [];
1644    my $RolesRawRw = $Permissions{ $Param{GroupID} }->{rw}             || [];
1645
1646    if ( ref $RolesRaw ne 'ARRAY' ) {
1647        $RolesRaw = [];
1648    }
1649    if ( ref $RolesRawRw ne 'ARRAY' ) {
1650        $RolesRawRw = [];
1651    }
1652
1653    # get valid role list
1654    my %RoleList = $Self->RoleList( Valid => 1 );
1655
1656    # calculate roles
1657    my %Roles;
1658    ROLEID:
1659    for my $RoleID ( @{$RolesRaw}, @{$RolesRawRw} ) {
1660
1661        next ROLEID if !$RoleID;
1662        next ROLEID if !$RoleList{$RoleID};
1663
1664        $Roles{$RoleID} = $RoleList{$RoleID};
1665    }
1666
1667    return %Roles;
1668}
1669
1670=head2 PermissionRoleGroupGet()
1671
1672returns a list with all groups of a role
1673
1674    my %GroupList = $GroupObject->PermissionRoleGroupGet(
1675        RoleID => 12,
1676        Type   => 'move_into',  # ro|move_into|create|note|owner|priority|rw
1677    );
1678
1679    %GroupList = (
1680        1 => 'Group1',
1681        2 => 'Group2',
1682        3 => 'Group3',
1683    );
1684
1685=cut
1686
1687sub PermissionRoleGroupGet {
1688    my ( $Self, %Param ) = @_;
1689
1690    # check needed stuff
1691    for (qw(RoleID Type)) {
1692        if ( !$Param{$_} ) {
1693            $Kernel::OM->Get('Kernel::System::Log')->Log(
1694                Priority => 'error',
1695                Message  => "Need $_!",
1696            );
1697            return;
1698        }
1699    }
1700
1701    # get permission type list
1702    my %PermissionTypeList = $Self->_PermissionTypeList(
1703        Type => $Param{Type},
1704    );
1705
1706    return if !%PermissionTypeList;
1707
1708    # get valid role list
1709    my %RoleList = $Self->RoleList( Valid => 1 );
1710
1711    return if !$RoleList{ $Param{RoleID} };
1712
1713    # get group role data
1714    my %Permissions = $Self->_DBGroupRoleGet(
1715        Type => 'RolePermGroup',
1716    );
1717
1718    return if !$Permissions{ $Param{RoleID} };
1719    return if ref $Permissions{ $Param{RoleID} } ne 'HASH';
1720
1721    # extract groups
1722    my $GroupsRaw   = $Permissions{ $Param{RoleID} }->{ $Param{Type} } || [];
1723    my $GroupsRawRw = $Permissions{ $Param{RoleID} }->{rw}             || [];
1724
1725    if ( ref $GroupsRaw ne 'ARRAY' ) {
1726        $GroupsRaw = [];
1727    }
1728    if ( ref $GroupsRawRw ne 'ARRAY' ) {
1729        $GroupsRawRw = [];
1730    }
1731
1732    # get valid group list
1733    my %GroupList = $Self->GroupList(
1734        Valid => 1,
1735    );
1736
1737    # calculate groups
1738    my %Groups;
1739    GROUPID:
1740    for my $GroupID ( @{$GroupsRaw}, @{$GroupsRawRw} ) {
1741
1742        next GROUPID if !$GroupID;
1743        next GROUPID if !$GroupList{$GroupID};
1744
1745        $Groups{$GroupID} = $GroupList{$GroupID};
1746    }
1747
1748    return %Groups;
1749}
1750
1751=head2 PermissionRoleUserAdd()
1752
1753add new permissions or update existing one to the given group of a given role
1754
1755    my $Success = $GroupObject->PermissionRoleUserAdd(
1756        UID    => 12,
1757        RID    => 6,
1758        Active => 1,
1759        UserID => 123,
1760    );
1761
1762=cut
1763
1764sub PermissionRoleUserAdd {
1765    my ( $Self, %Param ) = @_;
1766
1767    # check needed stuff
1768    for (qw(UID RID UserID)) {
1769        if ( !$Param{$_} ) {
1770            $Kernel::OM->Get('Kernel::System::Log')->Log(
1771                Priority => 'error',
1772                Message  => "Need $_!",
1773            );
1774            return;
1775        }
1776    }
1777
1778    # get role user data
1779    my %DBUserRole = $Self->_DBRoleUserGet(
1780        Type => 'UserRoleHash',
1781    );
1782
1783    return 1 if $Param{Active}  && $DBUserRole{ $Param{UID} }->{ $Param{RID} };
1784    return 1 if !$Param{Active} && !$DBUserRole{ $Param{UID} }->{ $Param{RID} };
1785
1786    # get needed object
1787    my $DBObject    = $Kernel::OM->Get('Kernel::System::DB');
1788    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
1789
1790    # delete existing relation
1791    $DBObject->Do(
1792        SQL  => 'DELETE FROM role_user WHERE user_id = ? AND role_id = ?',
1793        Bind => [ \$Param{UID}, \$Param{RID} ],
1794    );
1795
1796    # reset cache
1797    $CacheObject->CleanUp(
1798        Type => 'DBRoleUserGet',
1799    );
1800
1801    $CacheObject->CleanUp(
1802        Type => 'GroupPermissionUserGet',
1803    );
1804
1805    $CacheObject->CleanUp(
1806        Type => 'GroupPermissionGroupGet',
1807    );
1808
1809    return 1 if !$Param{Active};
1810
1811    # insert new relation
1812    $DBObject->Do(
1813        SQL => 'INSERT INTO role_user '
1814            . '(user_id, role_id, create_time, create_by, change_time, change_by) '
1815            . 'VALUES (?, ?, current_timestamp, ?, current_timestamp, ?)',
1816        Bind => [ \$Param{UID}, \$Param{RID}, \$Param{UserID}, \$Param{UserID} ],
1817    );
1818
1819    return 1;
1820}
1821
1822=head2 PermissionRoleUserGet()
1823
1824returns a list with all users of a role
1825
1826    my %UserList = $GroupObject->PermissionRoleUserGet(
1827        RoleID => $RoleID,
1828    );
1829
1830    %UserList = (
1831        1 => 'User1',
1832        2 => 'User2',
1833        3 => 'User3',
1834    );
1835
1836=cut
1837
1838sub PermissionRoleUserGet {
1839    my ( $Self, %Param ) = @_;
1840
1841    # check needed stuff
1842    if ( !$Param{RoleID} ) {
1843        $Kernel::OM->Get('Kernel::System::Log')->Log(
1844            Priority => 'error',
1845            Message  => "Need RoleID!",
1846        );
1847        return;
1848    }
1849
1850    # get valid role list
1851    my %RoleList = $Self->RoleList( Valid => 1 );
1852
1853    return if !$RoleList{ $Param{RoleID} };
1854
1855    # get permission data
1856    my %Permissions = $Self->_DBRoleUserGet(
1857        Type => 'RoleUser',
1858    );
1859
1860    return if !$Permissions{ $Param{RoleID} };
1861    return if ref $Permissions{ $Param{RoleID} } ne 'ARRAY';
1862
1863    # extract users
1864    my $UsersRaw = $Permissions{ $Param{RoleID} } || [];
1865
1866    # get valid user list
1867    my %UserList = $Kernel::OM->Get('Kernel::System::User')->UserList(
1868        Type => 'Short',
1869    );
1870
1871    # calculate users
1872    my %Users;
1873    USERID:
1874    for my $UserID ( @{$UsersRaw} ) {
1875
1876        next USERID if !$UserID;
1877        next USERID if !$UserList{$UserID};
1878
1879        $Users{$UserID} = $UserList{$UserID};
1880    }
1881
1882    return %Users;
1883}
1884
1885=head2 PermissionUserRoleGet()
1886
1887returns a list with all roles of a user
1888
1889    my %RoleList = $GroupObject->PermissionUserRoleGet(
1890        UserID => $UserID,
1891    );
1892
1893    %RoleList = (
1894        1 => 'Role1',
1895        2 => 'Role2',
1896        3 => 'Role3',
1897    );
1898
1899=cut
1900
1901sub PermissionUserRoleGet {
1902    my ( $Self, %Param ) = @_;
1903
1904    # check needed stuff
1905    if ( !$Param{UserID} ) {
1906        $Kernel::OM->Get('Kernel::System::Log')->Log(
1907            Priority => 'error',
1908            Message  => "Need UserID!",
1909        );
1910        return;
1911    }
1912
1913    # get valid user list
1914    my %UserList = $Kernel::OM->Get('Kernel::System::User')->UserList(
1915        Type => 'Short',
1916    );
1917
1918    return if !$UserList{ $Param{UserID} };
1919
1920    # get permission data
1921    my %Permissions = $Self->_DBRoleUserGet(
1922        Type => 'UserRole',
1923    );
1924
1925    return if !$Permissions{ $Param{UserID} };
1926    return if ref $Permissions{ $Param{UserID} } ne 'ARRAY';
1927
1928    # extract roles
1929    my $RolesRaw = $Permissions{ $Param{UserID} } || [];
1930
1931    # get valid role list
1932    my %RoleList = $Self->RoleList( Valid => 1 );
1933
1934    # calculate roles
1935    my %Roles;
1936    ROLEID:
1937    for my $RoleID ( @{$RolesRaw} ) {
1938
1939        next ROLEID if !$RoleID;
1940        next ROLEID if !$RoleList{$RoleID};
1941
1942        $Roles{$RoleID} = $RoleList{$RoleID};
1943    }
1944
1945    return %Roles;
1946}
1947
1948=head2 GroupMemberAdd()
1949
1950Function for backward compatibility. Redirected to PermissionGroupUserAdd().
1951
1952=cut
1953
1954sub GroupMemberAdd {
1955    my ( $Self, %Param ) = @_;
1956
1957    return $Self->PermissionGroupUserAdd(%Param);
1958}
1959
1960=head2 GroupMemberList()
1961
1962Function for backward compatibility. Redirected to PermissionUserGet() and PermissionGroupGet().
1963
1964=cut
1965
1966sub GroupMemberList {
1967    my ( $Self, %Param ) = @_;
1968
1969    # check needed stuff
1970    for (qw(Result Type)) {
1971        if ( !$Param{$_} ) {
1972            $Kernel::OM->Get('Kernel::System::Log')->Log(
1973                Priority => 'error',
1974                Message  => "Need $_!",
1975            );
1976            return;
1977        }
1978    }
1979    if ( !$Param{UserID} && !$Param{GroupID} ) {
1980        $Kernel::OM->Get('Kernel::System::Log')->Log(
1981            Priority => 'error',
1982            Message  => 'Need UserID or GroupID!',
1983        );
1984        return;
1985    }
1986
1987    if ( $Param{UserID} ) {
1988
1989        # get groups of the give user
1990        my %Groups = $Self->PermissionUserGet(
1991            UserID => $Param{UserID},
1992            Type   => $Param{Type},
1993        );
1994
1995        return %Groups if $Param{Result} eq 'HASH';
1996
1997        if ( $Param{Result} eq 'ID' ) {
1998
1999            my @IDList = sort keys %Groups;
2000
2001            return @IDList;
2002        }
2003
2004        if ( $Param{Result} eq 'Name' ) {
2005
2006            my @NameList = sort values %Groups;
2007
2008            return @NameList;
2009        }
2010    }
2011    else {
2012
2013        # get users of the give group
2014        my %Users = $Self->PermissionGroupGet(
2015            GroupID => $Param{GroupID},
2016            Type    => $Param{Type},
2017        );
2018
2019        return %Users if $Param{Result} eq 'HASH';
2020
2021        if ( $Param{Result} eq 'ID' ) {
2022
2023            my @IDList = sort keys %Users;
2024
2025            return @IDList;
2026        }
2027
2028        if ( $Param{Result} eq 'Name' ) {
2029
2030            my @NameList = sort values %Users;
2031
2032            return @NameList;
2033        }
2034    }
2035
2036    return;
2037}
2038
2039=head2 GroupMemberInvolvedList()
2040
2041Function for backward compatibility. Redirected to PermissionUserInvolvedGet().
2042
2043=cut
2044
2045sub GroupMemberInvolvedList {
2046    my ( $Self, %Param ) = @_;
2047
2048    return $Self->PermissionUserInvolvedGet(%Param);
2049}
2050
2051=head2 GroupGroupMemberList()
2052
2053Function for backward compatibility. Redirected to PermissionUserGroupGet() and PermissionGroupUserGet().
2054
2055=cut
2056
2057sub GroupGroupMemberList {
2058    my ( $Self, %Param ) = @_;
2059
2060    # check needed stuff
2061    for (qw(Result Type)) {
2062        if ( !$Param{$_} ) {
2063            $Kernel::OM->Get('Kernel::System::Log')->Log(
2064                Priority => 'error',
2065                Message  => "Need $_!",
2066            );
2067            return;
2068        }
2069    }
2070    if ( !$Param{UserID} && !$Param{GroupID} && !$Param{UserIDs} && !$Param{GroupIDs} ) {
2071        $Kernel::OM->Get('Kernel::System::Log')->Log(
2072            Priority => 'error',
2073            Message  => 'Need UserID or GroupID or UserIDs or GroupIDs!',
2074        );
2075        return;
2076    }
2077
2078    my @UserIDList;
2079    if ( $Param{UserID} ) {
2080        push @UserIDList, $Param{UserID};
2081    }
2082    elsif ( $Param{UserIDs} ) {
2083        @UserIDList = @{ $Param{UserIDs} };
2084    }
2085
2086    my @GroupIDList;
2087    if ( $Param{GroupID} ) {
2088        push @GroupIDList, $Param{GroupID};
2089    }
2090    elsif ( $Param{GroupIDs} ) {
2091        @GroupIDList = @{ $Param{GroupIDs} };
2092    }
2093
2094    if (@UserIDList) {
2095
2096        my %GroupList;
2097        for my $UserID (@UserIDList) {
2098
2099            my %GroupListOne = $Self->PermissionUserGroupGet(
2100                UserID => $UserID,
2101                Type   => $Param{Type},
2102            );
2103
2104            %GroupList = ( %GroupList, %GroupListOne );
2105        }
2106
2107        return %GroupList if $Param{Result} eq 'HASH';
2108
2109        if ( $Param{Result} eq 'ID' ) {
2110
2111            my @IDList = sort keys %GroupList;
2112
2113            return @IDList;
2114        }
2115
2116        if ( $Param{Result} eq 'Name' ) {
2117
2118            my @NameList = sort values %GroupList;
2119
2120            return @NameList;
2121        }
2122    }
2123
2124    if (@GroupIDList) {
2125
2126        my %UserList;
2127        for my $GroupID (@GroupIDList) {
2128
2129            my %UserListOne = $Self->PermissionGroupUserGet(
2130                GroupID => $GroupID,
2131                Type    => $Param{Type},
2132            );
2133
2134            %UserList = ( %UserList, %UserListOne );
2135        }
2136
2137        return %UserList if $Param{Result} eq 'HASH';
2138
2139        if ( $Param{Result} eq 'ID' ) {
2140
2141            my @IDList = sort keys %UserList;
2142
2143            return @IDList;
2144        }
2145
2146        if ( $Param{Result} eq 'Name' ) {
2147
2148            my @NameList = sort values %UserList;
2149
2150            return @NameList;
2151        }
2152    }
2153
2154    return;
2155}
2156
2157=head2 GroupRoleMemberList()
2158
2159Function for backward compatibility. Redirected to PermissionRoleGroupGet() and PermissionGroupRoleGet().
2160
2161=cut
2162
2163sub GroupRoleMemberList {
2164    my ( $Self, %Param ) = @_;
2165
2166    # check needed stuff
2167    for (qw(Result Type)) {
2168        if ( !$Param{$_} ) {
2169            $Kernel::OM->Get('Kernel::System::Log')->Log(
2170                Priority => 'error',
2171                Message  => "Need $_!",
2172            );
2173            return;
2174        }
2175    }
2176    if ( !$Param{RoleID} && !$Param{GroupID} && !$Param{RoleIDs} && !$Param{GroupIDs} ) {
2177        $Kernel::OM->Get('Kernel::System::Log')->Log(
2178            Priority => 'error',
2179            Message  => 'Need RoleID or GroupID or RoleIDs or GroupIDs!'
2180        );
2181        return;
2182    }
2183
2184    my @RoleIDList;
2185    if ( $Param{RoleID} ) {
2186        push @RoleIDList, $Param{RoleID};
2187    }
2188    elsif ( $Param{RoleIDs} ) {
2189        @RoleIDList = @{ $Param{RoleIDs} };
2190    }
2191
2192    my @GroupIDList;
2193    if ( $Param{GroupID} ) {
2194        push @GroupIDList, $Param{GroupID};
2195    }
2196    elsif ( $Param{GroupIDs} ) {
2197        @GroupIDList = @{ $Param{GroupIDs} };
2198    }
2199
2200    if (@RoleIDList) {
2201
2202        my %GroupList;
2203        for my $RoleID (@RoleIDList) {
2204
2205            my %GroupListOne = $Self->PermissionRoleGroupGet(
2206                RoleID => $RoleID,
2207                Type   => $Param{Type},
2208            );
2209
2210            %GroupList = ( %GroupList, %GroupListOne );
2211        }
2212
2213        return %GroupList if $Param{Result} eq 'HASH';
2214
2215        if ( $Param{Result} eq 'ID' ) {
2216
2217            my @IDList = sort keys %GroupList;
2218
2219            return @IDList;
2220        }
2221
2222        if ( $Param{Result} eq 'Name' ) {
2223
2224            my @NameList = sort values %GroupList;
2225
2226            return @NameList;
2227        }
2228    }
2229
2230    if (@GroupIDList) {
2231
2232        my %RoleList;
2233        for my $GroupID (@GroupIDList) {
2234
2235            my %RoleListOne = $Self->PermissionGroupRoleGet(
2236                GroupID => $GroupID,
2237                Type    => $Param{Type},
2238            );
2239
2240            %RoleList = ( %RoleList, %RoleListOne );
2241        }
2242
2243        return %RoleList if $Param{Result} eq 'HASH';
2244
2245        if ( $Param{Result} eq 'ID' ) {
2246
2247            my @IDList = sort keys %RoleList;
2248
2249            return @IDList;
2250        }
2251
2252        if ( $Param{Result} eq 'Name' ) {
2253
2254            my @NameList = sort values %RoleList;
2255
2256            return @NameList;
2257        }
2258    }
2259
2260    return;
2261}
2262
2263=head2 GroupRoleMemberAdd()
2264
2265Function for backward compatibility. Redirected to PermissionGroupRoleAdd().
2266
2267=cut
2268
2269sub GroupRoleMemberAdd {
2270    my ( $Self, %Param ) = @_;
2271
2272    return $Self->PermissionGroupRoleAdd(%Param);
2273}
2274
2275=head2 GroupUserRoleMemberList()
2276
2277Function for backward compatibility. Redirected to PermissionUserRoleGet() and PermissionRoleUserGet().
2278
2279=cut
2280
2281sub GroupUserRoleMemberList {
2282    my ( $Self, %Param ) = @_;
2283
2284    # check needed stuff
2285    if ( !$Param{Result} ) {
2286        $Kernel::OM->Get('Kernel::System::Log')->Log(
2287            Priority => 'error',
2288            Message  => 'Need Result!'
2289        );
2290        return;
2291    }
2292
2293    if ( !$Param{RoleID} && !$Param{UserID} && !$Param{RoleIDs} && !$Param{UserIDs} ) {
2294        $Kernel::OM->Get('Kernel::System::Log')->Log(
2295            Priority => 'error',
2296            Message  => 'Need RoleID or UserID or RoleIDs or UserIDs!',
2297        );
2298        return;
2299    }
2300
2301    my @UserIDList;
2302    if ( $Param{UserID} ) {
2303        push @UserIDList, $Param{UserID};
2304    }
2305    elsif ( $Param{UserIDs} ) {
2306        @UserIDList = @{ $Param{UserIDs} };
2307    }
2308
2309    my @RoleIDList;
2310    if ( $Param{RoleID} ) {
2311        push @RoleIDList, $Param{RoleID};
2312    }
2313    elsif ( $Param{RoleIDs} ) {
2314        @RoleIDList = @{ $Param{RoleIDs} };
2315    }
2316
2317    if (@UserIDList) {
2318
2319        my %RoleList;
2320        for my $UserID (@UserIDList) {
2321
2322            my %RoleListOne = $Self->PermissionUserRoleGet(
2323                UserID => $UserID,
2324            );
2325
2326            %RoleList = ( %RoleList, %RoleListOne );
2327        }
2328
2329        return %RoleList if $Param{Result} eq 'HASH';
2330
2331        if ( $Param{Result} eq 'ID' ) {
2332
2333            my @IDList = sort keys %RoleList;
2334
2335            return @IDList;
2336        }
2337
2338        if ( $Param{Result} eq 'Name' ) {
2339
2340            my @NameList = sort values %RoleList;
2341
2342            return @NameList;
2343        }
2344    }
2345
2346    if (@RoleIDList) {
2347
2348        my %UserList;
2349        for my $RoleID (@RoleIDList) {
2350
2351            my %UserListOne = $Self->PermissionRoleUserGet(
2352                RoleID => $RoleID,
2353            );
2354
2355            %UserList = ( %UserList, %UserListOne );
2356        }
2357
2358        return %UserList if $Param{Result} eq 'HASH';
2359
2360        if ( $Param{Result} eq 'ID' ) {
2361
2362            my @IDList = sort keys %UserList;
2363
2364            return @IDList;
2365        }
2366
2367        if ( $Param{Result} eq 'Name' ) {
2368
2369            my @NameList = sort values %UserList;
2370
2371            return @NameList;
2372        }
2373    }
2374
2375    return;
2376}
2377
2378=head2 GroupUserRoleMemberAdd()
2379
2380Function for backward compatibility. Redirected to PermissionRoleUserAdd().
2381
2382=cut
2383
2384sub GroupUserRoleMemberAdd {
2385    my ( $Self, %Param ) = @_;
2386
2387    return $Self->PermissionRoleUserAdd(%Param);
2388}
2389
2390=begin Internal:
2391
2392=cut
2393
2394=head2 _DBGroupUserGet()
2395
2396returns the content of the database table group_user
2397
2398    my %Data = $GroupObject->_DBGroupUserGet(
2399        Type => 'UserGroupPerm',  # UserGroupPerm|UserPermGroup|GroupPermUser
2400    );
2401
2402    Example if Type is UserGroupPerm:
2403
2404    $Data{$UserID}->{$GroupID}->{$Permission}
2405
2406    %Data = (
2407        32 => {
2408            34 => [
2409                'create',
2410                'move_into',
2411                'owner',
2412                'ro',
2413            ],
2414        },
2415        276 => {
2416            277 => [
2417                'rw',
2418            ],
2419        },
2420    );
2421
2422    Example if Type is UserPermGroup:
2423
2424    $Data{$UserID}->{$Permission}->{$GroupID}
2425
2426    %Data = (
2427        32 => {
2428            owner     => [ 34 ],
2429            create    => [ 34 ],
2430            ro        => [ 34 ],
2431            move_into => [ 34 ],
2432        },
2433        276 => {
2434            rw => [ 277 ],
2435        },
2436    );
2437
2438    Example if Type is GroupPermUser:
2439
2440    $Data{$GroupID}->{$Permission}->{$UserID}
2441
2442    %Data = (
2443        127 => {
2444            owner     => [ 128 ],
2445            create    => [ 128 ],
2446            ro        => [ 128 ],
2447            move_into => [ 128 ],
2448        },
2449        90 => {
2450            rw => [ 91 ],
2451        },
2452    );
2453
2454=cut
2455
2456sub _DBGroupUserGet {
2457    my ( $Self, %Param ) = @_;
2458
2459    # check needed stuff
2460    if ( !$Param{Type} ) {
2461        $Kernel::OM->Get('Kernel::System::Log')->Log(
2462            Priority => 'error',
2463            Message  => "Need Type!",
2464        );
2465        return;
2466    }
2467
2468    # get cache object
2469    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
2470
2471    # check cache
2472    if ( $Param{Type} eq 'UserGroupPerm' ) {
2473
2474        # read cache
2475        my $Cache = $CacheObject->Get(
2476            Type => 'DBGroupUserGet',
2477            Key  => 'UserGroupPermList',
2478        );
2479
2480        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2481    }
2482    elsif ( $Param{Type} eq 'UserPermGroup' ) {
2483
2484        # read cache
2485        my $Cache = $CacheObject->Get(
2486            Type => 'DBGroupUserGet',
2487            Key  => 'UserPermGroupList',
2488        );
2489
2490        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2491    }
2492    else {
2493
2494        # read cache
2495        my $Cache = $CacheObject->Get(
2496            Type => 'DBGroupUserGet',
2497            Key  => 'GroupPermUserList',
2498        );
2499
2500        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2501    }
2502
2503    # get database object
2504    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
2505
2506    # get all data from table group_user
2507    $DBObject->Prepare(
2508        SQL => 'SELECT user_id, group_id, permission_key FROM group_user',
2509    );
2510
2511    # fetch the result
2512    my %UserGroupPermList;
2513    my %UserPermGroupList;
2514    my %GroupPermUserList;
2515    while ( my @Row = $DBObject->FetchrowArray() ) {
2516
2517        $UserGroupPermList{ $Row[0] }->{ $Row[1] } ||= [];
2518        $UserPermGroupList{ $Row[0] }->{ $Row[2] } ||= [];
2519        $GroupPermUserList{ $Row[1] }->{ $Row[2] } ||= [];
2520
2521        push @{ $UserGroupPermList{ $Row[0] }->{ $Row[1] } }, $Row[2];
2522        push @{ $UserPermGroupList{ $Row[0] }->{ $Row[2] } }, $Row[1];
2523        push @{ $GroupPermUserList{ $Row[1] }->{ $Row[2] } }, $Row[0];
2524    }
2525
2526    # set cache
2527    $CacheObject->Set(
2528        Type  => 'DBGroupUserGet',
2529        Key   => 'UserGroupPermList',
2530        TTL   => 60 * 60 * 24 * 20,
2531        Value => \%UserGroupPermList,
2532    );
2533    $CacheObject->Set(
2534        Type  => 'DBGroupUserGet',
2535        Key   => 'UserPermGroupList',
2536        TTL   => 60 * 60 * 24 * 20,
2537        Value => \%UserPermGroupList,
2538    );
2539    $CacheObject->Set(
2540        Type  => 'DBGroupUserGet',
2541        Key   => 'GroupPermUserList',
2542        TTL   => 60 * 60 * 24 * 20,
2543        Value => \%GroupPermUserList,
2544    );
2545
2546    return %UserPermGroupList if $Param{Type} eq 'UserPermGroup';
2547    return %UserGroupPermList if $Param{Type} eq 'UserGroupPerm';
2548    return %GroupPermUserList;
2549}
2550
2551=head2 _DBGroupRoleGet()
2552
2553returns the content of the database table group_role
2554
2555    my %Data = $GroupObject->_DBGroupRoleGet(
2556        Type => 'RoleGroupPerm',  # RoleGroupPerm|RolePermGroup|GroupPermRole
2557    );
2558
2559    Example if Type is RoleGroupPerm:
2560
2561    $Data{$RoleID}->{$GroupID}->{$Permission}
2562
2563    %Data = (
2564        32 => {
2565            34 => [
2566                'create',
2567                'move_into',
2568                'owner',
2569                'ro',
2570            ],
2571        },
2572        276 => {
2573            277 => [
2574                'rw',
2575            ],
2576        },
2577    );
2578
2579    Example if Type is RolePermGroup:
2580
2581    $Data{$RoleID}->{$Permission}->{$GroupID}
2582
2583    %Data = (
2584        32 => {
2585            owner     => [ 34 ],
2586            create    => [ 34 ],
2587            ro        => [ 34 ],
2588            move_into => [ 34 ],
2589        },
2590        276 => {
2591            rw => [ 277 ],
2592        },
2593    );
2594
2595    Example if Type is GroupPermRole:
2596
2597    $Data{$GroupID}->{$Permission}->{$RoleID}
2598
2599    %Data = (
2600        127 => {
2601            owner     => [ 128 ],
2602            create    => [ 128 ],
2603            ro        => [ 128 ],
2604            move_into => [ 128 ],
2605        },
2606        90 => {
2607            rw => [ 91 ],
2608        },
2609    );
2610
2611=cut
2612
2613sub _DBGroupRoleGet {
2614    my ( $Self, %Param ) = @_;
2615
2616    # check needed stuff
2617    if ( !$Param{Type} ) {
2618        $Kernel::OM->Get('Kernel::System::Log')->Log(
2619            Priority => 'error',
2620            Message  => "Need Type!",
2621        );
2622        return;
2623    }
2624
2625    # get cache object
2626    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
2627
2628    # check cache
2629    if ( $Param{Type} eq 'RoleGroupPerm' ) {
2630
2631        # read cache
2632        my $Cache = $CacheObject->Get(
2633            Type => 'DBGroupRoleGet',
2634            Key  => 'RoleGroupPermList',
2635        );
2636
2637        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2638    }
2639    elsif ( $Param{Type} eq 'RolePermGroup' ) {
2640
2641        # read cache
2642        my $Cache = $CacheObject->Get(
2643            Type => 'DBGroupRoleGet',
2644            Key  => 'RolePermGroupList',
2645        );
2646
2647        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2648    }
2649    else {
2650
2651        # read cache
2652        my $Cache = $CacheObject->Get(
2653            Type => 'DBGroupRoleGet',
2654            Key  => 'GroupPermRoleList',
2655        );
2656
2657        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2658    }
2659
2660    # get database object
2661    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
2662
2663    # get all data from table group_role
2664    # We need to check for permission_value=1 because in previous OTRS 4 and below there could be records created
2665    #   with 0 (see bug#11616).
2666    $DBObject->Prepare(
2667        SQL => 'SELECT role_id, group_id, permission_key FROM group_role WHERE permission_value = 1',
2668    );
2669
2670    # fetch the result
2671    my %RoleGroupPermList;
2672    my %RolePermGroupList;
2673    my %GroupPermRoleList;
2674    while ( my @Row = $DBObject->FetchrowArray() ) {
2675
2676        $RoleGroupPermList{ $Row[0] }->{ $Row[1] } ||= [];
2677        $RolePermGroupList{ $Row[0] }->{ $Row[2] } ||= [];
2678        $GroupPermRoleList{ $Row[1] }->{ $Row[2] } ||= [];
2679
2680        push @{ $RoleGroupPermList{ $Row[0] }->{ $Row[1] } }, $Row[2];
2681        push @{ $RolePermGroupList{ $Row[0] }->{ $Row[2] } }, $Row[1];
2682        push @{ $GroupPermRoleList{ $Row[1] }->{ $Row[2] } }, $Row[0];
2683    }
2684
2685    # set cache
2686    $CacheObject->Set(
2687        Type  => 'DBGroupRoleGet',
2688        Key   => 'RoleGroupPermList',
2689        TTL   => 60 * 60 * 24 * 20,
2690        Value => \%RoleGroupPermList,
2691    );
2692    $CacheObject->Set(
2693        Type  => 'DBGroupRoleGet',
2694        Key   => 'RolePermGroupList',
2695        TTL   => 60 * 60 * 24 * 20,
2696        Value => \%RolePermGroupList,
2697    );
2698    $CacheObject->Set(
2699        Type  => 'DBGroupRoleGet',
2700        Key   => 'GroupPermRoleList',
2701        TTL   => 60 * 60 * 24 * 20,
2702        Value => \%GroupPermRoleList,
2703    );
2704
2705    return %RolePermGroupList if $Param{Type} eq 'RolePermGroup';
2706    return %RoleGroupPermList if $Param{Type} eq 'RoleGroupPerm';
2707    return %GroupPermRoleList;
2708}
2709
2710=head2 _DBRoleUserGet()
2711
2712returns the content of the database table role_user
2713
2714    my %Data = $GroupObject->_DBRoleUserGet(
2715        Type => 'RoleUser',  # UserRole|RoleUser|UserRoleHash
2716    );
2717
2718    Example if Type is UserRole:
2719
2720    $Data{$UserID}->{$RoleID}
2721
2722    %Data = (
2723        559 => [ 557 ],
2724        127 => [ 125 ],
2725        32  => [ 31 ],
2726        443 => [ 442 ],
2727    );
2728
2729    Example if Type is RoleUser:
2730
2731    $Data{$RoleID}->{$UserID}
2732
2733    %Data = (
2734        559 => [ 560 ],
2735        127 => [ 128 ],
2736        32  => [ 33, 34 ],
2737        443 => [ 444, 445 ],
2738    );
2739
2740    Example if Type is UserRoleHash:
2741
2742    $Data{$UserID}->{$RoleID} = 1
2743
2744    %Data = (
2745        559 => {
2746            557 => 1,
2747        },
2748        127 => {
2749            125 => 1,
2750        },
2751        32 => {
2752            31 => 1,
2753        },
2754        443 => {
2755            442 => 1,
2756        },
2757    );
2758
2759=cut
2760
2761sub _DBRoleUserGet {
2762    my ( $Self, %Param ) = @_;
2763
2764    # check needed stuff
2765    if ( !$Param{Type} ) {
2766        $Kernel::OM->Get('Kernel::System::Log')->Log(
2767            Priority => 'error',
2768            Message  => "Need Type!",
2769        );
2770        return;
2771    }
2772
2773    # get cache object
2774    my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
2775
2776    # check cache
2777    if ( $Param{Type} eq 'UserRole' ) {
2778
2779        # read cache
2780        my $Cache = $CacheObject->Get(
2781            Type => 'DBRoleUserGet',
2782            Key  => 'UserRoleList',
2783        );
2784
2785        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2786    }
2787    elsif ( $Param{Type} eq 'RoleUser' ) {
2788
2789        # read cache
2790        my $Cache = $CacheObject->Get(
2791            Type => 'DBRoleUserGet',
2792            Key  => 'RoleUserList',
2793        );
2794
2795        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2796    }
2797    else {
2798
2799        # read cache
2800        my $Cache = $CacheObject->Get(
2801            Type => 'DBRoleUserGet',
2802            Key  => 'UserRoleHash',
2803        );
2804
2805        return %{$Cache} if $Cache && ref $Cache eq 'HASH';
2806    }
2807
2808    # get database object
2809    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
2810
2811    # get all data from table role_user
2812    $DBObject->Prepare(
2813        SQL => 'SELECT user_id, role_id FROM role_user',
2814    );
2815
2816    # fetch the result
2817    my %UserRoleList;
2818    my %RoleUserList;
2819    my %UserRoleHash;
2820    while ( my @Row = $DBObject->FetchrowArray() ) {
2821
2822        $UserRoleList{ $Row[0] } ||= [];
2823        $RoleUserList{ $Row[1] } ||= [];
2824
2825        push @{ $UserRoleList{ $Row[0] } }, $Row[1];
2826        push @{ $RoleUserList{ $Row[1] } }, $Row[0];
2827
2828        $UserRoleHash{ $Row[0] }->{ $Row[1] } = 1;
2829    }
2830
2831    # set cache
2832    $CacheObject->Set(
2833        Type  => 'DBRoleUserGet',
2834        Key   => 'UserRoleList',
2835        TTL   => 60 * 60 * 24 * 20,
2836        Value => \%UserRoleList,
2837    );
2838    $CacheObject->Set(
2839        Type  => 'DBRoleUserGet',
2840        Key   => 'RoleUserList',
2841        TTL   => 60 * 60 * 24 * 20,
2842        Value => \%RoleUserList,
2843    );
2844    $CacheObject->Set(
2845        Type  => 'DBRoleUserGet',
2846        Key   => 'UserRoleHash',
2847        TTL   => 60 * 60 * 24 * 20,
2848        Value => \%UserRoleHash,
2849    );
2850
2851    return %UserRoleList if $Param{Type} eq 'UserRole';
2852    return %RoleUserList if $Param{Type} eq 'RoleUser';
2853    return %UserRoleHash;
2854}
2855
2856=head2 _PermissionTypeList()
2857
2858returns a list of valid system permissions.
2859
2860    %PermissionTypeList = $GroupObject->_PermissionTypeList(
2861        Type => 'close',  # (optional)
2862    );
2863
2864=cut
2865
2866sub _PermissionTypeList {
2867    my ( $Self, %Param ) = @_;
2868
2869    # get system permission config
2870    my $SystemPermissionConfig = $Kernel::OM->Get('Kernel::Config')->Get('System::Permission');
2871
2872    return () if !$SystemPermissionConfig;
2873    return () if ref $SystemPermissionConfig ne 'ARRAY';
2874
2875    my %TypeList;
2876    ROW:
2877    for my $Row ( @{$SystemPermissionConfig} ) {
2878
2879        next ROW if !$Row;
2880        next ROW if $Param{Type} && $Row ne $Param{Type};
2881
2882        $TypeList{$Row} = 1;
2883    }
2884
2885    $TypeList{rw} = 1;
2886
2887    return %TypeList;
2888}
2889
28901;
2891
2892=end Internal:
2893
2894=head1 TERMS AND CONDITIONS
2895
2896This software is part of the OTRS project (L<https://otrs.org/>).
2897
2898This software comes with ABSOLUTELY NO WARRANTY. For details, see
2899the enclosed file COPYING for license information (GPL). If you
2900did not receive this file, see L<https://www.gnu.org/licenses/gpl-3.0.txt>.
2901
2902=cut
2903