1# BEGIN BPS TAGGED BLOCK {{{
2#
3# COPYRIGHT:
4#
5# This software is Copyright (c) 1996-2021 Best Practical Solutions, LLC
6#                                          <sales@bestpractical.com>
7#
8# (Except where explicitly superseded by other copyright notices)
9#
10#
11# LICENSE:
12#
13# This work is made available to you under the terms of Version 2 of
14# the GNU General Public License. A copy of that license should have
15# been provided with this software, but in any event can be snarfed
16# from www.gnu.org.
17#
18# This work is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26# 02110-1301 or visit their web page on the internet at
27# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28#
29#
30# CONTRIBUTION SUBMISSION POLICY:
31#
32# (The following paragraph is not intended to limit the rights granted
33# to you to modify and distribute this software under the terms of
34# the GNU General Public License and is only of importance to you if
35# you choose to contribute your changes and enhancements to the
36# community by submitting them to Best Practical Solutions, LLC.)
37#
38# By intentionally submitting any modifications, corrections or
39# derivatives to this work, or any other work intended for use with
40# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41# you are the copyright holder for those contributions and you grant
42# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
43# royalty-free, perpetual, license to use, copy, create derivative
44# works based on those contributions, and sublicense and distribute
45# those contributions and any derivatives thereof.
46#
47# END BPS TAGGED BLOCK }}}
48
49package RT::REST2::Resource::User;
50use strict;
51use warnings;
52
53use Moose;
54use namespace::autoclean;
55use RT::REST2::Util qw(expand_uid);
56
57extends 'RT::REST2::Resource::Record';
58with (
59    'RT::REST2::Resource::Record::Readable',
60    'RT::REST2::Resource::Record::DeletableByDisabling',
61    'RT::REST2::Resource::Record::Writable',
62    'RT::REST2::Resource::Record::Hypermedia'
63        => { -alias => { hypermedia_links => '_default_hypermedia_links' } },
64);
65
66sub dispatch_rules {
67    Path::Dispatcher::Rule::Regex->new(
68        regex => qr{^/user/?$},
69        block => sub { { record_class => 'RT::User' } },
70    ),
71    Path::Dispatcher::Rule::Regex->new(
72        regex => qr{^/user/(\d+)/?$},
73        block => sub { { record_class => 'RT::User', record_id => shift->pos(1) } },
74    ),
75    Path::Dispatcher::Rule::Regex->new(
76        regex => qr{^/user/([^/]+)/?$},
77        block => sub {
78            my ($match, $req) = @_;
79            my $user = RT::User->new($req->env->{"rt.current_user"});
80            $user->Load($match->pos(1));
81            return { record => $user };
82        },
83    ),
84}
85
86around 'serialize' => sub {
87    my $orig = shift;
88    my $self = shift;
89    my $data = $self->$orig(@_);
90    $data->{Privileged} = $self->record->Privileged ? 1 : 0;
91
92    unless ( $self->record->CurrentUserHasRight("AdminUsers") or $self->record->id == $self->current_user->id ) {
93        my $summary = { map { $_ => $data->{$_} }
94                ( '_hyperlinks', 'Privileged', split( /\s*,\s*/, RT->Config->Get('UserSummaryExtraInfo') ) ) };
95        return $summary;
96    }
97
98    $data->{Disabled}   = $self->record->PrincipalObj->Disabled;
99    $data->{Memberships} = [
100        map { expand_uid($_->UID) }
101        @{ $self->record->OwnGroups->ItemsArrayRef }
102    ];
103    return $data;
104};
105
106sub forbidden {
107    my $self = shift;
108    return 0 if not $self->record->id;
109    return 0 if $self->record->id == $self->current_user->id;
110    return 0 if $self->current_user->Privileged;
111    return 1;
112}
113
114sub hypermedia_links {
115    my $self = shift;
116    my $links = $self->_default_hypermedia_links(@_);
117
118    if (   $self->record->CurrentUserHasRight('ShowUserHistory')
119        or $self->record->CurrentUserHasRight("AdminUsers")
120        or $self->record->id == $self->current_user->id )
121    {
122        push @$links, $self->_transaction_history_link;
123    }
124
125    # TODO Use the same right in UserGroups.pm.
126    # Maybe loose it a bit so user can see groups?
127    if ((   $self->current_user->HasRight(
128                Right  => "ModifyOwnMembership",
129                Object => RT->System,
130            )
131            && $self->current_user->id == $self->record->id
132        )
133        || $self->current_user->HasRight(
134            Right  => 'AdminGroupMembership',
135            Object => RT->System
136        )
137       )
138    {
139
140        my $id = $self->record->id;
141        push @$links,
142            {
143            ref  => 'memberships',
144            _url => RT::REST2->base_uri . "/user/$id/groups",
145            };
146    }
147
148    return $links;
149}
150
151__PACKAGE__->meta->make_immutable;
152
1531;
154