This commit was generated by cvs2svn to compensate for changes in r9232,
[freeside.git] / FS / FS / TicketSystem / RT_Internal.pm
1 package FS::TicketSystem::RT_Internal;
2
3 use strict;
4 use vars qw( @ISA $DEBUG $me );
5 use Data::Dumper;
6 use MIME::Entity;
7 use FS::UID qw(dbh);
8 use FS::CGI qw(popurl);
9 use FS::TicketSystem::RT_Libs;
10 use RT::CurrentUser;
11
12 @ISA = qw( FS::TicketSystem::RT_Libs );
13
14 $DEBUG = 0;
15 $me = '[FS::TicketSystem::RT_Internal]';
16
17 sub sql_num_customer_tickets {
18   "( select count(*) from Tickets
19                      join Links on ( Tickets.id = Links.LocalBase )
20      where ( Status = 'new' or Status = 'open' or Status = 'stalled' )
21        and Target = 'freeside://freeside/cust_main/' || custnum
22    )";
23 }
24
25 sub baseurl {
26   #my $self = shift;
27   if ( $RT::URI::freeside::URL ) {
28     $RT::URI::freeside::URL. '/rt/';
29   } else {
30     'http://you_need_to_set_RT_URI_freeside_URL_in_SiteConfig.pm/';
31   }
32 }
33
34 #mapping/genericize??
35 #ShowConfigTab ModifySelf
36 sub access_right {
37   my( $self, $session, $right ) = @_;
38
39   #return '' unless $conf->config('ticket_system');
40   return '' unless FS::Conf->new->config('ticket_system');
41
42   $session = $self->session($session);
43
44   #warn "$me access_right: CurrentUser ". $session->{'CurrentUser'}. ":\n".
45   #     ( $DEBUG>1 ? Dumper($session->{'CurrentUser'}) : '' )
46   #  if $DEBUG > 1;
47
48   $session->{'CurrentUser'}->HasRight( Right  => $right,
49                                        Object => $RT::System );
50 }
51
52 sub session {
53   my( $self, $session ) = @_;
54
55   if ( $session && $session->{'Current_User'} ) {
56     warn "$me session: using existing session and CurrentUser: \n".
57          Dumper($session->{'CurrentUser'})
58       if $DEBUG;
59  } else {
60     warn "$me session: loading session and CurrentUser\n" if $DEBUG > 1;
61     $session = $self->_web_external_auth($session);
62   }
63
64   $session;
65 }
66
67 sub init {
68   my $self = shift;
69
70   warn "$me init: loading RT libraries\n" if $DEBUG;
71   eval '
72     use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" );
73     use RT;
74     #it looks like the rest are taken care of these days in RT::InitClasses
75     #use RT::Ticket;
76     #use RT::Transactions;
77     #use RT::Users;
78     #use RT::CurrentUser;
79     #use RT::Templates;
80     #use RT::Queues;
81     #use RT::ScripActions;
82     #use RT::ScripConditions;
83     #use RT::Scrips;
84     #use RT::Groups;
85     #use RT::GroupMembers;
86     #use RT::CustomFields;
87     #use RT::CustomFieldValues;
88     #use RT::ObjectCustomFieldValues;
89
90     #for web external auth...
91     use RT::Interface::Web;
92   ';
93   die $@ if $@;
94
95   warn "$me init: loading RT config\n" if $DEBUG;
96   {
97     local $SIG{__DIE__};
98     eval 'RT::LoadConfig();';
99   }
100   die $@ if $@;
101
102   warn "$me init: initializing RT\n" if $DEBUG;
103   {
104     local $SIG{__DIE__};
105     eval 'RT::Init("NoSignalHandlers"=>1);';
106   }
107   die $@ if $@;
108
109   warn "$me init: complete" if $DEBUG;
110 }
111
112 =item create_ticket SESSION_HASHREF, OPTION => VALUE ...
113
114 Class method.  Creates a ticket.  If there is an error, returns the scalar
115 error, otherwise returns the newly created RT::Ticket object.
116
117 Accepts the following options:
118
119 =over 4
120
121 =item queue
122
123 Queue name or Id
124
125 =item subject
126
127 Ticket subject
128
129 =item requestor
130
131 Requestor email address or arrayref of addresses
132
133 =item cc
134
135 Cc: email address or arrayref of addresses
136
137 =item message
138
139 Ticket message
140
141 =item mime_type
142
143 MIME type to use for message.  Defaults to text/plain.  Specifying text/html
144 can be useful to use HTML markup in message.
145
146 =item custnum
147
148 Customer number (see L<FS::cust_main>) to associate with ticket.
149
150 =item svcnum
151
152 Service number (see L<FS::cust_svc>) to associate with ticket.  Will also
153 associate the customer who has this service (unless the service is unlinked).
154
155 =back
156
157 =cut
158
159 sub create_ticket {
160   my($self, $session, %param) = @_;
161
162   $session = $self->session($session);
163
164   my $Queue = RT::Queue->new($session->{'CurrentUser'});
165   $Queue->Load( $param{'queue'} );
166
167   my $req = ref($param{'requestor'})
168               ? $param{'requestor'}
169               : ( $param{'requestor'} ? [ $param{'requestor'} ] : [] );
170
171   my $cc = ref($param{'cc'})
172              ? $param{'cc'}
173              : ( $param{'cc'} ? [ $param{'cc'} ] : [] );
174
175   my $mimeobj = MIME::Entity->build(
176     'Data' => $param{'message'},
177     'Type' => ( $param{'mime_type'} || 'text/plain' ),
178   );
179
180   my %ticket = (
181     'Queue'     => $Queue->Id,
182     'Subject'   => $param{'subject'},
183     'Requestor' => $req,
184     'Cc'        => $cc,
185     'MIMEObj'   => $mimeobj,
186   );
187   warn Dumper(\%ticket) if $DEBUG > 1;
188
189   my $Ticket = RT::Ticket->new($session->{'CurrentUser'});
190   my( $id, $Transaction, $ErrStr );
191   {
192     local $SIG{__DIE__};
193     ( $id, $Transaction, $ErrStr ) = $Ticket->Create( %ticket );
194   }
195   return $ErrStr if $id == 0;
196
197   warn "ticket got id $id\n" if $DEBUG;
198
199   #XXX check errors adding custnum/svcnum links (put it in a transaction)...
200   # but we do already know they're good
201
202   if ( $param{'custnum'} ) {
203     my( $val, $msg ) = $Ticket->_AddLink(
204      'Type'   => 'MemberOf',
205      'Target' => 'freeside://freeside/cust_main/'. $param{'custnum'},
206     );
207   }
208
209   if ( $param{'svcnum'} ) {
210     my( $val, $msg ) = $Ticket->_AddLink(
211      'Type'   => 'MemberOf',
212      'Target' => 'freeside://freeside/cust_svc/'. $param{'svcnum'},
213     );
214   }
215
216   $Ticket;
217 }
218
219 #shameless false laziness w/RT::Interface::Web::AttemptExternalAuth
220 # to get logged into RT from afar
221 sub _web_external_auth {
222   my( $self, $session ) = @_;
223
224   my $user = $FS::CurrentUser::CurrentUser->username;
225
226   $session ||= {};
227   $session->{'CurrentUser'} = RT::CurrentUser->new();
228
229   warn "$me _web_external_auth loading RT user for $user\n"
230     if $DEBUG > 1;
231
232   $session->{'CurrentUser'}->Load($user);
233
234   if ( ! $session->{'CurrentUser'}->Id() ) {
235
236       # Create users on-the-fly
237
238       warn "can't load RT user for $user; auto-creating\n"
239         if $DEBUG;
240
241       my $UserObj = RT::User->new( RT::CurrentUser->new('RT_System') );
242
243       my ( $val, $msg ) = $UserObj->Create(
244           %{ ref($RT::AutoCreate) ? $RT::AutoCreate : {} },
245           Name  => $user,
246           Gecos => $user,
247       );
248
249       if ($val) {
250
251           # now get user specific information, to better create our user.
252           my $new_user_info
253               = RT::Interface::Web::WebExternalAutoInfo($user);
254
255           # set the attributes that have been defined.
256           # FIXME: this is a horrible kludge. I'm sure there's something cleaner
257           foreach my $attribute (
258               'Name',                  'Comments',
259               'Signature',             'EmailAddress',
260               'PagerEmailAddress',     'FreeformContactInfo',
261               'Organization',          'Disabled',
262               'Privileged',            'RealName',
263               'NickName',              'Lang',
264               'EmailEncoding',         'WebEncoding',
265               'ExternalContactInfoId', 'ContactInfoSystem',
266               'ExternalAuthId',        'Gecos',
267               'HomePhone',             'WorkPhone',
268               'MobilePhone',           'PagerPhone',
269               'Address1',              'Address2',
270               'City',                  'State',
271               'Zip',                   'Country'
272               )
273           {
274               #uhh, wrong root
275               #$m->comp( '/Elements/Callback', %ARGS,
276               #    _CallbackName => 'NewUser' );
277
278               my $method = "Set$attribute";
279               $UserObj->$method( $new_user_info->{$attribute} )
280                   if ( defined $new_user_info->{$attribute} );
281           }
282           $session->{'CurrentUser'}->Load($user);
283       }
284       else {
285
286          # we failed to successfully create the user. abort abort abort.
287           delete $session->{'CurrentUser'};
288
289           die "can't auto-create RT user"; #an error message would be nice :/
290           #$m->abort() unless $RT::WebFallbackToInternalAuth;
291           #$m->comp( '/Elements/Login', %ARGS,
292           #    Error => loc( 'Cannot create user: [_1]', $msg ) );
293       }
294   }
295
296   unless ( $session->{'CurrentUser'}->Id() ) {
297       delete $session->{'CurrentUser'};
298
299       die "can't auto-create RT user";
300       #$user = $orig_user;
301       # 
302       #if ($RT::WebExternalOnly) {
303       #    $m->comp( '/Elements/Login', %ARGS,
304       #        Error => loc('You are not an authorized user') );
305       #    $m->abort();
306       #}
307   }
308
309   $session;
310
311 }
312
313 1;
314