import rt 3.8.10
[freeside.git] / rt / lib / RT / Installer.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2011 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
49 package RT::Installer;
50 use strict;
51 use warnings;
52
53 require UNIVERSAL::require;
54 my %Meta = (
55     DatabaseType => {
56         Widget          => '/Widgets/Form/Select',
57         WidgetArguments => {
58             Description => 'Database type',    # loc
59             Values      => [
60                 grep {
61                     my $m = 'DBD::' . $_;
62                     $m->require ? 1 : 0
63                   } qw/mysql Pg SQLite Oracle/
64             ],
65             ValuesLabel => {
66                 mysql  => 'MySQL',             #loc
67                 Pg     => 'PostgreSQL',        #loc
68                 SQLite => 'SQLite',            #loc
69                 Oracle => 'Oracle',            #loc
70             },
71         },
72     },
73     DatabaseHost => {
74         Widget          => '/Widgets/Form/String',
75         WidgetArguments => {
76             Description => 'Database host', #loc
77             Default => 1,
78             DefaultLabel => "Keep 'localhost' if you're not sure. Leave blank to connect locally over a socket", #loc
79             Hints => "The domain name of your database server (like 'db.example.com').",       #loc
80         },
81     },
82     DatabasePort => {
83         Widget          => '/Widgets/Form/Integer',
84         WidgetArguments => {
85             Description => 'Database port',         #loc
86             Default     => 1,
87             DefaultLabel =>
88               'Leave empty to use the default value for your database',              #loc
89         },
90     },
91     DatabaseName => {
92         Widget          => '/Widgets/Form/String',
93         WidgetArguments => {
94             Description => 'Database name',                       #loc
95         },
96     },
97     DatabaseAdmin => {
98         Widget          => '/Widgets/Form/String',
99         WidgetArguments => {
100             Default => 1,
101             Hints => "Leave this alone to use the default dba username for your database type", #loc
102             Description => 'DBA username', # loc
103             DefaultLabel => '',
104         },
105     },
106     DatabaseAdminPassword => {
107         Widget          => '/Widgets/Form/String',
108         WidgetArguments => {
109             Description => 'DBA password',  #loc
110             DefaultLabel => "The DBA's database password",#loc
111             Type => 'password',
112             Hints => "You must provide the dba's password so we can create the RT database and user.",
113         },
114     },
115     DatabaseUser => {
116         Widget          => '/Widgets/Form/String',
117         WidgetArguments => {
118             Description => 'Database username for RT',                      #loc
119             Hints => 'RT will connect to the database using this user.  It will be created for you.', #loc
120         },
121     },
122     DatabasePassword => {
123         Widget          => '/Widgets/Form/String',
124         WidgetArguments => {
125             Description => 'Database password for RT',                      #loc
126             Type        => 'password',
127             Hints       => 'The password RT should use to connect to the database.',
128         },
129     },
130     DatabaseRequireSSL => {
131         Widget          => '/Widgets/Form/Boolean',
132         WidgetArguments => {
133             Description => 'Use SSL?',    # loc
134         },
135     },
136     rtname => {
137         Widget          => '/Widgets/Form/String',
138         WidgetArguments => {
139             Description => 'Site name',                        #loc
140             Hints => 'RT will use this string to uniquely identify your installation and looks for it in the subject of emails to decide what ticket a message applies to.  We recommend that you set this to your internet domain. (ex: example.com)' #loc
141         },
142     },
143     MinimumPasswordLength => {
144         Widget          => '/Widgets/Form/Integer',
145         WidgetArguments => {
146             Description => 'Minimum password length',    #loc
147         },
148     },
149     Password => {
150         Widget          => '/Widgets/Form/String',
151         WidgetArguments => {
152             Description => 'Administrative password', #loc
153             Hints => 'RT will create a user called "root" and set this as their password', #loc
154             Type => 'password',
155         },
156     },
157     OwnerEmail => {
158         Widget          => '/Widgets/Form/String',
159         WidgetArguments => {
160             Description => 'RT Administrator Email',                   #loc
161             Hints => "When RT can't handle an email message, where should it be forwarded?", #loc
162         },
163     },
164     CommentAddress => {
165         Widget          => '/Widgets/Form/String',
166         WidgetArguments => {
167             Description => 'Comment address',                           #loc
168             Hints =>
169 'the default addresses that will be listed in From: and Reply-To: headers of comment mail.' #loc
170         },
171     },
172     CorrespondAddress => {
173         Widget          => '/Widgets/Form/String',
174         WidgetArguments => {
175             Description => 'Correspond address',    #loc
176             Hints =>
177 'the default addresses that will be listed in From: and Reply-To: headers of correspondence mail.' #loc
178         },
179     },
180     SendmailPath => {
181         Widget          => '/Widgets/Form/String',
182         WidgetArguments => {
183             Hints => 'Where to find your sendmail binary.',    #loc
184             Description => 'Path to sendmail', #loc
185         },
186     },
187     WebDomain => {
188         Widget          => '/Widgets/Form/String',
189         WidgetArguments => {
190             Description => 'Domain name',                  #loc
191             Hints => "Don't include http://, just something like 'localhost', 'rt.example.com'", #loc
192         },
193     },
194     WebPort => {
195         Widget          => '/Widgets/Form/Integer',
196         WidgetArguments => {
197             Description => 'Web port',                     #loc
198             Hints => 'which port your web server will listen to, e.g. 8080', #loc
199         },
200     },
201
202 );
203
204 my $HAS_DATETIME_TZ = eval { require DateTime::TimeZone };
205
206 if ($HAS_DATETIME_TZ) {
207     $Meta{Timezone} = {
208         Widget          => '/Widgets/Form/Select',
209         WidgetArguments => {
210             Description => 'Timezone',                              #loc
211             Callback    => sub {
212                 my $ret;
213                 $ret->{Values} = ['', DateTime::TimeZone->all_names];
214
215                 my $has_datetime = eval { require DateTime };
216                 if ( $has_datetime ) {
217                     my $dt = DateTime->now;
218                     for my $tz ( DateTime::TimeZone->all_names ) {
219                         $dt->set_time_zone( $tz );
220                         $ret->{ValuesLabel}{$tz} =
221                             $tz . ' ' . $dt->strftime('%z');
222                     }
223                 }
224                 $ret->{ValuesLabel}{''} = 'System Default'; #loc
225
226                 return $ret;
227             },
228         },
229     };
230 }
231 else {
232     $Meta{Timezone} = {
233         Widget          => '/Widgets/Form/String',
234         WidgetArguments => {
235             Description => 'Timezone',                              #loc
236         },
237     };
238 }
239
240 sub Meta {
241     my $class = shift;
242     my $type  = shift;
243     return $Meta{$type} if $type;
244     return \%Meta;
245 }
246
247 sub CurrentValue {
248     my $class = shift;
249     my $type  = shift;
250     $type = $class if !ref $class && $class && $class ne 'RT::Installer';
251
252     return undef unless $type;
253     return $RT::Installer
254       && exists $RT::Installer->{InstallConfig}{$type}
255       ? $RT::Installer->{InstallConfig}{$type}
256       : scalar RT->Config->Get($type);
257 }
258
259 sub CurrentValues {
260     my $class = shift;
261     my @types = @_;
262     push @types, $class if !ref $class && $class && $class ne 'RT::Installer';
263
264     return { map { $_ => CurrentValue($_) } @types };
265 }
266
267 sub ConfigFile {
268     require File::Spec;
269     return File::Spec->catfile( $RT::EtcPath, 'RT_SiteConfig.pm' );
270 }
271
272 sub SaveConfig {
273     my $class = shift;
274
275     my $file = $class->ConfigFile;
276
277     my $content;
278
279     {
280         local $/;
281         open( my $fh, '<', $file ) or die $!;
282         $content = <$fh>;
283         $content =~ s/^\s*1;\s*$//m;
284     }
285
286     # make organization the same as rtname
287     $RT::Installer->{InstallConfig}{Organization} =
288       $RT::Installer->{InstallConfig}{rtname};
289
290     if ( open my $fh, '>', $file ) {
291         for ( keys %{ $RT::Installer->{InstallConfig} } ) {
292
293             # we don't want to store root's password in config.
294             next if $_ eq 'Password';
295
296             $RT::Installer->{InstallConfig}{$_} = ''
297               unless defined $RT::Installer->{InstallConfig}{$_};
298
299             # remove obsolete settings we'll add later
300             $content =~ s/^\s* Set \s* \( \s* \$$_ .*$//xm;
301
302             $content .= "Set( \$$_, '$RT::Installer->{InstallConfig}{$_}' );\n";
303         }
304         $content .= "1;\n";
305         print $fh $content;
306         close $fh;
307
308         return ( 1, "Successfully saved configuration to $file." );
309     }
310
311     return ( 0, "Cannot save configuration to $file: $!" );
312 }
313
314 =head1 NAME
315
316     RT::Installer - RT's Installer
317
318 =head1 SYNOPSYS
319
320     use RT::Installer;
321     my $meta = RT::Installer->Meta;
322
323 =head1 DESCRIPTION
324
325 C<RT::Installer> class provides access to RT Installer Meta
326
327 =cut
328
329 RT::Base->_ImportOverlays();
330
331 1;
332