diff options
Diffstat (limited to 'rt/etc')
79 files changed, 9698 insertions, 0 deletions
diff --git a/rt/etc/RT_Config.pm b/rt/etc/RT_Config.pm new file mode 100644 index 000000000..21d837546 --- /dev/null +++ b/rt/etc/RT_Config.pm @@ -0,0 +1,1831 @@ + +package RT; + +=head1 NAME + +RT::Config + +=for testing + +use RT::Config; + +=cut + +=head1 WARNING + +NEVER EDIT RT_Config.pm. + +Instead, copy any sections you want to change to F<RT_SiteConfig.pm> and edit them there. + +=cut + +=head1 Base Configuration + +=over 4 + +=item C<$rtname> + +C<$rtname> is the string that RT will look for in mail messages to +figure out what ticket a new piece of mail belongs to. + +Your domain name is recommended, so as not to pollute the namespace. +once you start using a given tag, you should probably never change it. +(otherwise, mail for existing tickets won't get put in the right place) + +=cut + +Set($rtname , "example.com"); + + +=item C<$EmailSubjectTagRegex> + +This regexp controls what subject tags RT recognizes as its own. +If you're not dealing with historical C<$rtname> values, you'll likely +never have to enable this feature. + +Be VERY CAREFUL with it. Note that it overrides C<$rtname> for subject +token matching and that you should use only "non-capturing" parenthesis +grouping. For example: + +C<Set($EmailSubjectTagRegex, qr/(?:example.com|example.org)/i );> + +and NOT + +C<Set($EmailSubjectTagRegex, qr/(example.com|example.org)/i );> + +This setting would make RT behave exactly as it does without the +setting enabled. + +=cut + +#Set($EmailSubjectTagRegex, qr/\Q$rtname\E/i ); + + + +=item C<$Organization> + +You should set this to your organization's DNS domain. For example, +I<fsck.com> or I<asylum.arkham.ma.us>. It's used by the linking interface to +guarantee that ticket URIs are unique and easy to construct. + +=cut + +Set($Organization , "example.com"); + +=item C<$MinimumPasswordLength> + +C<$MinimumPasswordLength> defines the minimum length for user +passwords. Setting it to 0 disables this check. + +=cut + +Set($MinimumPasswordLength , "5"); + +=item C<$Timezone> + +C<$Timezone> is used to convert times entered by users into GMT and back again +It should be set to a timezone recognized by your local unix box. + +=cut + +Set($Timezone , 'US/Eastern'); + +=back + +=head1 Database Configuration + +=over 4 + +=item C<$DatabaseType> + +Database driver being used; case matters. + +Valid types are "mysql", "Oracle" and "Pg" + +=cut + +Set($DatabaseType , 'Pg'); + +=item C<$DatabaseHost>, C<$DatabaseRTHost> + +The domain name of your database server. + +If you're running mysql and it's on localhost, +leave it blank for enhanced performance + +=cut + +Set($DatabaseHost , 'localhost'); +Set($DatabaseRTHost , 'localhost'); + +=item C<$DatabasePort> + +The port that your database server is running on. Ignored unless it's +a positive integer. It's usually safe to leave this blank + +=cut + +Set($DatabasePort , ''); + +=item C<$DatabaseUser> + +The name of the database user (inside the database) + +=cut + +Set($DatabaseUser , 'freeside'); + +=item C<$DatabasePassword> + +Password the C<$DatabaseUser> should use to access the database + +=cut + +Set($DatabasePassword , ''); + +=item C<$DatabaseName> + +The name of the RT's database on your database server. For Oracle +it's SID, DB objects are created in L<$DatabaseUser>'s schema. + +=cut + +Set($DatabaseName , 'freeside'); + +=item C<$DatabaseRequireSSL> + +If you're using Postgres and have compiled in SSL support, +set C<$DatabaseRequireSSL> to 1 to turn on SSL communication + +=cut + +Set($DatabaseRequireSSL , undef); + +=item C<$UseSQLForACLChecks> + +In RT for ages ACL are checked after search what in some situtations +result in empty search pages and wrong count of tickets. + +Set C<$UseSQLForACLChecks> to 1 to use SQL and get rid of these problems. + +However, this option is beta. In some cases it result in performance +improvements, but some setups can not handle it. + +=cut + +Set($UseSQLForACLChecks, undef); + +=item C<$TicketsItemMapSize> + +In RT at display page of a ticket and there is the current search, +then links for first, next, previous and last ticket are shown in +the menu. + +To build full map RT has to fetch full result set out of DB what can +eat lots of resourses. Using this option it's possible to limit number +of tickets fetched. + +Set C<$TicketsItemMapSize> to number of tickets you want RT to look +at to build the map. If full result set is bigger than that number +then there would be no 'last' link in the menu. + +Set this to zero to return back to old behaviour. + +=cut + +Set($TicketsItemMapSize, 1000); + +=back + +=head1 Incoming Mail Gateway Configuration + +=over 4 + +=item C<$OwnerEmail> + +C<$OwnerEmail> is the address of a human who manages RT. RT will send +errors generated by the mail gateway to this address. This address +should _not_ be an address that's managed by your RT instance. + +=cut + +Set($OwnerEmail , 'root'); + +=item C<$LoopsToRTOwner> + +If C<$LoopsToRTOwner> is defined, RT will send mail that it believes +might be a loop to C<$OwnerEmail> + +=cut + +Set($LoopsToRTOwner , 1); + +=item C<$StoreLoops> + +If C<$StoreLoops> is defined, RT will record messages that it believes +to be part of mail loops. + +As it does this, it will try to be careful not to send mail to the +sender of these messages + +=cut + +Set($StoreLoops , undef); + +=item C<$MaxAttachmentSize> + +C<$MaxAttachmentSize> sets the maximum size (in bytes) of attachments stored +in the database. + +For mysql and oracle, we set this size at 10 megabytes. +If you're running a postgres version earlier than 7.1, you will need +to drop this to 8192. (8k) + +=cut + + +Set($MaxAttachmentSize , 10000000); + +=item C<$TruncateLongAttachments> + +C<$TruncateLongAttachments>: if this is set to a non-undef value, +RT will truncate attachments longer than C<$MaxAttachmentSize>. + +=cut + +Set($TruncateLongAttachments , undef); + +=item C<$DropLongAttachments> + +C<$DropLongAttachments>: if this is set to a non-undef value, +RT will silently drop attachments longer than C<MaxAttachmentSize>. + +=cut + +Set($DropLongAttachments , undef); + +=item C<$ParseNewMessageForTicketCcs> + +If C<$ParseNewMessageForTicketCcs> is true, RT will attempt to divine +Ticket 'Cc' watchers from the To and Cc lines of incoming messages +Be forewarned that if you have _any_ addresses which forward mail to +RT automatically and you enable this option without modifying +C<$RTAddressRegexp> below, you will get yourself into a heap of trouble. + +=cut + +Set($ParseNewMessageForTicketCcs , undef); + +=item C<$RTAddressRegexp> + +C<$RTAddressRegexp> is used to make sure RT doesn't add itself as a ticket CC if +the setting above is enabled. It is important that you set this to a +regular expression that matches all addresses used by your RT. This lets RT +avoid sending mail to itself. It will also hide RT addresses from the list of +"One-time Cc" and Bcc lists on ticket reply. + +=cut + +Set($RTAddressRegexp , undef); + +=item C<$CanonicalizeEmailAddressMatch>, C<$CanonicalizeEmailAddressReplace> + +RT provides functionality which allows the system to rewrite +incoming email addresses. In its simplest form, +you can substitute the value in $<CanonicalizeEmailAddressReplace> +for the value in $<CanonicalizeEmailAddressMatch> +(These values are passed to the $<CanonicalizeEmailAddress> subroutine in + F<RT/User.pm>) + +By default, that routine performs a C<s/$Match/$Replace/gi> on any address +passed to it. + +=cut + +#Set($CanonicalizeEmailAddressMatch , '@subdomain\.example\.com$'); +#Set($CanonicalizeEmailAddressReplace , '@example.com'); + +=item C<$CanonicalizeEmailAddressMatch> + +Set this to true and the create new user page will use the values that you +enter in the form but use the function CanonicalizeUserInfo in +F<RT/User_Local.pm> + +=cut + +Set($CanonicalizeOnCreate, 0); + +=item C<$SenderMustExistInExternalDatabase> + +If C<$SenderMustExistInExternalDatabase> is true, RT will refuse to +create non-privileged accounts for unknown users if you are using +the C<$LookupSenderInExternalDatabase> option. +Instead, an error message will be mailed and RT will forward the +message to C<$RTOwner>. + +If you are not using C<$LookupSenderInExternalDatabase>, this option +has no effect. + +If you define an AutoRejectRequest template, RT will use this +template for the rejection message. + +=cut + +Set($SenderMustExistInExternalDatabase , undef); + +=item C<$ValidateUserEmailAddresses> + +If C<$ValidateUserEmailAddresses> is true, RT will refuse to create users with +an invalid email address (as specified in RFC 2822) or with an email address +made of multiple email adresses. + +=cut + +Set($ValidateUserEmailAddresses, undef); + +=item C<@MailPlugins> + +C<@MailPlugins> is a list of auth plugins for L<RT::Interface::Email> +to use; see L<rt-mailgate> + +=cut + +=item C<$UnsafeEmailCommands> + +C<$UnsafeEmailCommands>, if set to true, enables 'take' and 'resolve' +as possible actions via the mail gateway. As its name implies, this +is very unsafe, as it allows email with a forged sender to possibly +resolve arbitrary tickets! + +=cut + +=item C<$ExtractSubjectTagMatch>, C<$ExtractSubjectTagNoMatch> + +The default "extract remote tracking tags" scrip settings; these +detect when your RT is talking to another RT, and adjusts the +subject accordingly. + +=cut + +Set($ExtractSubjectTagMatch, qr/\[.+? #\d+\]/); +Set($ExtractSubjectTagNoMatch, ( ${RT::EmailSubjectTagRegex} + ? qr/\[(?:${RT::EmailSubjectTagRegex}) #\d+\]/ + : qr/\[\Q$RT::rtname\E #\d+\]/)); + +=back + +=head1 Outgoing Mail Configuration + +=over 4 + +=item C<$MailCommand> + +C<$MailCommand> defines which method RT will use to try to send mail. +We know that 'sendmailpipe' works fairly well. If 'sendmailpipe' +doesn't work well for you, try 'sendmail'. Other options are 'smtp' +or 'qmail'. + +Note that you should remove the '-t' from C<$SendmailArguments> +if you use 'sendmail' rather than 'sendmailpipe' + +=cut + +Set($MailCommand , 'sendmailpipe'); + +=item C<$SetOutgoingMailFrom> + +C<$SetOutgoingMailFrom> tells RT to set the sender envelope with the correspond +mail address of the ticket's queue. + +Warning: If you use this setting, bounced mails will appear to be incoming +mail to the system, thus creating new tickets. + +=cut + +Set($SetOutgoingMailFrom, 0); + +=item C<$OverrideOutgoingMailFrom> + +C<$OverrideOutgoingMailFrom> is used for overwriting the Correspond +address of the queue. The option is a hash reference of queue name to +email address. + +If there is no ticket involved, then the value of the C<Default> key will be +used. + +=cut + +Set($OverrideOutgoingMailFrom, { +# 'Default' => 'admin@rt.example.com', +# 'General' => 'general@rt.example.com', +}); + +=back + +=item C<$DefaultMailPrecedence> + +C<$DefaultMailPrecedence> is used to control the default +Precedence level of outgoing mail where none is specified. +By default it is C<bulk>, but if you only send mail to +your staff, you may wish to change it. + +Note that you can set the precedence of individual templates +by including an explicit Precedence header. + +If you set this value to C<undef> then we do not set a default +Precedence header to outgoing mail. However, if there already is a +Precedence header it will be preserved. + +=cut + +Set($DefaultMailPrecedence, 'bulk'); + +=back + +=item C<$DefaultErrorMailPrecedence> + +C<$DefaultErrorMailPrecedence> is used to control the default +Precedence level of outgoing mail that indicates some kind of +error condition. By default it is C<bulk>, but if you only send +mail to your staff, you may wish to change it. + +If you set this value to C<undef> then we do not add a Precedence +header to error mail. + +=cut + +Set($DefaultErrorMailPrecedence, 'bulk'); + +=back + +=item C<$UseOriginatorHeader> + +C<$UseOriginatorHeader> is used to control the insertion of an +RT-Originator Header in every outgoing mail, containing the +mail address of the transaction creator. + +=cut + +Set($UseOriginatorHeader, 1); + +=back + +=head1 Sendmail Configuration + +These options only take effect if C<$MailCommand> is 'sendmail' or +'sendmailpipe' + +=over 4 + +=item C<$SendmailArguments> + +C<$SendmailArguments> defines what flags to pass to C<$SendmailPath> +If you picked 'sendmailpipe', you MUST add a -t flag to C<$SendmailArguments> +These options are good for most sendmail wrappers and workalikes + +These arguments are good for sendmail brand sendmail 8 and newer +C<Set($SendmailArguments,"-oi -t -ODeliveryMode=b -OErrorMode=m");> + +=cut + +Set($SendmailArguments , "-oi -t"); + + +=item C<$SendmailBounceArguments> + +C<$SendmailBounceArguments> defines what flags to pass to C<$Sendmail> +assuming RT needs to send an error (ie. bounce). + +=cut + +Set($SendmailBounceArguments , '-f "<>"'); + +=item C<$SendmailPath> + +If you selected 'sendmailpipe' above, you MUST specify the path to +your sendmail binary in C<$SendmailPath>. + +=cut + +Set($SendmailPath , "/usr/sbin/sendmail"); + + +=back + +=head1 SMTP Configuration + +These options only take effect if C<$MailCommand> is 'smtp' + +=over 4 + +=item C<$SMTPServer> + +C<$SMTPServer> should be set to the hostname of the SMTP server to use + +=cut + +Set($SMTPServer, undef); + +=item C<$SMTPFrom> + +C<$SMTPFrom> should be set to the 'From' address to use, if not the +email's 'From' + +=cut + +Set($SMTPFrom, undef); + +=item C<$SMTPDebug> + +C<$SMTPDebug> should be set to true to debug SMTP mail sending + +=cut + +Set($SMTPDebug, 0); + +=back + +=head1 Other Mailer Configuration + +=over 4 + +=item C<@MailParams> + +C<@MailParams> defines a list of options passed to $MailCommand if it +is not 'sendmailpipe', 'sendmail', or 'smtp' + +=cut + +Set(@MailParams, ()); + +=item C<$CorrespondAddress>, C<$CommentAddress> + +RT is designed such that any mail which already has a ticket-id associated +with it will get to the right place automatically. + +C<$CorrespondAddress> and C<$CommentAddress> are the default addresses +that will be listed in From: and Reply-To: headers of correspondence +and comment mail tracked by RT, unless overridden by a queue-specific +address. + +=cut + +Set($CorrespondAddress , ''); + +Set($CommentAddress , ''); + +=item C<$DashboardAddress> + +The email address from which RT will send dashboards. If none is set, then +C<$OwnerEmail> will be used. + +=cut + +Set($DashboardAddress, ''); + +=item C<$UseFriendlyFromLine> + +By default, RT sets the outgoing mail's "From:" header to +"SenderName via RT". Setting C<$UseFriendlyFromLine> to 0 disables it. + +=cut + +Set($UseFriendlyFromLine, 1); + +=item C<$FriendlyFromLineFormat> + +C<sprintf()> format of the friendly 'From:' header; its arguments +are SenderName and SenderEmailAddress. + +=cut + +Set($FriendlyFromLineFormat, "\"%s via RT\" <%s>"); + +=item C<$UseFriendlyToLine> + +RT can optionally set a "Friendly" 'To:' header when sending messages to +Ccs or AdminCcs (rather than having a blank 'To:' header. + +This feature DOES NOT WORK WITH SENDMAIL[tm] BRAND SENDMAIL +If you are using sendmail, rather than postfix, qmail, exim or some other MTA, +you _must_ disable this option. + +=cut + +Set($UseFriendlyToLine, 0); + +=item C<$FriendlyToLineFormat> + +C<sprintf()> format of the friendly 'From:' header; its arguments +are WatcherType and TicketId. + +=cut + +Set($FriendlyToLineFormat, "\"%s of ". RT->Config->Get('rtname') ." Ticket #%s\":;"); + +=item C<$NotifyActor> + +By default, RT doesn't notify the person who performs an update, as they +already know what they've done. If you'd like to change this behaviour, +Set C<$NotifyActor> to 1 + +=cut + +Set($NotifyActor, 0); + +=item C<$RecordOutgoingEmail> + +By default, RT records each message it sends out to its own internal database. +To change this behavior, set C<$RecordOutgoingEmail> to 0 + +=cut + +Set($RecordOutgoingEmail, 1); + +=item C<$VERPPrefix>, C<$VERPPrefix> + +VERP support (http://cr.yp.to/proto/verp.txt) + +uncomment the following two directives to generate envelope senders +of the form C<${VERPPrefix}${originaladdress}@${VERPDomain}> +(i.e. rt-jesse=fsck.com@rt.example.com ). + +This currently only works with sendmail and sendmailppie. + +=cut + +# Set($VERPPrefix, 'rt-'); +# Set($VERPDomain, $RT::Organization); + + +=item C<$ForwardFromUser> + +By default, RT forwards a message using queue's address and adds RT's tag into +subject of the outgoing message, so recipients' replies go into RT as correspondents. + +To change this behavior, set C<$ForwardFromUser> to true value and RT will use +address of the current user and leave subject without RT's tag. + +=cut + +Set($ForwardFromUser, 0); + +=item C<$ShowBccHeader> + +By default RT hides from the web UI information about blind copies user sent on +reply or comment. + +To change this set the following option to true value. + +=cut + +Set($ShowBccHeader, 0); + +=item C<$DashboardSubject> + +Lets you set the subject of dashboards. Arguments are the frequency (Daily, +Weekly, Monthly) of the dashboard and the dashboard's name. [_1] for the name +of the dashboard. + +=cut + +Set($DashboardSubject, '%s Dashboard: %s'); + +=back + +=head1 GnuPG Configuration + +A full description of the (somewhat extensive) GnuPG integration can be found +by running the command `perldoc L<RT::Crypt::GnuPG>` (or `perldoc + lib/RT/Crypt/GnuPG.pm` from your RT install directory). + +=over 4 + +=item C<%GnuPG> + +Set C<OutgoingMessagesFormat> to 'inline' to use inline encryption and +signatures instead of 'RFC' (GPG/MIME: RFC3156 and RFC1847) format. + +If you want to allow people to encrypt attachments inside the DB then +set C<AllowEncryptDataInDB> to true + +Set C<RejectOnMissingPrivateKey> to false if you don't want to reject +emails encrypted for key RT doesn't have and can not decrypt. + +Set C<RejectOnBadData> to false if you don't want to reject letters +with incorrect GnuPG data. + +=cut + +Set( %GnuPG, + Enable => 1, + OutgoingMessagesFormat => 'RFC', # Inline + AllowEncryptDataInDB => 0, + + RejectOnMissingPrivateKey => 1, + RejectOnBadData => 1, +); + +=item C<%GnuPGOptions> + +Options of GnuPG program. + +If you override this in your RT_SiteConfig, you should be sure +to include a homedir setting. + +NOTE that options with '-' character MUST be quoted. + +=cut + +Set(%GnuPGOptions, + homedir => '/opt/rt3/var/data/gpg', + +# URL of a keyserver +# keyserver => 'hkp://subkeys.pgp.net', + +# enables the automatic retrieving of keys when encrypting +# 'auto-key-locate' => 'keyserver', + +# enables the automatic retrieving of keys when verifying signatures +# 'auto-key-retrieve' => undef, +); + + +=back + +=head1 Logging Configuration + +The default is to log anything except debugging +information to syslog. Check the L<Log::Dispatch> POD for +information about how to get things by syslog, mail or anything +else, get debugging info in the log, etc. + +It might generally make sense to send error and higher by email to +some administrator. If you do this, be careful that this email +isn't sent to this RT instance. Mail loops will generate a critical +log message. + +=over 4 + +=item C<$LogToSyslog>, C<$LogToScreen> + +The minimum level error that will be logged to the specific device. +From lowest to highest priority, the levels are: + debug info notice warning error critical alert emergency + +=cut + +Set($LogToSyslog , 'info'); +Set($LogToScreen , 'info'); + +=item C<$LogToFile>, C<$LogDir>, C<$LogToFileNamed> + +Logging to a standalone file is also possible, but note that the +file should needs to both exist and be writable by all direct users +of the RT API. This generally include the web server, whoever +rt-crontool runs as. Note that as rt-mailgate and the RT CLI go +through the webserver, so their users do not need to have write +permissions to this file. If you expect to have multiple users of +the direct API, Best Practical recommends using syslog instead of +direct file logging. + +=cut + +Set($LogToFile , undef); +Set($LogDir, '/opt/rt3/var/log'); +Set($LogToFileNamed , "rt.log"); #log to rt.log + +=item C<$LogStackTraces> + +If set to a log level then logging will include stack traces for +messages with level equal to or greater than specified. + +NOTICE: Stack traces include parameters supplied to functions or +methods. It is possible for stack trace logging to reveal sensitive +information such as passwords or ticket content in your logs. + +=cut + +Set($LogStackTraces, ''); + +=item C<@LogToSyslogConf> + +On Solaris or UnixWare, set to ( socket => 'inet' ). Options here +override any other options RT passes to L<Log::Dispatch::Syslog>. +Other interesting flags include facility and logopt. (See the +L<Log::Dispatch::Syslog> documentation for more information.) (Maybe +ident too, if you have multiple RT installations.) + +=cut + +Set(@LogToSyslogConf, ()); + +=item C<$StatementLog>, + +RT has rudimentary SQL statement logging support if you have +DBIx-SearchBuilder 1.31_1 or higher; simply set C<$StatementLog> to be +the level that you wish SQL statements to be logged at. + +=cut + +Set($StatementLog, undef); + +=back + +=head1 Web Interface Configuration + +=over 4 + +=item C<$WebDefaultStylesheet> + +This determines the default stylesheet the RT web interface will use. +RT ships with several themes by default: + + web2 The totally new, default layout for RT 3.8 + 3.5-default RT 3.5 and 3.6 original layout + 3.4-compat A 3.4 compatibility stylesheet to make RT look + (mostly) like 3.4 + +This bundled distibution of RT also includes (enabled by default): + freeside2.1 Integration with Freeside + +This value actually specifies a directory in F<share/html/NoAuth/css/> +from which RT will try to load the file main.css (which should +@import any other files the stylesheet needs). This allows you to +easily and cleanly create your own stylesheets to apply to RT. This +option can be overridden by users in their preferences. + +=cut + +Set($WebDefaultStylesheet, 'freeside2.1'); + +=item C<$UsernameFormat> + +This determines how user info is displayed. 'concise' will show one of +either NickName, RealName, Name or EmailAddress, depending on what exists +and whether the user is privileged or not. 'verbose' will show RealName and +EmailAddress. + +=cut + +Set($UsernameFormat, 'verbose'); + +=item C<$WebDomain> + +Domain name of the RT server, eg 'www.example.com'. It should not contain +anything else, but server name. + +=cut + +Set( $WebDomain, 'localhost' ); + +=item C<$WebPort> + +If we're running as a superuser, run on port 80 +Otherwise, pick a high port for this user. + +443 is default port for https protocol. + +=cut + +Set($WebPort, 80);# + ($< * 7274) % 32766 + ($< && 1024)); + +=item C<$WebPath> + +If you're putting the web ui somewhere other than at the root of +your server, you should set C<$WebPath> to the path you'll be +serving RT at. + +C<$WebPath> requires a leading / but no trailing /, or it can be blank. + +In most cases, you should leave C<$WebPath> set to '' (an empty value). + +=cut + +Set($WebPath, ""); + +=item C<$WebBaseURL>, C<$WebURL> + +Usually you don't want to set these options. The only obviouse reason is +RT accessible via https protocol on non standard port, eg +'https://rt.example.com:9999'. In all other cases these options are computed +using C<$WebDomain>, C<$WebPort> and C<$WebPath>. + +C<$WebBaseURL> is the scheme, server and port (eg 'http://rt.example.com') +for constructing urls to the web UI. C<$WebBaseURL> doesn't need a trailing /. + +C<$WebURL> is the C<$WebBaseURL>, C<$WebPath> and trailing /, for example: +'http://www.example.com/rt/'. + +=cut + +my $port = RT->Config->Get('WebPort'); +Set($WebBaseURL, + ($port == 443? 'https': 'http') .'://' + . RT->Config->Get('WebDomain') + . ($port != 80 && $port != 443? ":$port" : '') +); + +Set($WebURL, RT->Config->Get('WebBaseURL') . RT->Config->Get('WebPath') . "/"); + +=item C<$WebImagesURL> + +C<$WebImagesURL> points to the base URL where RT can find its images. +Define the directory name to be used for images in rt web +documents. + +=cut + +Set($WebImagesURL, RT->Config->Get('WebPath') . "/NoAuth/images/"); + +=item C<$LogoURL> + +C<$LogoURL> points to the URL of the RT logo displayed in the web UI + +=cut + +Set($LogoURL, RT->Config->Get('WebImagesURL') . "bplogo.gif"); + +=item C<$LogoLinkURL> + +C<$LogoLinkURL> is the URL that the RT logo hyperlinks to. + +=cut + +Set($LogoLinkURL, "http://bestpractical.com"); + +=item C<$LogoAltText> + +C<$LogoAltText> is a string of text for the alt-text of the logo. It +will be passed through C<loc> for localization. + +=cut + +Set($LogoAltText, "Best Practical Solutions, LLC corporate logo"); + +=item C<$LogoImageHeight> + +C<$LogoImageHeight> is the value of the C<height> attribute of the logo +C<img> tag. + +=cut + +Set($LogoImageHeight, 33); + +=item C<$LogoImageWidth> + +C<$LogoImageWidth> is the value of the C<width> attribute of the logo +C<img> tag. + +=cut + +Set($LogoImageWidth, 177); + +=item C<$WebNoAuthRegex> + +What portion of RT's URL space should not require authentication. + +This is mostly for extension and doesn't mean RT will work without +login if you change it. + +=cut + +Set($WebNoAuthRegex, qr{^ /rt (?:/+NoAuth/ | /+REST/\d+\.\d+/NoAuth/) }x ); + +=item C<$SelfServiceRegex> + +What portion of RT's URLspace should be accessible to Unprivileged users +This does not override the redirect from F</Ticket/Display.html> to +F</SelfService/Display.html> when Unprivileged users attempt to access +ticked displays + +=cut + +Set($SelfServiceRegex, qr!^(?:/+SelfService/)!x ); + +=item C<$MessageBoxWidth>, C<$MessageBoxHeight> + +For message boxes, set the entry box width, height and what type of +wrapping to use. These options can be overridden by users in their +preferences. + +Default width: 72, height: 15 + +These settings only apply to the non-RichText message box. +See below for Rich Text settings. + +=cut + +Set($MessageBoxWidth, 72); +Set($MessageBoxHeight, 15); + +=item C<$MessageBoxWrap> + +Default wrapping: "HARD" (choices "SOFT", "HARD") + +Wrapping is disabled when using MessageBoxRichText because +of a bad interaction between IE and wrapping with the Rich +Text Editor. + +=cut + +Set($MessageBoxWrap, "HARD"); + +=item C<$MessageBoxRichText> + +Should "rich text" editing be enabled? This option lets your users send html email messages from the web interface. + +=cut + +Set($MessageBoxRichText, 1); + +=item C<$MessageBoxRichTextHeight> + +Height of RichText javascript enabled editing boxes (in pixels) + +=cut + +Set($MessageBoxRichTextHeight, 200); + +=item C<$MessageBoxIncludeSignature> + +Should your user's signatures (from their Preferences page) be included in Comments and Replies + +=cut + +Set($MessageBoxIncludeSignature, 1); + +=item C<$MessageBoxIncludeSignatureOnComment> + +Should your user's signatures (from their Preferences page) be included in Comments. Setting this to false overrides C<$MessageBoxIncludeSignature>. + +=cut + +Set($MessageBoxIncludeSignatureOnComment, 1); + +=item C<$WikiImplicitLinks> + +Support implicit links in WikiText custom fields? A true value +causes InterCapped or ALLCAPS words in WikiText fields to +automatically become links to searches for those words. If used on +RTFM articles, it links to the RTFM article with that name. + +=cut + +Set($WikiImplicitLinks, 0); + +=item C<$TrustHTMLAttachments> + +if C<TrustHTMLAttachments> is not defined, we will display them +as text. This prevents malicious HTML and javascript from being +sent in a request (although there is probably more to it than that) + +=cut + +Set($TrustHTMLAttachments, undef); + +=item C<$AlwaysDownloadAttachments> + +Always download attachments, regardless of content type. If set, +this overrides C<TrustHTMLAttachments>. + +=cut + +Set($AlwaysDownloadAttachments, undef); + +=item C<$AttachmentUnits> + +Controls the units (kilobytes or bytes) that attachment sizes use +for display. The default is to display kilobytes if the attachment +is larger than 1024 bytes, bytes otherwise. If you set +C<$AttachmentUnits> to C<'k'> then attachment sizes will always be +displayed in kilobytes. If set to C<'b'>, then sizes will be bytes. + +=cut + +Set($AttachmentUnits, undef); + +=item C<$RedistributeAutoGeneratedMessages> + +Should RT redistribute correspondence that it identifies as +machine generated? A true value will do so; setting this to '0' +will cause no such messages to be redistributed. +You can also use 'privileged' (the default), which will redistribute +only to privileged users. This helps to protect against malformed +bounces and loops caused by autocreated requestors with bogus addresses. + +=cut + +Set($RedistributeAutoGeneratedMessages, 'privileged'); + +=item C<$PreferRichText> + +If C<$PreferRichText> is set to a true value, RT will show HTML/Rich text +messages in preference to their plaintext alternatives. RT "scrubs" the +html to show only a minimal subset of HTML to avoid possible contamination +by cross-site-scripting attacks. + +=cut + +Set($PreferRichText, undef); + +=item C<$WebExternalAuth> + +If C<$WebExternalAuth> is defined, RT will defer to the environment's +REMOTE_USER variable. + +=cut + +Set($WebExternalAuth, undef); + +=item C<$WebExternalAuthContinuous> + +If C<$WebExternalAuthContinuous> is defined, RT will check for the +REMOTE_USER on each access. If you would prefer this to only happen +once (at initial login) set this to a false value. The default setting +will help ensure that if your external auth system deauthenticates a +user, RT notices as soon as possible. + +=cut + +Set($WebExternalAuthContinuous, 1); + +=item C<$WebFallbackToInternalAuth> + +If C<$WebFallbackToInternalAuth> is defined, the user is allowed a chance +of fallback to the login screen, even if REMOTE_USER failed. + +=cut + +Set($WebFallbackToInternalAuth , undef); + +=item C<$WebExternalGecos> + +C<$WebExternalGecos> means to match 'gecos' field as the user identity); +useful with mod_auth_pwcheck and IIS Integrated Windows logon. + +=cut + +Set($WebExternalGecos , undef); + +=item C<$WebExternalAuto> + +C<$WebExternalAuto> will create users under the same name as REMOTE_USER +upon login, if it's missing in the Users table. + +=cut + +Set($WebExternalAuto , undef); + +=item C<$AutoCreate> + +If C<$WebExternalAuto> is true, C<$AutoCreate> will be passed to User's +Create method. Use it to set defaults, such as creating +Unprivileged users with C<{ Privileged => 0 }> +( Must be a hashref of arguments ) + +=cut + +Set($AutoCreate, undef); + +=item C<$WebSessionClass> + +C<$WebSessionClass> is the class you wish to use for managing Sessions. +It defaults to use your SQL database, but if you are using MySQL 3.x and +plans to use non-ascii Queue names, uncomment and add this line to +F<RT_SiteConfig.pm> will prevent session corruption. + +=cut + +# Set($WebSessionClass , 'Apache::Session::File'); + +=item C<$AutoLogoff> + +By default, RT's user sessions persist until a user closes his or her +browser. With the C<$AutoLogoff> option you can setup session lifetime in +minutes. A user will be logged out if he or she doesn't send any requests +to RT for the defined time. + +=cut + +Set($AutoLogoff, 0); + +=item C<$LogoutRefresh> + +The number of seconds to wait after logout before sending the user to the +login page. By default, 1 second, though you may want to increase this if +you display additional information on the logout page. + +=cut + +Set($LogoutRefresh, 1); + +=item C<$WebSecureCookies> + +By default, RT's session cookie isn't marked as "secure" Some web browsers +will treat secure cookies more carefully than non-secure ones, being careful +not to write them to disk, only send them over an SSL secured connection +and so on. To enable this behaviour, set C<$WebSecureCookies> to a true value. +NOTE: You probably don't want to turn this on _unless_ users are only connecting +via SSL encrypted HTTP connections. + +=cut + +Set($WebSecureCookies, 0); + +=item C<$WebFlushDbCacheEveryRequest> + +By default, RT clears its database cache after every page view. +This ensures that you've always got the most current information +when working in a multi-process (mod_perl or FastCGI) Environment +Setting C<$WebFlushDbCacheEveryRequest> to '0' will turn this off, +which will speed RT up a bit, at the expense of a tiny bit of data +accuracy. + +=cut + +Set($WebFlushDbCacheEveryRequest, '1'); + + +=item C<$MaxInlineBody> + +C<$MaxInlineBody> is the maximum attachment size that we want to see +inline when viewing a transaction. RT will inline any text if value +is undefined or 0. This option can be overridden by users in their +preferences. + +=cut + +Set($MaxInlineBody, 12000); + +=item C<$DefaultSummaryRows> + +C<$DefaultSummaryRows> is default number of rows displayed in for search +results on the frontpage. + +=cut + +Set($DefaultSummaryRows, 10); + +=item C<$HomePageRefreshInterval> + +C<$HomePageRefreshInterval> is default number of seconds to refresh the RT +home page. Choose from [0, 120, 300, 600, 1200, 3600, 7200]. + +=cut + +Set($HomePageRefreshInterval, 0); + +=item C<$SearchResultsRefreshInterval> + +C<$SearchResultsRefreshInterval> is default number of seconds to refresh +search results in RT. Choose from [0, 120, 300, 600, 1200, 3600, 7200]. + +=cut + +Set($SearchResultsRefreshInterval, 0); + +=item C<$OldestTransactionsFirst> + +By default, RT shows newest transactions at the bottom of the ticket +history page, if you want see them at the top set this to '0'. This +option can be overridden by users in their preferences. + +=cut + +Set($OldestTransactionsFirst, '1'); + +=item C<$ShowTransactionImages> + +By default, RT shows images attached to incoming (and outgoing) ticket updates +inline. Set this variable to 0 if you'd like to disable that behaviour + +=cut + +Set($ShowTransactionImages, 1); + +=item C<$PlainTextPre> + +Normally plaintext attachments are displayed as HTML with line +breaks preserved. This causes space- and tab-based formatting not +to be displayed correctly. By setting $PlainTextPre they'll be +displayed using <pre> instead so such formatting works, but they'll +use a monospaced font, no matter what the value of C<$PlainTextMono> is. + +=cut + +Set($PlainTextPre, 0); + + +=item C<$PlainTextMono> +To display plaintext attachments, +Set C<$PlainTextMono> to 1 to use monospaced font and preserve +formatting, but unlike PlainTextPre, the text will wrap to fit into the +UI. + +=cut + +Set($PlainTextMono, 0); + +=item C<$ShowUnreadMessageNotifications> + +By default, RT will prompt users when there are new, unread messages on +tickets they are viewing. + +Set C<$ShowUnreadMessageNotifications> to a false value to disable this feature. + +=cut + +Set($ShowUnreadMessageNotifications, 1); + + +=item C<$HomepageComponents> + +C<$HomepageComponents> is an arrayref of allowed components on a user's +customized homepage ("RT at a glance"). + +=cut + +Set($HomepageComponents, [qw(QuickCreate Quicksearch MyCalendar MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards)]); + +=item C<@MasonParameters> + +C<@MasonParameters> is the list of parameters for the constructor of +HTML::Mason's Apache or CGI Handler. This is normally only useful +for debugging, eg. profiling individual components with: + + use MasonX::Profiler; # available on CPAN + Set(@MasonParameters, (preamble => 'my $p = MasonX::Profiler->new($m, $r);')); + +=cut + +Set(@MasonParameters, ()); + +=item C<$DefaultSearchResultFormat> + +C<$DefaultSearchResultFormat> is the default format for RT search results + +=cut + +Set ($DefaultSearchResultFormat, qq{ + '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__id__</a></B>/TITLE:#', + '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', + Customer, + Status, + QueueName, + OwnerName, + Priority, + '__NEWLINE__', + '', + '<small>__Requestors__</small>', + '', + '<small>__CreatedRelative__</small>', + '<small>__ToldRelative__</small>', + '<small>__LastUpdatedRelative__</small>', + '<small>__TimeLeft__</small>'}); + +=item C<$DefaultSelfServiceSearchResultFormat> + +C<$DefaultSelfServiceSearchResultFormat> is the default format of searches displayed in the +SelfService interface. + +=cut + +Set($DefaultSelfServiceSearchResultFormat, qq{ + '<B><A HREF="__WebPath__/SelfService/Display.html?id=__id__">__id__</a></B>/TITLE:#', + '<B><A HREF="__WebPath__/SelfService/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', + Status, + Requestors, + OwnerName}); + +=item C<%AdminSearchResultFormat> + +In admin interface format strings similar to tickets search result +formats are used. Use C<%AdminSearchResultFormat> to define format +strings per RT class. + +=cut + +Set(%AdminSearchResultFormat, + Queues => + q{'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__Description__,__Address__,__Priority__,__DefaultDueIn__,__Disabled__}, + + Groups => + q{'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,'__Description__'}, + + Users => + q{'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__RealName__, __EmailAddress__}, + + CustomFields => + q{'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__AppliedTo__, __FriendlyType__, __FriendlyPattern__}, + + Scrips => + q{'<a href="__WebPath__/__WebRequestPathDir__/Scrip.html?id=__id__&Queue=__QueueId__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/__WebRequestPathDir__/Scrip.html?id=__id__&Queue=__QueueId__">__Description__</a>/TITLE:Description'} + .q{,__Stage__, __Condition__, __Action__, __Template__}, + + Templates => + q{'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__Name__</a>/TITLE:Name'} + .q{,'__Description__'}, +); + +=item C<$SuppressInlineTextFiles> + +If C<$SuppressInlineTextFiles> is set to a true value, then uploaded +text files (text-type attachments with file names) are prevented +from being displayed in-line when viewing a ticket's history. + +=cut + +Set($SuppressInlineTextFiles, undef); + +=item C<$DontSearchFileAttachments> + +If C<$DontSearchFileAttachments> is set to a true value, then uploaded +files (attachments with file names) are not searched during full-content +ticket searches. + +=cut + +Set($DontSearchFileAttachments, undef); + +=item C<%ChartFont> + +The L<GD> module (which RT uses for graphs) ships with a builtin font +that doesn't have full Unicode support. You can use a given TrueType font +for a specific language by setting %ChartFont to (language =E<gt> the +absolute path of a font) pairs. Your GD library must have support for +TrueType fonts to use this option. If there is no entry for a language +in the hash then font with 'others' key is used. + +RT comes with two TrueType fonts covering most available languages. + +=cut + +Set( + %ChartFont, + 'zh-cn' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'zh-tw' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'ja' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'others' => "$RT::BasePath/share/fonts/DroidSans.ttf", +); + +=item C<$ChartsTimezonesInDB> + +Dates are stored using UTC timezone in the DB, so charts groupped +by dates and time are not representative. Set C<$ChartsTimezonesInDB> +to a true value to enable timezones conversions using DB's +capabilities. You may need to do some work on DB side to use this +feature, read more in F<docs/timezones_in_charts.pod>. + +=cut + +Set( $ChartsTimezonesInDB, 0 ); + +=item C<@Active_MakeClicky> + +MakeClicky detects various formats of data in headers and email +messages, and extends them with supporting links. By default, RT +provides two formats: + +* 'httpurl': detects http:// and https:// URLs and adds '[Open URL]' + link after the URL. + +* 'httpurl_overwrite': also detects URLs as 'httpurl' format, but + replace URL with link and *adds spaces* into text if it's longer + then 30 chars. This allow browser to wrap long URLs and avoid + horizontal scrolling. + +See F<share/html/Elements/MakeClicky> for documentation on how to add your own. + +=cut + +Set(@Active_MakeClicky, qw()); + +=item C<$DefaultQueue> + +Use this to select the default queue name that will be used for creating new +tickets. You may use either the queue's name or its ID. This only affects the +queue selection boxes on the web interface. + +=cut + +#Set($DefaultQueue, 'General'); + +=item C<$DefaultTimeUnitsToHours> + +Use this to set the default units for time entry to hours instead of minutes. + +=cut + +Set($DefaultTimeUnitsToHours, 0); + +=back + +=head1 L<Net::Server> (rt-server) Configuration + +=over 4 + +=item C<$StandaloneMinServers>, C<$StandaloneMaxServers> + +The absolute minimum and maximum number of servers that will be created to +handle requests. Having multiple servers means that serving a slow page will +affect other users less. + +=cut + +Set($StandaloneMinServers, 1); +Set($StandaloneMaxServers, 1); + +=item C<$StandaloneMinSpareServers>, C<$StandaloneMaxSpareServers> + +These next two options can be used to scale up and down the number of servers +to adjust to load. These two options will respect the C<$StandaloneMinServers +> and C<$StandaloneMaxServers options>. + +=cut + +Set($StandaloneMinSpareServers, 0); +Set($StandaloneMaxSpareServers, 0); + +=item C<$StandaloneMaxRequests> + +This sets the absolute maximum number of requests a single server will serve. +Setting this would be useful if, for example, memory usage slowly crawls up +every hit. + +=cut + +#Set($StandaloneMaxRequests, 50); + +=item C<%NetServerOptions> + +C<%NetServerOptions> is a hash of additional options to use for +L<Net::Server/DEFAULT ARGUMENTS>. For example, you could set +reverse_lookups to get the hostnames for all users with: + +C<Set(%NetServerOptions, (reverse_lookups => 1));> + +=cut + +Set(%NetServerOptions, ()); + +=back + + +=head1 UTF-8 Configuration + +=over 4 + +=item C<@LexiconLanguages> + +An array that contains languages supported by RT's internationalization +interface. Defaults to all *.po lexicons; setting it to C<qw(en ja)> will make +RT bilingual instead of multilingual, but will save some memory. + +=cut + +Set(@LexiconLanguages, qw(*)); + +=item C<@EmailInputEncodings> + +An array that contains default encodings used to guess which charset +an attachment uses if not specified. Must be recognized by +L<Encode::Guess>. + +=cut + +Set(@EmailInputEncodings, qw(utf-8 iso-8859-1 us-ascii)); + +=item C<$EmailOutputEncoding> + +The charset for localized email. Must be recognized by Encode. + +=cut + +Set($EmailOutputEncoding, 'utf-8'); + + +=back + +=head1 Date Handling Configuration + +=over 4 + +=item C<$DateTimeFormat> + +You can choose date and time format. See "Output formatters" +section in perldoc F<lib/RT/Date.pm> for more options. This option can +be overridden by users in their preferences. +Some examples: + +C<Set($DateTimeFormat, 'LocalizedDateTime');> +C<Set($DateTimeFormat, { Format => 'ISO', Seconds => 0 });> +C<Set($DateTimeFormat, 'RFC2822');> +C<Set($DateTimeFormat, { Format => 'RFC2822', Seconds => 0, DayOfWeek => 0 });> + +=cut + +Set($DateTimeFormat, 'DefaultFormat'); + +# Next two options are for Time::ParseDate + +=item C<$DateDayBeforeMonth> + +Set this to 1 if your local date convention looks like "dd/mm/yy" instead of +"mm/dd/yy". Used only for parsing, not for displaying dates. + +=cut + +Set($DateDayBeforeMonth , 1); + +=item C<$AmbiguousDayInPast>, C<$AmbiguousDayInFuture> + +Should an unspecified day or year in a date refer to a future or a +past value? For example, should a date of "Tuesday" default to mean +the date for next Tuesday or last Tuesday? Should the date "March 1" +default to the date for next March or last March? + +Set $<AmbiguousDayInPast> for the last date, or $<$AmbiguousDayInFuture> for the +next date. + +The default is usually good. + +=cut + +Set($AmbiguousDayInPast, 0); +Set($AmbiguousDayInFuture, 0); + +=back + +=head1 Approval Configuration + +Configration for the approvl system + +=over 4 + +=item C<$ApprovalRejectionNotes> + +Should rejection notes be sent to the requestors? The default is true. + +=cut + +Set($ApprovalRejectionNotes, 1); + + +=back + +=head1 Miscellaneous Configuration + +=over 4 + +=item C<@ActiveStatus>, C<@InactiveStatus> + +You can define new statuses and even reorder existing statuses here. +WARNING. DO NOT DELETE ANY OF THE DEFAULT STATUSES. If you do, RT +will break horribly. The statuses you add must be no longer than +10 characters. + +=cut + +Set(@ActiveStatus, qw(new open stalled)); +Set(@InactiveStatus, qw(resolved rejected deleted)); + +=item C<$LinkTransactionsRun1Scrip> + +RT-3.4 backward compatibility setting. Add/Delete Link used to record one +transaction and run one scrip. Set this value to 1 if you want +only one of the link transactions to have scrips run. + +=cut + +Set($LinkTransactionsRun1Scrip, 0); + +=item C<$StrictLinkACL> + +When this feature is enabled a user needs I<ModifyTicket> rights on both +tickets to link them together, otherwise he can have rights on either of +them. + +=cut + +Set($StrictLinkACL, 1); + +=item C<$PreviewScripMessages> + +Set C<$PreviewScripMessages> to 1 if the scrips preview on the ticket +reply page should include the content of the messages to be sent. + +=cut + +Set($PreviewScripMessages, 0); + +=item C<$UseTransactionBatch> + +Set C<$UseTransactionBatch> to 1 to execute transactions in batches, +such that a resolve and comment (for example) would happen +simultaneously, instead of as two transactions, unaware of each +others' existence. + +=cut + +Set($UseTransactionBatch, 1); + +=item C<@CustomFieldValuesSources> + +Set C<@CustomFieldValuesSources> to a list of class names which extend +L<RT::CustomFieldValues::External>. This can be used to pull lists of +custom field values from external sources at runtime. + +=cut + +Set(@CustomFieldValuesSources, ()); + +=item C<$CanonicalizeRedirectURLs> + +Set C<$CanonicalizeRedirectURLs> to 1 to use $C<WebURL> when redirecting rather +than the one we get from C<%ENV>. + +If you use RT behind a reverse proxy, you almost certainly want to +enable this option. + +=cut + +Set($CanonicalizeRedirectURLs, 0); +=item C<$EnableReminders> + +Hide links/portlets related to Reminders by setting this to 0 + +=cut + +Set($EnableReminders,1); + + +=item C<@Plugins> + +Set C<@Plugins> to a list of external RT plugins that should be enabled (those +plugins have to be previously downloaded and installed). +Example: + +C<Set(@Plugins, (qw(Extension::QuickDelete RT::FM)));> + +=cut + +Set(@Plugins, qw( RTx::Calendar )); #RTx::Checklist )); + +=back + +=head1 Development Configuration + +=over 4 + +=item C<$DevelMode> + +RT comes with a "Development mode" setting. +This setting, as a convenience for developers, turns on +all sorts of development options that you most likely don't want in +production: + +* Turns off Mason's 'static_source' directive. By default, you can't + edit RT's web ui components on the fly and have RT magically pick up + your changes. (It's a big performance hit) + + * More to come + +=cut + +Set($DevelMode, '0'); + + +=back + +=head1 Deprecated Options + +=over 4 + +=item C<$AlwaysUseBase64> + +Encode blobs as base64 in DB (?) + +=item C<$TicketBaseURI> + +Base URI to tickets in this system; used when loading (?) + +=item C<$UseCodeTickets> + +This option is exists for backwards compatibility. Don't use it. + +=back + +=cut + +1; diff --git a/rt/etc/RT_Config.pm.in b/rt/etc/RT_Config.pm.in new file mode 100644 index 000000000..c73a1e52f --- /dev/null +++ b/rt/etc/RT_Config.pm.in @@ -0,0 +1,1831 @@ + +package RT; + +=head1 NAME + +RT::Config + +=for testing + +use RT::Config; + +=cut + +=head1 WARNING + +NEVER EDIT RT_Config.pm. + +Instead, copy any sections you want to change to F<RT_SiteConfig.pm> and edit them there. + +=cut + +=head1 Base Configuration + +=over 4 + +=item C<$rtname> + +C<$rtname> is the string that RT will look for in mail messages to +figure out what ticket a new piece of mail belongs to. + +Your domain name is recommended, so as not to pollute the namespace. +once you start using a given tag, you should probably never change it. +(otherwise, mail for existing tickets won't get put in the right place) + +=cut + +Set($rtname , "example.com"); + + +=item C<$EmailSubjectTagRegex> + +This regexp controls what subject tags RT recognizes as its own. +If you're not dealing with historical C<$rtname> values, you'll likely +never have to enable this feature. + +Be VERY CAREFUL with it. Note that it overrides C<$rtname> for subject +token matching and that you should use only "non-capturing" parenthesis +grouping. For example: + +C<Set($EmailSubjectTagRegex, qr/(?:example.com|example.org)/i );> + +and NOT + +C<Set($EmailSubjectTagRegex, qr/(example.com|example.org)/i );> + +This setting would make RT behave exactly as it does without the +setting enabled. + +=cut + +#Set($EmailSubjectTagRegex, qr/\Q$rtname\E/i ); + + + +=item C<$Organization> + +You should set this to your organization's DNS domain. For example, +I<fsck.com> or I<asylum.arkham.ma.us>. It's used by the linking interface to +guarantee that ticket URIs are unique and easy to construct. + +=cut + +Set($Organization , "example.com"); + +=item C<$MinimumPasswordLength> + +C<$MinimumPasswordLength> defines the minimum length for user +passwords. Setting it to 0 disables this check. + +=cut + +Set($MinimumPasswordLength , "5"); + +=item C<$Timezone> + +C<$Timezone> is used to convert times entered by users into GMT and back again +It should be set to a timezone recognized by your local unix box. + +=cut + +Set($Timezone , 'US/Eastern'); + +=back + +=head1 Database Configuration + +=over 4 + +=item C<$DatabaseType> + +Database driver being used; case matters. + +Valid types are "mysql", "Oracle" and "Pg" + +=cut + +Set($DatabaseType , '@DB_TYPE@'); + +=item C<$DatabaseHost>, C<$DatabaseRTHost> + +The domain name of your database server. + +If you're running mysql and it's on localhost, +leave it blank for enhanced performance + +=cut + +Set($DatabaseHost , '@DB_HOST@'); +Set($DatabaseRTHost , '@DB_RT_HOST@'); + +=item C<$DatabasePort> + +The port that your database server is running on. Ignored unless it's +a positive integer. It's usually safe to leave this blank + +=cut + +Set($DatabasePort , '@DB_PORT@'); + +=item C<$DatabaseUser> + +The name of the database user (inside the database) + +=cut + +Set($DatabaseUser , '@DB_RT_USER@'); + +=item C<$DatabasePassword> + +Password the C<$DatabaseUser> should use to access the database + +=cut + +Set($DatabasePassword , '@DB_RT_PASS@'); + +=item C<$DatabaseName> + +The name of the RT's database on your database server. For Oracle +it's SID, DB objects are created in L<$DatabaseUser>'s schema. + +=cut + +Set($DatabaseName , '@DB_DATABASE@'); + +=item C<$DatabaseRequireSSL> + +If you're using Postgres and have compiled in SSL support, +set C<$DatabaseRequireSSL> to 1 to turn on SSL communication + +=cut + +Set($DatabaseRequireSSL , undef); + +=item C<$UseSQLForACLChecks> + +In RT for ages ACL are checked after search what in some situtations +result in empty search pages and wrong count of tickets. + +Set C<$UseSQLForACLChecks> to 1 to use SQL and get rid of these problems. + +However, this option is beta. In some cases it result in performance +improvements, but some setups can not handle it. + +=cut + +Set($UseSQLForACLChecks, undef); + +=item C<$TicketsItemMapSize> + +In RT at display page of a ticket and there is the current search, +then links for first, next, previous and last ticket are shown in +the menu. + +To build full map RT has to fetch full result set out of DB what can +eat lots of resourses. Using this option it's possible to limit number +of tickets fetched. + +Set C<$TicketsItemMapSize> to number of tickets you want RT to look +at to build the map. If full result set is bigger than that number +then there would be no 'last' link in the menu. + +Set this to zero to return back to old behaviour. + +=cut + +Set($TicketsItemMapSize, 1000); + +=back + +=head1 Incoming Mail Gateway Configuration + +=over 4 + +=item C<$OwnerEmail> + +C<$OwnerEmail> is the address of a human who manages RT. RT will send +errors generated by the mail gateway to this address. This address +should _not_ be an address that's managed by your RT instance. + +=cut + +Set($OwnerEmail , 'root'); + +=item C<$LoopsToRTOwner> + +If C<$LoopsToRTOwner> is defined, RT will send mail that it believes +might be a loop to C<$OwnerEmail> + +=cut + +Set($LoopsToRTOwner , 1); + +=item C<$StoreLoops> + +If C<$StoreLoops> is defined, RT will record messages that it believes +to be part of mail loops. + +As it does this, it will try to be careful not to send mail to the +sender of these messages + +=cut + +Set($StoreLoops , undef); + +=item C<$MaxAttachmentSize> + +C<$MaxAttachmentSize> sets the maximum size (in bytes) of attachments stored +in the database. + +For mysql and oracle, we set this size at 10 megabytes. +If you're running a postgres version earlier than 7.1, you will need +to drop this to 8192. (8k) + +=cut + + +Set($MaxAttachmentSize , 10000000); + +=item C<$TruncateLongAttachments> + +C<$TruncateLongAttachments>: if this is set to a non-undef value, +RT will truncate attachments longer than C<$MaxAttachmentSize>. + +=cut + +Set($TruncateLongAttachments , undef); + +=item C<$DropLongAttachments> + +C<$DropLongAttachments>: if this is set to a non-undef value, +RT will silently drop attachments longer than C<MaxAttachmentSize>. + +=cut + +Set($DropLongAttachments , undef); + +=item C<$ParseNewMessageForTicketCcs> + +If C<$ParseNewMessageForTicketCcs> is true, RT will attempt to divine +Ticket 'Cc' watchers from the To and Cc lines of incoming messages +Be forewarned that if you have _any_ addresses which forward mail to +RT automatically and you enable this option without modifying +C<$RTAddressRegexp> below, you will get yourself into a heap of trouble. + +=cut + +Set($ParseNewMessageForTicketCcs , undef); + +=item C<$RTAddressRegexp> + +C<$RTAddressRegexp> is used to make sure RT doesn't add itself as a ticket CC if +the setting above is enabled. It is important that you set this to a +regular expression that matches all addresses used by your RT. This lets RT +avoid sending mail to itself. It will also hide RT addresses from the list of +"One-time Cc" and Bcc lists on ticket reply. + +=cut + +Set($RTAddressRegexp , undef); + +=item C<$CanonicalizeEmailAddressMatch>, C<$CanonicalizeEmailAddressReplace> + +RT provides functionality which allows the system to rewrite +incoming email addresses. In its simplest form, +you can substitute the value in $<CanonicalizeEmailAddressReplace> +for the value in $<CanonicalizeEmailAddressMatch> +(These values are passed to the $<CanonicalizeEmailAddress> subroutine in + F<RT/User.pm>) + +By default, that routine performs a C<s/$Match/$Replace/gi> on any address +passed to it. + +=cut + +#Set($CanonicalizeEmailAddressMatch , '@subdomain\.example\.com$'); +#Set($CanonicalizeEmailAddressReplace , '@example.com'); + +=item C<$CanonicalizeEmailAddressMatch> + +Set this to true and the create new user page will use the values that you +enter in the form but use the function CanonicalizeUserInfo in +F<RT/User_Local.pm> + +=cut + +Set($CanonicalizeOnCreate, 0); + +=item C<$SenderMustExistInExternalDatabase> + +If C<$SenderMustExistInExternalDatabase> is true, RT will refuse to +create non-privileged accounts for unknown users if you are using +the C<$LookupSenderInExternalDatabase> option. +Instead, an error message will be mailed and RT will forward the +message to C<$RTOwner>. + +If you are not using C<$LookupSenderInExternalDatabase>, this option +has no effect. + +If you define an AutoRejectRequest template, RT will use this +template for the rejection message. + +=cut + +Set($SenderMustExistInExternalDatabase , undef); + +=item C<$ValidateUserEmailAddresses> + +If C<$ValidateUserEmailAddresses> is true, RT will refuse to create users with +an invalid email address (as specified in RFC 2822) or with an email address +made of multiple email adresses. + +=cut + +Set($ValidateUserEmailAddresses, undef); + +=item C<@MailPlugins> + +C<@MailPlugins> is a list of auth plugins for L<RT::Interface::Email> +to use; see L<rt-mailgate> + +=cut + +=item C<$UnsafeEmailCommands> + +C<$UnsafeEmailCommands>, if set to true, enables 'take' and 'resolve' +as possible actions via the mail gateway. As its name implies, this +is very unsafe, as it allows email with a forged sender to possibly +resolve arbitrary tickets! + +=cut + +=item C<$ExtractSubjectTagMatch>, C<$ExtractSubjectTagNoMatch> + +The default "extract remote tracking tags" scrip settings; these +detect when your RT is talking to another RT, and adjusts the +subject accordingly. + +=cut + +Set($ExtractSubjectTagMatch, qr/\[.+? #\d+\]/); +Set($ExtractSubjectTagNoMatch, ( ${RT::EmailSubjectTagRegex} + ? qr/\[(?:${RT::EmailSubjectTagRegex}) #\d+\]/ + : qr/\[\Q$RT::rtname\E #\d+\]/)); + +=back + +=head1 Outgoing Mail Configuration + +=over 4 + +=item C<$MailCommand> + +C<$MailCommand> defines which method RT will use to try to send mail. +We know that 'sendmailpipe' works fairly well. If 'sendmailpipe' +doesn't work well for you, try 'sendmail'. Other options are 'smtp' +or 'qmail'. + +Note that you should remove the '-t' from C<$SendmailArguments> +if you use 'sendmail' rather than 'sendmailpipe' + +=cut + +Set($MailCommand , 'sendmailpipe'); + +=item C<$SetOutgoingMailFrom> + +C<$SetOutgoingMailFrom> tells RT to set the sender envelope with the correspond +mail address of the ticket's queue. + +Warning: If you use this setting, bounced mails will appear to be incoming +mail to the system, thus creating new tickets. + +=cut + +Set($SetOutgoingMailFrom, 0); + +=item C<$OverrideOutgoingMailFrom> + +C<$OverrideOutgoingMailFrom> is used for overwriting the Correspond +address of the queue. The option is a hash reference of queue name to +email address. + +If there is no ticket involved, then the value of the C<Default> key will be +used. + +=cut + +Set($OverrideOutgoingMailFrom, { +# 'Default' => 'admin@rt.example.com', +# 'General' => 'general@rt.example.com', +}); + +=back + +=item C<$DefaultMailPrecedence> + +C<$DefaultMailPrecedence> is used to control the default +Precedence level of outgoing mail where none is specified. +By default it is C<bulk>, but if you only send mail to +your staff, you may wish to change it. + +Note that you can set the precedence of individual templates +by including an explicit Precedence header. + +If you set this value to C<undef> then we do not set a default +Precedence header to outgoing mail. However, if there already is a +Precedence header it will be preserved. + +=cut + +Set($DefaultMailPrecedence, 'bulk'); + +=back + +=item C<$DefaultErrorMailPrecedence> + +C<$DefaultErrorMailPrecedence> is used to control the default +Precedence level of outgoing mail that indicates some kind of +error condition. By default it is C<bulk>, but if you only send +mail to your staff, you may wish to change it. + +If you set this value to C<undef> then we do not add a Precedence +header to error mail. + +=cut + +Set($DefaultErrorMailPrecedence, 'bulk'); + +=back + +=item C<$UseOriginatorHeader> + +C<$UseOriginatorHeader> is used to control the insertion of an +RT-Originator Header in every outgoing mail, containing the +mail address of the transaction creator. + +=cut + +Set($UseOriginatorHeader, 1); + +=back + +=head1 Sendmail Configuration + +These options only take effect if C<$MailCommand> is 'sendmail' or +'sendmailpipe' + +=over 4 + +=item C<$SendmailArguments> + +C<$SendmailArguments> defines what flags to pass to C<$SendmailPath> +If you picked 'sendmailpipe', you MUST add a -t flag to C<$SendmailArguments> +These options are good for most sendmail wrappers and workalikes + +These arguments are good for sendmail brand sendmail 8 and newer +C<Set($SendmailArguments,"-oi -t -ODeliveryMode=b -OErrorMode=m");> + +=cut + +Set($SendmailArguments , "-oi -t"); + + +=item C<$SendmailBounceArguments> + +C<$SendmailBounceArguments> defines what flags to pass to C<$Sendmail> +assuming RT needs to send an error (ie. bounce). + +=cut + +Set($SendmailBounceArguments , '-f "<>"'); + +=item C<$SendmailPath> + +If you selected 'sendmailpipe' above, you MUST specify the path to +your sendmail binary in C<$SendmailPath>. + +=cut + +Set($SendmailPath , "/usr/sbin/sendmail"); + + +=back + +=head1 SMTP Configuration + +These options only take effect if C<$MailCommand> is 'smtp' + +=over 4 + +=item C<$SMTPServer> + +C<$SMTPServer> should be set to the hostname of the SMTP server to use + +=cut + +Set($SMTPServer, undef); + +=item C<$SMTPFrom> + +C<$SMTPFrom> should be set to the 'From' address to use, if not the +email's 'From' + +=cut + +Set($SMTPFrom, undef); + +=item C<$SMTPDebug> + +C<$SMTPDebug> should be set to true to debug SMTP mail sending + +=cut + +Set($SMTPDebug, 0); + +=back + +=head1 Other Mailer Configuration + +=over 4 + +=item C<@MailParams> + +C<@MailParams> defines a list of options passed to $MailCommand if it +is not 'sendmailpipe', 'sendmail', or 'smtp' + +=cut + +Set(@MailParams, ()); + +=item C<$CorrespondAddress>, C<$CommentAddress> + +RT is designed such that any mail which already has a ticket-id associated +with it will get to the right place automatically. + +C<$CorrespondAddress> and C<$CommentAddress> are the default addresses +that will be listed in From: and Reply-To: headers of correspondence +and comment mail tracked by RT, unless overridden by a queue-specific +address. + +=cut + +Set($CorrespondAddress , ''); + +Set($CommentAddress , ''); + +=item C<$DashboardAddress> + +The email address from which RT will send dashboards. If none is set, then +C<$OwnerEmail> will be used. + +=cut + +Set($DashboardAddress, ''); + +=item C<$UseFriendlyFromLine> + +By default, RT sets the outgoing mail's "From:" header to +"SenderName via RT". Setting C<$UseFriendlyFromLine> to 0 disables it. + +=cut + +Set($UseFriendlyFromLine, 1); + +=item C<$FriendlyFromLineFormat> + +C<sprintf()> format of the friendly 'From:' header; its arguments +are SenderName and SenderEmailAddress. + +=cut + +Set($FriendlyFromLineFormat, "\"%s via RT\" <%s>"); + +=item C<$UseFriendlyToLine> + +RT can optionally set a "Friendly" 'To:' header when sending messages to +Ccs or AdminCcs (rather than having a blank 'To:' header. + +This feature DOES NOT WORK WITH SENDMAIL[tm] BRAND SENDMAIL +If you are using sendmail, rather than postfix, qmail, exim or some other MTA, +you _must_ disable this option. + +=cut + +Set($UseFriendlyToLine, 0); + +=item C<$FriendlyToLineFormat> + +C<sprintf()> format of the friendly 'From:' header; its arguments +are WatcherType and TicketId. + +=cut + +Set($FriendlyToLineFormat, "\"%s of ". RT->Config->Get('rtname') ." Ticket #%s\":;"); + +=item C<$NotifyActor> + +By default, RT doesn't notify the person who performs an update, as they +already know what they've done. If you'd like to change this behaviour, +Set C<$NotifyActor> to 1 + +=cut + +Set($NotifyActor, 0); + +=item C<$RecordOutgoingEmail> + +By default, RT records each message it sends out to its own internal database. +To change this behavior, set C<$RecordOutgoingEmail> to 0 + +=cut + +Set($RecordOutgoingEmail, 1); + +=item C<$VERPPrefix>, C<$VERPPrefix> + +VERP support (http://cr.yp.to/proto/verp.txt) + +uncomment the following two directives to generate envelope senders +of the form C<${VERPPrefix}${originaladdress}@${VERPDomain}> +(i.e. rt-jesse=fsck.com@rt.example.com ). + +This currently only works with sendmail and sendmailppie. + +=cut + +# Set($VERPPrefix, 'rt-'); +# Set($VERPDomain, $RT::Organization); + + +=item C<$ForwardFromUser> + +By default, RT forwards a message using queue's address and adds RT's tag into +subject of the outgoing message, so recipients' replies go into RT as correspondents. + +To change this behavior, set C<$ForwardFromUser> to true value and RT will use +address of the current user and leave subject without RT's tag. + +=cut + +Set($ForwardFromUser, 0); + +=item C<$ShowBccHeader> + +By default RT hides from the web UI information about blind copies user sent on +reply or comment. + +To change this set the following option to true value. + +=cut + +Set($ShowBccHeader, 0); + +=item C<$DashboardSubject> + +Lets you set the subject of dashboards. Arguments are the frequency (Daily, +Weekly, Monthly) of the dashboard and the dashboard's name. [_1] for the name +of the dashboard. + +=cut + +Set($DashboardSubject, '%s Dashboard: %s'); + +=back + +=head1 GnuPG Configuration + +A full description of the (somewhat extensive) GnuPG integration can be found +by running the command `perldoc L<RT::Crypt::GnuPG>` (or `perldoc + lib/RT/Crypt/GnuPG.pm` from your RT install directory). + +=over 4 + +=item C<%GnuPG> + +Set C<OutgoingMessagesFormat> to 'inline' to use inline encryption and +signatures instead of 'RFC' (GPG/MIME: RFC3156 and RFC1847) format. + +If you want to allow people to encrypt attachments inside the DB then +set C<AllowEncryptDataInDB> to true + +Set C<RejectOnMissingPrivateKey> to false if you don't want to reject +emails encrypted for key RT doesn't have and can not decrypt. + +Set C<RejectOnBadData> to false if you don't want to reject letters +with incorrect GnuPG data. + +=cut + +Set( %GnuPG, + Enable => @RT_GPG@, + OutgoingMessagesFormat => 'RFC', # Inline + AllowEncryptDataInDB => 0, + + RejectOnMissingPrivateKey => 1, + RejectOnBadData => 1, +); + +=item C<%GnuPGOptions> + +Options of GnuPG program. + +If you override this in your RT_SiteConfig, you should be sure +to include a homedir setting. + +NOTE that options with '-' character MUST be quoted. + +=cut + +Set(%GnuPGOptions, + homedir => '@RT_VAR_PATH@/data/gpg', + +# URL of a keyserver +# keyserver => 'hkp://subkeys.pgp.net', + +# enables the automatic retrieving of keys when encrypting +# 'auto-key-locate' => 'keyserver', + +# enables the automatic retrieving of keys when verifying signatures +# 'auto-key-retrieve' => undef, +); + + +=back + +=head1 Logging Configuration + +The default is to log anything except debugging +information to syslog. Check the L<Log::Dispatch> POD for +information about how to get things by syslog, mail or anything +else, get debugging info in the log, etc. + +It might generally make sense to send error and higher by email to +some administrator. If you do this, be careful that this email +isn't sent to this RT instance. Mail loops will generate a critical +log message. + +=over 4 + +=item C<$LogToSyslog>, C<$LogToScreen> + +The minimum level error that will be logged to the specific device. +From lowest to highest priority, the levels are: + debug info notice warning error critical alert emergency + +=cut + +Set($LogToSyslog , 'info'); +Set($LogToScreen , 'info'); + +=item C<$LogToFile>, C<$LogDir>, C<$LogToFileNamed> + +Logging to a standalone file is also possible, but note that the +file should needs to both exist and be writable by all direct users +of the RT API. This generally include the web server, whoever +rt-crontool runs as. Note that as rt-mailgate and the RT CLI go +through the webserver, so their users do not need to have write +permissions to this file. If you expect to have multiple users of +the direct API, Best Practical recommends using syslog instead of +direct file logging. + +=cut + +Set($LogToFile , undef); +Set($LogDir, '@RT_LOG_PATH@'); +Set($LogToFileNamed , "rt.log"); #log to rt.log + +=item C<$LogStackTraces> + +If set to a log level then logging will include stack traces for +messages with level equal to or greater than specified. + +NOTICE: Stack traces include parameters supplied to functions or +methods. It is possible for stack trace logging to reveal sensitive +information such as passwords or ticket content in your logs. + +=cut + +Set($LogStackTraces, ''); + +=item C<@LogToSyslogConf> + +On Solaris or UnixWare, set to ( socket => 'inet' ). Options here +override any other options RT passes to L<Log::Dispatch::Syslog>. +Other interesting flags include facility and logopt. (See the +L<Log::Dispatch::Syslog> documentation for more information.) (Maybe +ident too, if you have multiple RT installations.) + +=cut + +Set(@LogToSyslogConf, ()); + +=item C<$StatementLog>, + +RT has rudimentary SQL statement logging support if you have +DBIx-SearchBuilder 1.31_1 or higher; simply set C<$StatementLog> to be +the level that you wish SQL statements to be logged at. + +=cut + +Set($StatementLog, undef); + +=back + +=head1 Web Interface Configuration + +=over 4 + +=item C<$WebDefaultStylesheet> + +This determines the default stylesheet the RT web interface will use. +RT ships with several themes by default: + + web2 The totally new, default layout for RT 3.8 + 3.5-default RT 3.5 and 3.6 original layout + 3.4-compat A 3.4 compatibility stylesheet to make RT look + (mostly) like 3.4 + +This bundled distibution of RT also includes (enabled by default): + freeside2.1 Integration with Freeside + +This value actually specifies a directory in F<share/html/NoAuth/css/> +from which RT will try to load the file main.css (which should +@import any other files the stylesheet needs). This allows you to +easily and cleanly create your own stylesheets to apply to RT. This +option can be overridden by users in their preferences. + +=cut + +Set($WebDefaultStylesheet, 'freeside2.1'); + +=item C<$UsernameFormat> + +This determines how user info is displayed. 'concise' will show one of +either NickName, RealName, Name or EmailAddress, depending on what exists +and whether the user is privileged or not. 'verbose' will show RealName and +EmailAddress. + +=cut + +Set($UsernameFormat, 'verbose'); + +=item C<$WebDomain> + +Domain name of the RT server, eg 'www.example.com'. It should not contain +anything else, but server name. + +=cut + +Set( $WebDomain, 'localhost' ); + +=item C<$WebPort> + +If we're running as a superuser, run on port 80 +Otherwise, pick a high port for this user. + +443 is default port for https protocol. + +=cut + +Set($WebPort, 80);# + ($< * 7274) % 32766 + ($< && 1024)); + +=item C<$WebPath> + +If you're putting the web ui somewhere other than at the root of +your server, you should set C<$WebPath> to the path you'll be +serving RT at. + +C<$WebPath> requires a leading / but no trailing /, or it can be blank. + +In most cases, you should leave C<$WebPath> set to '' (an empty value). + +=cut + +Set($WebPath, ""); + +=item C<$WebBaseURL>, C<$WebURL> + +Usually you don't want to set these options. The only obviouse reason is +RT accessible via https protocol on non standard port, eg +'https://rt.example.com:9999'. In all other cases these options are computed +using C<$WebDomain>, C<$WebPort> and C<$WebPath>. + +C<$WebBaseURL> is the scheme, server and port (eg 'http://rt.example.com') +for constructing urls to the web UI. C<$WebBaseURL> doesn't need a trailing /. + +C<$WebURL> is the C<$WebBaseURL>, C<$WebPath> and trailing /, for example: +'http://www.example.com/rt/'. + +=cut + +my $port = RT->Config->Get('WebPort'); +Set($WebBaseURL, + ($port == 443? 'https': 'http') .'://' + . RT->Config->Get('WebDomain') + . ($port != 80 && $port != 443? ":$port" : '') +); + +Set($WebURL, RT->Config->Get('WebBaseURL') . RT->Config->Get('WebPath') . "/"); + +=item C<$WebImagesURL> + +C<$WebImagesURL> points to the base URL where RT can find its images. +Define the directory name to be used for images in rt web +documents. + +=cut + +Set($WebImagesURL, RT->Config->Get('WebPath') . "/NoAuth/images/"); + +=item C<$LogoURL> + +C<$LogoURL> points to the URL of the RT logo displayed in the web UI + +=cut + +Set($LogoURL, RT->Config->Get('WebImagesURL') . "bplogo.gif"); + +=item C<$LogoLinkURL> + +C<$LogoLinkURL> is the URL that the RT logo hyperlinks to. + +=cut + +Set($LogoLinkURL, "http://bestpractical.com"); + +=item C<$LogoAltText> + +C<$LogoAltText> is a string of text for the alt-text of the logo. It +will be passed through C<loc> for localization. + +=cut + +Set($LogoAltText, "Best Practical Solutions, LLC corporate logo"); + +=item C<$LogoImageHeight> + +C<$LogoImageHeight> is the value of the C<height> attribute of the logo +C<img> tag. + +=cut + +Set($LogoImageHeight, 33); + +=item C<$LogoImageWidth> + +C<$LogoImageWidth> is the value of the C<width> attribute of the logo +C<img> tag. + +=cut + +Set($LogoImageWidth, 177); + +=item C<$WebNoAuthRegex> + +What portion of RT's URL space should not require authentication. + +This is mostly for extension and doesn't mean RT will work without +login if you change it. + +=cut + +Set($WebNoAuthRegex, qr{^ /rt (?:/+NoAuth/ | /+REST/\d+\.\d+/NoAuth/) }x ); + +=item C<$SelfServiceRegex> + +What portion of RT's URLspace should be accessible to Unprivileged users +This does not override the redirect from F</Ticket/Display.html> to +F</SelfService/Display.html> when Unprivileged users attempt to access +ticked displays + +=cut + +Set($SelfServiceRegex, qr!^(?:/+SelfService/)!x ); + +=item C<$MessageBoxWidth>, C<$MessageBoxHeight> + +For message boxes, set the entry box width, height and what type of +wrapping to use. These options can be overridden by users in their +preferences. + +Default width: 72, height: 15 + +These settings only apply to the non-RichText message box. +See below for Rich Text settings. + +=cut + +Set($MessageBoxWidth, 72); +Set($MessageBoxHeight, 15); + +=item C<$MessageBoxWrap> + +Default wrapping: "HARD" (choices "SOFT", "HARD") + +Wrapping is disabled when using MessageBoxRichText because +of a bad interaction between IE and wrapping with the Rich +Text Editor. + +=cut + +Set($MessageBoxWrap, "HARD"); + +=item C<$MessageBoxRichText> + +Should "rich text" editing be enabled? This option lets your users send html email messages from the web interface. + +=cut + +Set($MessageBoxRichText, 1); + +=item C<$MessageBoxRichTextHeight> + +Height of RichText javascript enabled editing boxes (in pixels) + +=cut + +Set($MessageBoxRichTextHeight, 200); + +=item C<$MessageBoxIncludeSignature> + +Should your user's signatures (from their Preferences page) be included in Comments and Replies + +=cut + +Set($MessageBoxIncludeSignature, 1); + +=item C<$MessageBoxIncludeSignatureOnComment> + +Should your user's signatures (from their Preferences page) be included in Comments. Setting this to false overrides C<$MessageBoxIncludeSignature>. + +=cut + +Set($MessageBoxIncludeSignatureOnComment, 1); + +=item C<$WikiImplicitLinks> + +Support implicit links in WikiText custom fields? A true value +causes InterCapped or ALLCAPS words in WikiText fields to +automatically become links to searches for those words. If used on +RTFM articles, it links to the RTFM article with that name. + +=cut + +Set($WikiImplicitLinks, 0); + +=item C<$TrustHTMLAttachments> + +if C<TrustHTMLAttachments> is not defined, we will display them +as text. This prevents malicious HTML and javascript from being +sent in a request (although there is probably more to it than that) + +=cut + +Set($TrustHTMLAttachments, undef); + +=item C<$AlwaysDownloadAttachments> + +Always download attachments, regardless of content type. If set, +this overrides C<TrustHTMLAttachments>. + +=cut + +Set($AlwaysDownloadAttachments, undef); + +=item C<$AttachmentUnits> + +Controls the units (kilobytes or bytes) that attachment sizes use +for display. The default is to display kilobytes if the attachment +is larger than 1024 bytes, bytes otherwise. If you set +C<$AttachmentUnits> to C<'k'> then attachment sizes will always be +displayed in kilobytes. If set to C<'b'>, then sizes will be bytes. + +=cut + +Set($AttachmentUnits, undef); + +=item C<$RedistributeAutoGeneratedMessages> + +Should RT redistribute correspondence that it identifies as +machine generated? A true value will do so; setting this to '0' +will cause no such messages to be redistributed. +You can also use 'privileged' (the default), which will redistribute +only to privileged users. This helps to protect against malformed +bounces and loops caused by autocreated requestors with bogus addresses. + +=cut + +Set($RedistributeAutoGeneratedMessages, 'privileged'); + +=item C<$PreferRichText> + +If C<$PreferRichText> is set to a true value, RT will show HTML/Rich text +messages in preference to their plaintext alternatives. RT "scrubs" the +html to show only a minimal subset of HTML to avoid possible contamination +by cross-site-scripting attacks. + +=cut + +Set($PreferRichText, undef); + +=item C<$WebExternalAuth> + +If C<$WebExternalAuth> is defined, RT will defer to the environment's +REMOTE_USER variable. + +=cut + +Set($WebExternalAuth, undef); + +=item C<$WebExternalAuthContinuous> + +If C<$WebExternalAuthContinuous> is defined, RT will check for the +REMOTE_USER on each access. If you would prefer this to only happen +once (at initial login) set this to a false value. The default setting +will help ensure that if your external auth system deauthenticates a +user, RT notices as soon as possible. + +=cut + +Set($WebExternalAuthContinuous, 1); + +=item C<$WebFallbackToInternalAuth> + +If C<$WebFallbackToInternalAuth> is defined, the user is allowed a chance +of fallback to the login screen, even if REMOTE_USER failed. + +=cut + +Set($WebFallbackToInternalAuth , undef); + +=item C<$WebExternalGecos> + +C<$WebExternalGecos> means to match 'gecos' field as the user identity); +useful with mod_auth_pwcheck and IIS Integrated Windows logon. + +=cut + +Set($WebExternalGecos , undef); + +=item C<$WebExternalAuto> + +C<$WebExternalAuto> will create users under the same name as REMOTE_USER +upon login, if it's missing in the Users table. + +=cut + +Set($WebExternalAuto , undef); + +=item C<$AutoCreate> + +If C<$WebExternalAuto> is true, C<$AutoCreate> will be passed to User's +Create method. Use it to set defaults, such as creating +Unprivileged users with C<{ Privileged => 0 }> +( Must be a hashref of arguments ) + +=cut + +Set($AutoCreate, undef); + +=item C<$WebSessionClass> + +C<$WebSessionClass> is the class you wish to use for managing Sessions. +It defaults to use your SQL database, but if you are using MySQL 3.x and +plans to use non-ascii Queue names, uncomment and add this line to +F<RT_SiteConfig.pm> will prevent session corruption. + +=cut + +# Set($WebSessionClass , 'Apache::Session::File'); + +=item C<$AutoLogoff> + +By default, RT's user sessions persist until a user closes his or her +browser. With the C<$AutoLogoff> option you can setup session lifetime in +minutes. A user will be logged out if he or she doesn't send any requests +to RT for the defined time. + +=cut + +Set($AutoLogoff, 0); + +=item C<$LogoutRefresh> + +The number of seconds to wait after logout before sending the user to the +login page. By default, 1 second, though you may want to increase this if +you display additional information on the logout page. + +=cut + +Set($LogoutRefresh, 1); + +=item C<$WebSecureCookies> + +By default, RT's session cookie isn't marked as "secure" Some web browsers +will treat secure cookies more carefully than non-secure ones, being careful +not to write them to disk, only send them over an SSL secured connection +and so on. To enable this behaviour, set C<$WebSecureCookies> to a true value. +NOTE: You probably don't want to turn this on _unless_ users are only connecting +via SSL encrypted HTTP connections. + +=cut + +Set($WebSecureCookies, 0); + +=item C<$WebFlushDbCacheEveryRequest> + +By default, RT clears its database cache after every page view. +This ensures that you've always got the most current information +when working in a multi-process (mod_perl or FastCGI) Environment +Setting C<$WebFlushDbCacheEveryRequest> to '0' will turn this off, +which will speed RT up a bit, at the expense of a tiny bit of data +accuracy. + +=cut + +Set($WebFlushDbCacheEveryRequest, '1'); + + +=item C<$MaxInlineBody> + +C<$MaxInlineBody> is the maximum attachment size that we want to see +inline when viewing a transaction. RT will inline any text if value +is undefined or 0. This option can be overridden by users in their +preferences. + +=cut + +Set($MaxInlineBody, 12000); + +=item C<$DefaultSummaryRows> + +C<$DefaultSummaryRows> is default number of rows displayed in for search +results on the frontpage. + +=cut + +Set($DefaultSummaryRows, 10); + +=item C<$HomePageRefreshInterval> + +C<$HomePageRefreshInterval> is default number of seconds to refresh the RT +home page. Choose from [0, 120, 300, 600, 1200, 3600, 7200]. + +=cut + +Set($HomePageRefreshInterval, 0); + +=item C<$SearchResultsRefreshInterval> + +C<$SearchResultsRefreshInterval> is default number of seconds to refresh +search results in RT. Choose from [0, 120, 300, 600, 1200, 3600, 7200]. + +=cut + +Set($SearchResultsRefreshInterval, 0); + +=item C<$OldestTransactionsFirst> + +By default, RT shows newest transactions at the bottom of the ticket +history page, if you want see them at the top set this to '0'. This +option can be overridden by users in their preferences. + +=cut + +Set($OldestTransactionsFirst, '1'); + +=item C<$ShowTransactionImages> + +By default, RT shows images attached to incoming (and outgoing) ticket updates +inline. Set this variable to 0 if you'd like to disable that behaviour + +=cut + +Set($ShowTransactionImages, 1); + +=item C<$PlainTextPre> + +Normally plaintext attachments are displayed as HTML with line +breaks preserved. This causes space- and tab-based formatting not +to be displayed correctly. By setting $PlainTextPre they'll be +displayed using <pre> instead so such formatting works, but they'll +use a monospaced font, no matter what the value of C<$PlainTextMono> is. + +=cut + +Set($PlainTextPre, 0); + + +=item C<$PlainTextMono> +To display plaintext attachments, +Set C<$PlainTextMono> to 1 to use monospaced font and preserve +formatting, but unlike PlainTextPre, the text will wrap to fit into the +UI. + +=cut + +Set($PlainTextMono, 0); + +=item C<$ShowUnreadMessageNotifications> + +By default, RT will prompt users when there are new, unread messages on +tickets they are viewing. + +Set C<$ShowUnreadMessageNotifications> to a false value to disable this feature. + +=cut + +Set($ShowUnreadMessageNotifications, 1); + + +=item C<$HomepageComponents> + +C<$HomepageComponents> is an arrayref of allowed components on a user's +customized homepage ("RT at a glance"). + +=cut + +Set($HomepageComponents, [qw(QuickCreate Quicksearch MyCalendar MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards)]); + +=item C<@MasonParameters> + +C<@MasonParameters> is the list of parameters for the constructor of +HTML::Mason's Apache or CGI Handler. This is normally only useful +for debugging, eg. profiling individual components with: + + use MasonX::Profiler; # available on CPAN + Set(@MasonParameters, (preamble => 'my $p = MasonX::Profiler->new($m, $r);')); + +=cut + +Set(@MasonParameters, ()); + +=item C<$DefaultSearchResultFormat> + +C<$DefaultSearchResultFormat> is the default format for RT search results + +=cut + +Set ($DefaultSearchResultFormat, qq{ + '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__id__</a></B>/TITLE:#', + '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', + Customer, + Status, + QueueName, + OwnerName, + Priority, + '__NEWLINE__', + '', + '<small>__Requestors__</small>', + '', + '<small>__CreatedRelative__</small>', + '<small>__ToldRelative__</small>', + '<small>__LastUpdatedRelative__</small>', + '<small>__TimeLeft__</small>'}); + +=item C<$DefaultSelfServiceSearchResultFormat> + +C<$DefaultSelfServiceSearchResultFormat> is the default format of searches displayed in the +SelfService interface. + +=cut + +Set($DefaultSelfServiceSearchResultFormat, qq{ + '<B><A HREF="__WebPath__/SelfService/Display.html?id=__id__">__id__</a></B>/TITLE:#', + '<B><A HREF="__WebPath__/SelfService/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', + Status, + Requestors, + OwnerName}); + +=item C<%AdminSearchResultFormat> + +In admin interface format strings similar to tickets search result +formats are used. Use C<%AdminSearchResultFormat> to define format +strings per RT class. + +=cut + +Set(%AdminSearchResultFormat, + Queues => + q{'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Queues/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__Description__,__Address__,__Priority__,__DefaultDueIn__,__Disabled__}, + + Groups => + q{'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Groups/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,'__Description__'}, + + Users => + q{'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/Users/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__RealName__, __EmailAddress__}, + + CustomFields => + q{'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/Admin/CustomFields/Modify.html?id=__id__">__Name__</a>/TITLE:Name'} + .q{,__AppliedTo__, __FriendlyType__, __FriendlyPattern__}, + + Scrips => + q{'<a href="__WebPath__/__WebRequestPathDir__/Scrip.html?id=__id__&Queue=__QueueId__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/__WebRequestPathDir__/Scrip.html?id=__id__&Queue=__QueueId__">__Description__</a>/TITLE:Description'} + .q{,__Stage__, __Condition__, __Action__, __Template__}, + + Templates => + q{'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__id__</a>/TITLE:#'} + .q{,'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__Name__</a>/TITLE:Name'} + .q{,'__Description__'}, +); + +=item C<$SuppressInlineTextFiles> + +If C<$SuppressInlineTextFiles> is set to a true value, then uploaded +text files (text-type attachments with file names) are prevented +from being displayed in-line when viewing a ticket's history. + +=cut + +Set($SuppressInlineTextFiles, undef); + +=item C<$DontSearchFileAttachments> + +If C<$DontSearchFileAttachments> is set to a true value, then uploaded +files (attachments with file names) are not searched during full-content +ticket searches. + +=cut + +Set($DontSearchFileAttachments, undef); + +=item C<%ChartFont> + +The L<GD> module (which RT uses for graphs) ships with a builtin font +that doesn't have full Unicode support. You can use a given TrueType font +for a specific language by setting %ChartFont to (language =E<gt> the +absolute path of a font) pairs. Your GD library must have support for +TrueType fonts to use this option. If there is no entry for a language +in the hash then font with 'others' key is used. + +RT comes with two TrueType fonts covering most available languages. + +=cut + +Set( + %ChartFont, + 'zh-cn' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'zh-tw' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'ja' => "$RT::BasePath/share/fonts/DroidSansFallback.ttf", + 'others' => "$RT::BasePath/share/fonts/DroidSans.ttf", +); + +=item C<$ChartsTimezonesInDB> + +Dates are stored using UTC timezone in the DB, so charts groupped +by dates and time are not representative. Set C<$ChartsTimezonesInDB> +to a true value to enable timezones conversions using DB's +capabilities. You may need to do some work on DB side to use this +feature, read more in F<docs/timezones_in_charts.pod>. + +=cut + +Set( $ChartsTimezonesInDB, 0 ); + +=item C<@Active_MakeClicky> + +MakeClicky detects various formats of data in headers and email +messages, and extends them with supporting links. By default, RT +provides two formats: + +* 'httpurl': detects http:// and https:// URLs and adds '[Open URL]' + link after the URL. + +* 'httpurl_overwrite': also detects URLs as 'httpurl' format, but + replace URL with link and *adds spaces* into text if it's longer + then 30 chars. This allow browser to wrap long URLs and avoid + horizontal scrolling. + +See F<share/html/Elements/MakeClicky> for documentation on how to add your own. + +=cut + +Set(@Active_MakeClicky, qw()); + +=item C<$DefaultQueue> + +Use this to select the default queue name that will be used for creating new +tickets. You may use either the queue's name or its ID. This only affects the +queue selection boxes on the web interface. + +=cut + +#Set($DefaultQueue, 'General'); + +=item C<$DefaultTimeUnitsToHours> + +Use this to set the default units for time entry to hours instead of minutes. + +=cut + +Set($DefaultTimeUnitsToHours, 0); + +=back + +=head1 L<Net::Server> (rt-server) Configuration + +=over 4 + +=item C<$StandaloneMinServers>, C<$StandaloneMaxServers> + +The absolute minimum and maximum number of servers that will be created to +handle requests. Having multiple servers means that serving a slow page will +affect other users less. + +=cut + +Set($StandaloneMinServers, 1); +Set($StandaloneMaxServers, 1); + +=item C<$StandaloneMinSpareServers>, C<$StandaloneMaxSpareServers> + +These next two options can be used to scale up and down the number of servers +to adjust to load. These two options will respect the C<$StandaloneMinServers +> and C<$StandaloneMaxServers options>. + +=cut + +Set($StandaloneMinSpareServers, 0); +Set($StandaloneMaxSpareServers, 0); + +=item C<$StandaloneMaxRequests> + +This sets the absolute maximum number of requests a single server will serve. +Setting this would be useful if, for example, memory usage slowly crawls up +every hit. + +=cut + +#Set($StandaloneMaxRequests, 50); + +=item C<%NetServerOptions> + +C<%NetServerOptions> is a hash of additional options to use for +L<Net::Server/DEFAULT ARGUMENTS>. For example, you could set +reverse_lookups to get the hostnames for all users with: + +C<Set(%NetServerOptions, (reverse_lookups => 1));> + +=cut + +Set(%NetServerOptions, ()); + +=back + + +=head1 UTF-8 Configuration + +=over 4 + +=item C<@LexiconLanguages> + +An array that contains languages supported by RT's internationalization +interface. Defaults to all *.po lexicons; setting it to C<qw(en ja)> will make +RT bilingual instead of multilingual, but will save some memory. + +=cut + +Set(@LexiconLanguages, qw(*)); + +=item C<@EmailInputEncodings> + +An array that contains default encodings used to guess which charset +an attachment uses if not specified. Must be recognized by +L<Encode::Guess>. + +=cut + +Set(@EmailInputEncodings, qw(utf-8 iso-8859-1 us-ascii)); + +=item C<$EmailOutputEncoding> + +The charset for localized email. Must be recognized by Encode. + +=cut + +Set($EmailOutputEncoding, 'utf-8'); + + +=back + +=head1 Date Handling Configuration + +=over 4 + +=item C<$DateTimeFormat> + +You can choose date and time format. See "Output formatters" +section in perldoc F<lib/RT/Date.pm> for more options. This option can +be overridden by users in their preferences. +Some examples: + +C<Set($DateTimeFormat, 'LocalizedDateTime');> +C<Set($DateTimeFormat, { Format => 'ISO', Seconds => 0 });> +C<Set($DateTimeFormat, 'RFC2822');> +C<Set($DateTimeFormat, { Format => 'RFC2822', Seconds => 0, DayOfWeek => 0 });> + +=cut + +Set($DateTimeFormat, 'DefaultFormat'); + +# Next two options are for Time::ParseDate + +=item C<$DateDayBeforeMonth> + +Set this to 1 if your local date convention looks like "dd/mm/yy" instead of +"mm/dd/yy". Used only for parsing, not for displaying dates. + +=cut + +Set($DateDayBeforeMonth , 1); + +=item C<$AmbiguousDayInPast>, C<$AmbiguousDayInFuture> + +Should an unspecified day or year in a date refer to a future or a +past value? For example, should a date of "Tuesday" default to mean +the date for next Tuesday or last Tuesday? Should the date "March 1" +default to the date for next March or last March? + +Set $<AmbiguousDayInPast> for the last date, or $<$AmbiguousDayInFuture> for the +next date. + +The default is usually good. + +=cut + +Set($AmbiguousDayInPast, 0); +Set($AmbiguousDayInFuture, 0); + +=back + +=head1 Approval Configuration + +Configration for the approvl system + +=over 4 + +=item C<$ApprovalRejectionNotes> + +Should rejection notes be sent to the requestors? The default is true. + +=cut + +Set($ApprovalRejectionNotes, 1); + + +=back + +=head1 Miscellaneous Configuration + +=over 4 + +=item C<@ActiveStatus>, C<@InactiveStatus> + +You can define new statuses and even reorder existing statuses here. +WARNING. DO NOT DELETE ANY OF THE DEFAULT STATUSES. If you do, RT +will break horribly. The statuses you add must be no longer than +10 characters. + +=cut + +Set(@ActiveStatus, qw(new open stalled)); +Set(@InactiveStatus, qw(resolved rejected deleted)); + +=item C<$LinkTransactionsRun1Scrip> + +RT-3.4 backward compatibility setting. Add/Delete Link used to record one +transaction and run one scrip. Set this value to 1 if you want +only one of the link transactions to have scrips run. + +=cut + +Set($LinkTransactionsRun1Scrip, 0); + +=item C<$StrictLinkACL> + +When this feature is enabled a user needs I<ModifyTicket> rights on both +tickets to link them together, otherwise he can have rights on either of +them. + +=cut + +Set($StrictLinkACL, 1); + +=item C<$PreviewScripMessages> + +Set C<$PreviewScripMessages> to 1 if the scrips preview on the ticket +reply page should include the content of the messages to be sent. + +=cut + +Set($PreviewScripMessages, 0); + +=item C<$UseTransactionBatch> + +Set C<$UseTransactionBatch> to 1 to execute transactions in batches, +such that a resolve and comment (for example) would happen +simultaneously, instead of as two transactions, unaware of each +others' existence. + +=cut + +Set($UseTransactionBatch, 1); + +=item C<@CustomFieldValuesSources> + +Set C<@CustomFieldValuesSources> to a list of class names which extend +L<RT::CustomFieldValues::External>. This can be used to pull lists of +custom field values from external sources at runtime. + +=cut + +Set(@CustomFieldValuesSources, ()); + +=item C<$CanonicalizeRedirectURLs> + +Set C<$CanonicalizeRedirectURLs> to 1 to use $C<WebURL> when redirecting rather +than the one we get from C<%ENV>. + +If you use RT behind a reverse proxy, you almost certainly want to +enable this option. + +=cut + +Set($CanonicalizeRedirectURLs, 0); +=item C<$EnableReminders> + +Hide links/portlets related to Reminders by setting this to 0 + +=cut + +Set($EnableReminders,1); + + +=item C<@Plugins> + +Set C<@Plugins> to a list of external RT plugins that should be enabled (those +plugins have to be previously downloaded and installed). +Example: + +C<Set(@Plugins, (qw(Extension::QuickDelete RT::FM)));> + +=cut + +Set(@Plugins, (qw(RTx::Calendar))); #RTx::Checklist )); + +=back + +=head1 Development Configuration + +=over 4 + +=item C<$DevelMode> + +RT comes with a "Development mode" setting. +This setting, as a convenience for developers, turns on +all sorts of development options that you most likely don't want in +production: + +* Turns off Mason's 'static_source' directive. By default, you can't + edit RT's web ui components on the fly and have RT magically pick up + your changes. (It's a big performance hit) + + * More to come + +=cut + +Set($DevelMode, '@RT_DEVEL_MODE@'); + + +=back + +=head1 Deprecated Options + +=over 4 + +=item C<$AlwaysUseBase64> + +Encode blobs as base64 in DB (?) + +=item C<$TicketBaseURI> + +Base URI to tickets in this system; used when loading (?) + +=item C<$UseCodeTickets> + +This option is exists for backwards compatibility. Don't use it. + +=back + +=cut + +1; diff --git a/rt/etc/RT_SiteConfig.pm b/rt/etc/RT_SiteConfig.pm new file mode 100644 index 000000000..eb2d09af5 --- /dev/null +++ b/rt/etc/RT_SiteConfig.pm @@ -0,0 +1,53 @@ +# Any configuration directives you include here will override +# RT's default configuration file, RT_Config.pm +# +# To include a directive here, just copy the equivalent statement +# from RT_Config.pm and change the value. We've included a single +# sample value below. +# +# This file is actually a perl module, so you can include valid +# perl code, as well. +# +# The converse is also true, if this file isn't valid perl, you're +# going to run into trouble. To check your SiteConfig file, use +# this comamnd: +# +# perl -c /path/to/your/etc/RT_SiteConfig.pm + +#Set( $rtname, 'example.com'); + +# These settings should have been inserted by the initial Freeside install. +# Sometimes you may want to change domain, timezone, or freeside::URL later, +# everything else should probably stay untouched. + +Set($rtname, '%%%RT_DOMAIN%%%'); +Set($Organization, '%%%RT_DOMAIN%%%'); + +Set($Timezone, '%%%RT_TIMEZONE%%%'); + +Set($WebExternalAuth, 1); +Set($WebFallbackToInternal, 1); #no +Set($WebExternalAuto, 1); + +$RT::URI::freeside::IntegrationType = 'Internal'; +$RT::URI::freeside::URL = '%%%FREESIDE_URL%%%'; + +$RT::URI::freeside::URL =~ m(^(https?://[^/]+)(/.*)$)i; +Set($WebBaseURL, $1); +Set($WebPath, "$2/rt"); + +Set($DatabaseHost , ''); + +# These settings are user-editable. + +Set($WebDefaultStylesheet, 'freeside2.1'); +Set($UsernameFormat, 'verbose'); #back to concise to hide email addresses + +#uncomment to use +#Set($DefaultSummaryRows, 10); + +Set($MessageBoxWidth, 80); +Set($MessageBoxRichTextHeight, 368); + +#Set(@Plugins,(qw(Extension::QuickDelete RT::FM))); +1; diff --git a/rt/etc/acl.Informix b/rt/etc/acl.Informix new file mode 100644 index 000000000..eff232f4d --- /dev/null +++ b/rt/etc/acl.Informix @@ -0,0 +1,6 @@ + +sub acl { + return ("GRANT RESOURCE TO ". RT->Config->Get('DatabaseUser') .";"); +} + +1; diff --git a/rt/etc/acl.Oracle b/rt/etc/acl.Oracle new file mode 100644 index 000000000..9ca4122a0 --- /dev/null +++ b/rt/etc/acl.Oracle @@ -0,0 +1,4 @@ + +sub acl { return () } + +1; diff --git a/rt/etc/acl.Pg b/rt/etc/acl.Pg new file mode 100755 index 000000000..8a0d4f28c --- /dev/null +++ b/rt/etc/acl.Pg @@ -0,0 +1,76 @@ + +sub acl { + my $dbh = shift; + + my @acls; + + my @tables = qw ( + attachments_id_seq + Attachments + Attributes + attributes_id_seq + queues_id_seq + Queues + links_id_seq + Links + principals_id_seq + Principals + groups_id_seq + Groups + scripconditions_id_seq + ScripConditions + transactions_id_seq + Transactions + scrips_id_seq + Scrips + acl_id_seq + ACL + groupmembers_id_seq + GroupMembers + cachedgroupmembers_id_seq + CachedGroupMembers + users_id_seq + Users + tickets_id_seq + Tickets + scripactions_id_seq + ScripActions + templates_id_seq + Templates + objectcustomfieldvalues_id_s + ObjectCustomFieldValues + customfields_id_seq + CustomFields + objectcustomfields_id_s + ObjectCustomFields + customfieldvalues_id_seq + CustomFieldValues + sessions + ); + + my $db_user = RT->Config->Get('DatabaseUser'); + my $db_pass = RT->Config->Get('DatabasePassword'); + + # if there's already an rt_user, use it. + my @row = $dbh->selectrow_array( "SELECT usename FROM pg_user WHERE usename = '$db_user'" ); + unless ( $row[0] ) { + push @acls, "CREATE USER \"$db_user\" WITH PASSWORD '$db_pass' NOCREATEDB NOCREATEUSER;"; + } + + my $sequence_right + = ( $dbh->{pg_server_version} >= 80200 ) + ? "USAGE, SELECT, UPDATE" + : "SELECT, UPDATE"; + foreach my $table (@tables) { + if ( $table =~ /^[a-z]/ && $table ne 'sessions' ) { +# table like objectcustomfields_id_s + push @acls, "GRANT $sequence_right ON $table TO \"$db_user\";" + } + else { + push @acls, "GRANT SELECT, INSERT, UPDATE, DELETE ON $table TO \"$db_user\";" + } + } + return (@acls); +} + +1; diff --git a/rt/etc/acl.Sybase b/rt/etc/acl.Sybase new file mode 100644 index 000000000..7583c02e3 --- /dev/null +++ b/rt/etc/acl.Sybase @@ -0,0 +1,10 @@ + +sub acl { + my $db_name = RT->Config->Get('DatabaseName'); + my $db_user = RT->Config->Get('DatabaseUser'); + my $db_pass = RT->Config->Get('DatabasePassword'); + + return ("SP_ADDLOGIN $db_user, $db_pass, $db_name"); +} + +1; diff --git a/rt/etc/acl.mysql b/rt/etc/acl.mysql new file mode 100755 index 000000000..0982ca228 --- /dev/null +++ b/rt/etc/acl.mysql @@ -0,0 +1,27 @@ + +sub acl { + my $db_name = RT->Config->Get('DatabaseName'); + my $db_rthost = RT->Config->Get('DatabaseRTHost'); + my $db_user = RT->Config->Get('DatabaseUser'); + my $db_pass = RT->Config->Get('DatabasePassword'); + unless ( $db_user ) { + print STDERR "DatabaseUser option is not defined or empty. Skipping...\n"; + return; + } + if ( $db_user eq 'root' ) { + print STDERR "DatabaseUser is root. Skipping...\n"; + return; + } + print "Granting access to $db_user\@'$db_rthost' on $db_name.\n"; + return ( + "USE mysql;", + "DELETE FROM user WHERE user = '$db_user';", + "DELETE FROM db where db = '$db_name';", + "GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE + ON $db_name.* + TO '$db_user'\@'$db_rthost' + IDENTIFIED BY '$db_pass';", + ); +} + +1; diff --git a/rt/etc/constraints.mysql b/rt/etc/constraints.mysql new file mode 100644 index 000000000..355d2c5e5 --- /dev/null +++ b/rt/etc/constraints.mysql @@ -0,0 +1,85 @@ + + ALTER TABLE Links ADD INDEX(LocalBase); + ALTER TABLE Links ADD FOREIGN KEY (LocalBase) REFERENCES Tickets(id); + ALTER TABLE Links ADD INDEX(LocalTarget); + ALTER TABLE Links ADD FOREIGN KEY (LocalTarget) REFERENCES Tickets(id); + ALTER TABLE Tickets ADD INDEX(Queue); + ALTER TABLE Tickets ADD FOREIGN KEY (Queue) REFERENCES Queues(id); + ALTER TABLE Tickets ADD INDEX(EffectiveId); + ALTER TABLE Tickets ADD FOREIGN KEY (EffectiveId) REFERENCES Tickets(id); + ALTER TABLE Tickets ADD INDEX(Owner); + ALTER TABLE Tickets ADD FOREIGN KEY (Owner) REFERENCES Principals(id); + ALTER TABLE Tickets ADD INDEX(Creator); + ALTER TABLE Tickets ADD INDEX(LastUpdatedBy); + ALTER TABLE Tickets ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE Tickets ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE Transactions ADD INDEX(Creator); + ALTER TABLE Transactions ADD INDEX (Ticket) ; + ALTER TABLE Transactions ADD INDEX (EffectiveTicket) ; + ALTER TABLE Transactions ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE Transactions ADD FOREIGN KEY (Ticket) REFERENCES Tickets(id); + ALTER TABLE Transactions ADD FOREIGN KEY (EffectiveTicket) REFERENCES Tickets(id); + ALTER TABLE Attachments ADD INDEX (TransactionId) ; + ALTER TABLE Attachments ADD INDEX (Parent) ; + ALTER TABLE Attachments ADD FOREIGN KEY (TransactionId) REFERENCES Transactions(id); + ALTER TABLE Attachments ADD FOREIGN KEY (Parent) REFERENCES Attachments(id); + ALTER TABLE Scrips ADD INDEX (ScripCondition) ; + ALTER TABLE Scrips ADD INDEX (ScripAction) ; + ALTER TABLE Scrips ADD INDEX (Template) ; + ALTER TABLE Scrips ADD INDEX (Queue) ; + ALTER TABLE Scrips ADD INDEX (Creator) ; + ALTER TABLE Scrips ADD INDEX (LastUpdatedBy) ; + ALTER TABLE Scrips ADD FOREIGN KEY (ScripCondition) REFERENCES ScripConditions(id); + ALTER TABLE Scrips ADD FOREIGN KEY (ScripAction) REFERENCES ScripActions(id); + ALTER TABLE Scrips ADD FOREIGN KEY (Template) REFERENCES Templates(id); + ALTER TABLE Scrips ADD FOREIGN KEY (Queue) REFERENCES Queues(id); + ALTER TABLE Scrips ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE Scrips ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE ACL ADD INDEX (PrincipalId) ; + ALTER TABLE ACL ADD INDEX (DelegatedBy) ; + ALTER TABLE ACL ADD INDEX (DelegatedFrom) ; + ALTER TABLE ACL ADD FOREIGN KEY (PrincipalId) REFERENCES Principals(id); + ALTER TABLE ACL ADD FOREIGN KEY (DelegatedBy) REFERENCES Principals(id); + ALTER TABLE ACL ADD FOREIGN KEY (DelegatedFrom) REFERENCES ACL(id); + ALTER TABLE GroupMembers ADD INDEX (MemberId); + ALTER TABLE GroupMembers ADD INDEX (GroupId); + ALTER TABLE GroupMembers ADD FOREIGN KEY (GroupId) REFERENCES Groups(id); + ALTER TABLE GroupMembers ADD FOREIGN KEY (MemberId) REFERENCES Principals(id); + ALTER TABLE CachedGroupMembers ADD INDEX (ImmediateParentId) ; + ALTER TABLE CachedGroupMembers ADD INDEX (GroupId) ; + ALTER TABLE CachedGroupMembers ADD INDEX (MemberId) ; + ALTER TABLE CachedGroupMembers ADD INDEX (Via) ; + ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (ImmediateParentId) REFERENCES Principals(id); + ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (GroupId) REFERENCES Principals(id); + ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (MemberId) REFERENCES Principals(id); + ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id); + ALTER TABLE ScripActions ADD INDEX(Creator); + ALTER TABLE ScripActions ADD INDEX(LastUpdatedBy); + ALTER TABLE ScripActions ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE ScripActions ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE Templates ADD INDEX(Queue); + ALTER TABLE Templates ADD INDEX(Creator); + ALTER TABLE Templates ADD INDEX(LastUpdatedBy); + ALTER TABLE Templates ADD FOREIGN KEY (Queue) REFERENCES Queues(id); + ALTER TABLE Templates ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE Templates ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE CustomFields ADD INDEX(Queue); + ALTER TABLE CustomFields ADD INDEX(Creator); + ALTER TABLE CustomFields ADD INDEX(LastUpdatedBy); + ALTER TABLE CustomFields ADD FOREIGN KEY (Queue) REFERENCES Queues(id); + ALTER TABLE CustomFields ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE CustomFields ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE TicketCustomFieldValues ADD INDEX(Ticket); + ALTER TABLE TicketCustomFieldValues ADD INDEX(CustomField); + ALTER TABLE TicketCustomFieldValues ADD INDEX(Creator); + ALTER TABLE TicketCustomFieldValues ADD INDEX(LastUpdatedBy); + ALTER TABLE TicketCustomFieldValues ADD FOREIGN KEY (Ticket) REFERENCES Tickets(id); + ALTER TABLE TicketCustomFieldValues ADD FOREIGN KEY (CustomField) REFERENCES CustomFields(id); + ALTER TABLE TicketCustomFieldValues ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE TicketCustomFieldValues ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); + ALTER TABLE CustomFieldValues ADD INDEX(CustomField); + ALTER TABLE CustomFieldValues ADD INDEX(Creator); + ALTER TABLE CustomFieldValues ADD INDEX(LastUpdatedBy); + ALTER TABLE CustomFieldValues ADD FOREIGN KEY (CustomField) REFERENCES CustomFields(id); + ALTER TABLE CustomFieldValues ADD FOREIGN KEY (Creator) REFERENCES Users(id); + ALTER TABLE CustomFieldValues ADD FOREIGN KEY (LastUpdatedBy) REFERENCES Users(id); diff --git a/rt/etc/drop.Informix b/rt/etc/drop.Informix new file mode 100644 index 000000000..ce7cc0181 --- /dev/null +++ b/rt/etc/drop.Informix @@ -0,0 +1,19 @@ +DROP TABLE ACL; +DROP TABLE ATTACHMENTS; +DROP TABLE CACHEDGROUPMEMBERS; +DROP TABLE CUSTOMFIELDS; +DROP TABLE CUSTOMFIELDVALUES; +DROP TABLE GROUPMEMBERS; +DROP TABLE GROUPS; +DROP TABLE LINKS; +DROP TABLE PRINCIPALS; +DROP TABLE QUEUES; +DROP TABLE SCRIPACTIONS; +DROP TABLE SCRIPCONDITIONS; +DROP TABLE SCRIPS; +DROP TABLE SESSIONS; +DROP TABLE TEMPLATES; +DROP TABLE TICKETCUSTOMFIELDVALUES; +DROP TABLE TICKETS; +DROP TABLE TRANSACTIONS; +DROP TABLE USERS; diff --git a/rt/etc/drop.Oracle b/rt/etc/drop.Oracle new file mode 100644 index 000000000..475e984e1 --- /dev/null +++ b/rt/etc/drop.Oracle @@ -0,0 +1,41 @@ +DROP TABLE ACL; +DROP TABLE ATTACHMENTS; +DROP TABLE ATTRIBUTES; +DROP TABLE CACHEDGROUPMEMBERS; +DROP TABLE CUSTOMFIELDS; +DROP TABLE CUSTOMFIELDVALUES; +DROP TABLE GROUPMEMBERS; +DROP TABLE GROUPS; +DROP TABLE LINKS; +DROP TABLE PRINCIPALS; +DROP TABLE QUEUES; +DROP TABLE SCRIPACTIONS; +DROP TABLE SCRIPCONDITIONS; +DROP TABLE SCRIPS; +DROP TABLE SESSIONS; +DROP TABLE TEMPLATES; +DROP TABLE OBJECTCUSTOMFIELDS; +DROP TABLE OBJECTCUSTOMFIELDVALUES; +DROP TABLE TICKETS; +DROP TABLE TRANSACTIONS; +DROP TABLE USERS; +DROP SEQUENCE ACL_seq; +DROP SEQUENCE ATTACHMENTS_seq; +DROP SEQUENCE ATTRIBUTES_seq; +DROP SEQUENCE CACHEDGROUPMEMBERS_seq; +DROP SEQUENCE CUSTOMFIELDS_seq; +DROP SEQUENCE CUSTOMFIELDVALUES_seq; +DROP SEQUENCE GROUPMEMBERS_seq; +DROP SEQUENCE GROUPS_seq; +DROP SEQUENCE LINKS_seq; +DROP SEQUENCE PRINCIPALS_seq; +DROP SEQUENCE QUEUES_seq; +DROP SEQUENCE SCRIPACTIONS_seq; +DROP SEQUENCE SCRIPCONDITIONS_seq; +DROP SEQUENCE SCRIPS_seq; +DROP SEQUENCE TEMPLATES_seq; +DROP SEQUENCE OBJECTCUSTOMFIELDVALUES_seq; +DROP SEQUENCE OBJECTCUSTOMFIELDS_seq; +DROP SEQUENCE TICKETS_seq; +DROP SEQUENCE TRANSACTIONS_seq; +DROP SEQUENCE USERS_seq; diff --git a/rt/etc/initialdata b/rt/etc/initialdata new file mode 100644 index 000000000..89db2cc64 --- /dev/null +++ b/rt/etc/initialdata @@ -0,0 +1,604 @@ +# Initial data for a fresh RT3 Installation. + +@Users = ( + { Name => 'root', + Gecos => 'root', + RealName => 'Enoch Root', + Password => 'password', + EmailAddress => "root\@localhost", + Comments => 'SuperUser', + Privileged => '1', + }, +); + +@Groups = ( +); + +@Queues = ({ Name => 'General', + Description => 'The default queue', + CorrespondAddress => "", + CommentAddress => "", }, + { Name => '___Approvals', + Description => 'A system-internal queue for the approvals system', + Disabled => 2, } ); + +@ScripActions = ( + + { Name => 'Autoreply To Requestors', # loc + Description => +'Always sends a message to the requestors independent of message sender' , # loc + ExecModule => 'Autoreply', + Argument => 'Requestor' }, + { Name => 'Notify Requestors', # loc + Description => 'Sends a message to the requestors', # loc + ExecModule => 'Notify', + Argument => 'Requestor' }, + { Name => 'Notify Owner as Comment', # loc + Description => 'Sends mail to the owner', # loc + ExecModule => 'NotifyAsComment', + Argument => 'Owner' }, + { Name => 'Notify Owner', # loc + Description => 'Sends mail to the owner', # loc + ExecModule => 'Notify', + Argument => 'Owner' }, + { Name => 'Notify Ccs as Comment', # loc + Description => 'Sends mail to the Ccs as a comment', # loc + ExecModule => 'NotifyAsComment', + Argument => 'Cc' }, + { Name => 'Notify Ccs', # loc + Description => 'Sends mail to the Ccs', # loc + ExecModule => 'Notify', + Argument => 'Cc' }, + { Name => 'Notify AdminCcs as Comment', # loc + Description => 'Sends mail to the administrative Ccs as a comment', # loc + ExecModule => 'NotifyAsComment', + Argument => 'AdminCc' }, + { Name => 'Notify AdminCcs', # loc + Description => 'Sends mail to the administrative Ccs', # loc + ExecModule => 'Notify', + Argument => 'AdminCc' }, + + { Name => 'Notify Requestors and Ccs as Comment', # loc + Description => 'Send mail to requestors and Ccs as a comment', # loc + ExecModule => 'NotifyAsComment', + Argument => 'Requestor,Cc' }, + + { Name => 'Notify Requestors and Ccs', # loc + Description => 'Send mail to requestors and Ccs', # loc + ExecModule => 'Notify', + Argument => 'Requestor,Cc' }, + + { Name => 'Notify Owner, Requestors, Ccs and AdminCcs as Comment', # loc + Description => 'Send mail to owner and all watchers as a "comment"', # loc + ExecModule => 'NotifyAsComment', + Argument => 'All' }, + { Name => 'Notify Owner, Requestors, Ccs and AdminCcs', # loc + Description => 'Send mail to owner and all watchers', # loc + ExecModule => 'Notify', + Argument => 'All' }, + { Name => 'Notify Other Recipients as Comment', # loc + Description => 'Sends mail to explicitly listed Ccs and Bccs', # loc + ExecModule => 'NotifyAsComment', + Argument => 'OtherRecipients' }, + { Name => 'Notify Other Recipients', # loc + Description => 'Sends mail to explicitly listed Ccs and Bccs', # loc + ExecModule => 'Notify', + Argument => 'OtherRecipients' }, + { Name => 'User Defined', # loc + Description => 'Perform a user-defined action', # loc + ExecModule => 'UserDefined', }, + { Name => 'Create Tickets', # loc + Description => + 'Create new tickets based on this scrip\'s template', # loc + ExecModule => 'CreateTickets', }, + { Name => 'Open Tickets', # loc + Description => 'Open tickets on correspondence', # loc + ExecModule => 'AutoOpen' }, + { Name => 'Extract Subject Tag', # loc + Description => 'Extract tags from a Transaction\'s subject and add them to the Ticket\'s subject.', # loc + ExecModule => 'ExtractSubjectTag' }, +); + +@ScripConditions = ( + { Name => 'On Create', # loc + Description => 'When a ticket is created', # loc + ApplicableTransTypes => 'Create', + ExecModule => 'AnyTransaction', }, + + { Name => 'On Transaction', # loc + Description => 'When anything happens', # loc + ApplicableTransTypes => 'Any', + ExecModule => 'AnyTransaction', }, + { + + Name => 'On Correspond', # loc + Description => 'Whenever correspondence comes in', # loc + ApplicableTransTypes => 'Correspond', + ExecModule => 'AnyTransaction', }, + + { + + Name => 'On Comment', # loc + Description => 'Whenever comments come in', # loc + ApplicableTransTypes => 'Comment', + ExecModule => 'AnyTransaction' }, + { + + Name => 'On Status Change', # loc + Description => 'Whenever a ticket\'s status changes', # loc + ApplicableTransTypes => 'Status', + ExecModule => 'AnyTransaction', + + }, + { + + Name => 'On Priority Change', # loc + Description => 'Whenever a ticket\'s priority changes', # loc + ApplicableTransTypes => 'Set', + ExecModule => 'PriorityChange', + }, + { + + Name => 'On Owner Change', # loc + Description => 'Whenever a ticket\'s owner changes', # loc + ApplicableTransTypes => 'Any', + ExecModule => 'OwnerChange', + + }, + { + + Name => 'On Queue Change', # loc + Description => 'Whenever a ticket\'s queue changes', # loc + ApplicableTransTypes => 'Set', + ExecModule => 'QueueChange', + + }, + { Name => 'On Resolve', # loc + Description => 'Whenever a ticket is resolved', # loc + ApplicableTransTypes => 'Status', + ExecModule => 'StatusChange', + Argument => 'resolved' + + }, + { Name => 'On Reject', # loc + Description => 'Whenever a ticket is rejected', # loc + ApplicableTransTypes => 'Status', + ExecModule => 'StatusChange', + Argument => 'rejected' + + }, + { Name => 'User Defined', # loc + Description => 'Whenever a user-defined condition occurs', # loc + ApplicableTransTypes => 'Any', + ExecModule => 'UserDefined' + + }, + + { Name => 'On Close', # loc + Description => 'Whenever a ticket is closed', # loc + ApplicableTransTypes => 'Status,Set', + ExecModule => 'CloseTicket', + }, + { Name => 'On Reopen', # loc + Description => 'Whenever a ticket is reopened', # loc + ApplicableTransTypes => 'Status,Set', + ExecModule => 'ReopenTicket', + }, + +); + +@Templates = ( + { Queue => '0', + Name => 'Blank', # loc + Description => 'A blank template', # loc + Content => '', }, + { Queue => '0', + Name => 'Autoreply', # loc + Description => 'Default Autoresponse template', # loc + Content => 'Subject: AutoReply: {$Ticket->Subject} + + +Greetings, + +This message has been automatically generated in response to the +creation of a trouble ticket regarding: + "{$Ticket->Subject()}", +a summary of which appears below. + +There is no need to reply to this message right now. Your ticket has been +assigned an ID of [{$Ticket->QueueObj->SubjectTag || $rtname} #{$Ticket->id()}]. + +Please include the string: + + [{$Ticket->QueueObj->SubjectTag || $rtname} #{$Ticket->id}] + +in the subject line of all future correspondence about this issue. To do so, +you may reply to this message. + + Thank you, + {$Ticket->QueueObj->CorrespondAddress()} + +------------------------------------------------------------------------- +{$Transaction->Content()} +' + }, + + { Queue => '0', + Name => 'Transaction', # loc + Description => 'Default transaction template', # loc + Content => 'RT-Attach-Message: yes + + +{$Transaction->CreatedAsString}: Request {$Ticket->id} was acted upon. + Transaction: {$Transaction->Description} + Queue: {$Ticket->QueueObj->Name} + Subject: {$Transaction->Subject || $Ticket->Subject || "(No subject given)"} + Owner: {$Ticket->OwnerObj->Name} + Requestors: {$Ticket->RequestorAddresses} + Status: {$Ticket->Status} + Ticket <URL: {RT->Config->Get(\'WebURL\')}Ticket/Display.html?id={$Ticket->id} > + + +{$Transaction->Content()} +' + }, + + { + + Queue => '0', + Name => 'Admin Correspondence', # loc + Description => 'Default admin correspondence template', # loc + Content => 'RT-Attach-Message: yes + + +<URL: {RT->Config->Get(\'WebURL\')}Ticket/Display.html?id={$Ticket->id} > + +{$Transaction->Content()} +' + }, + + { Queue => '0', + Name => 'Correspondence', # loc + Description => 'Default correspondence template', # loc + Content => 'RT-Attach-Message: yes + +{$Transaction->Content()} +' + }, + + { Queue => '0', + Name => 'Admin Comment', # loc + Description => 'Default admin comment template', # loc + Content => +'Subject: [Comment] {my $s=($Transaction->Subject||$Ticket->Subject); $s =~ s/\\[Comment\\]//g; $s =~ s/^Re//i; $s;} +RT-Attach-Message: yes + + +{RT->Config->Get(\'WebURL\')}Ticket/Display.html?id={$Ticket->id} +This is a comment. It is not sent to the Requestor(s): + +{$Transaction->Content()} +' + }, + + { Queue => '0', + Name => 'Status Change', # loc + Description => 'Ticket status changed', # loc + Content => 'Subject: Status Changed to: {$Transaction->NewValue} + + +{RT->Config->Get(\'WebURL\')}Ticket/Display.html?id={$Ticket->id} + +{$Transaction->Content()} +' + }, + + { + + Queue => '0', + Name => 'Resolved', # loc + Description => 'Ticket Resolved', # loc + Content => 'Subject: Resolved: {$Ticket->Subject} + +According to our records, your request has been resolved. If you have any +further questions or concerns, please respond to this message. +' + }, + { Queue => '___Approvals', + Name => "New Pending Approval", # loc + Description => + "Notify Owners and AdminCcs of new items pending their approval", # loc + Content => 'Subject: New Pending Approval: {$Ticket->Subject} + +Greetings, + +There is a new item pending your approval: "{$Ticket->Subject()}", +a summary of which appears below. + +Please visit {RT->Config->Get(\'WebURL\')}Approvals/Display.html?id={$Ticket->id} +to approve or reject this ticket, or {RT->Config->Get(\'WebURL\')}Approvals/ to +batch-process all your pending approvals. + +------------------------------------------------------------------------- +{$Transaction->Content()} +' + }, + { Queue => '___Approvals', + Name => "Approval Passed", # loc + Description => + "Notify Requestor of their ticket has been approved by some approver", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +Your ticket has been approved by { eval { $Approval->OwnerObj->Name } }. +Other approvals may be pending. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "All Approvals Passed", # loc + Description => + "Notify Requestor of their ticket has been approved by all approvers", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +Your ticket has been approved by { eval { $Approval->OwnerObj->Name } }. +Its Owner may now start to act on it. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "Approval Rejected", # loc + Description => + "Notify Owner of their rejected ticket", # loc + Content => 'Subject: Ticket Rejected: {$Ticket->Subject} + +Greetings, + +Your ticket has been rejected by { eval { $Approval->OwnerObj->Name } }. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "Approval Ready for Owner", # loc + Description => + "Notify Owner of their ticket has been approved and is ready to be acted on", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +The ticket has been approved, you may now start to act on it. + +' + }, + { Queue => 0, + Name => "Forward", # loc + Description => "Heading of a forwarded message", # loc + Content => q{ +This is a forward of transaction #{$Transaction->id} of ticket #{ $Ticket->id } +} + }, + { Queue => 0, + Name => "Forward Ticket", # loc + Description => "Heading of a forwarded Ticket", # loc + Content => q{ + +This is a forward of ticket #{ $Ticket->id } +} + }, + { Queue => 0, + Name => "Error: public key", # loc + Description => + "Inform user that he has problems with public key and couldn't recieve encrypted content", # loc + Content => q{Subject: We have no your public key or it's wrong + +You received this message as we have no your public PGP key or we have a problem with your key. Inform the administrator about the problem. +} + }, + { Queue => 0, + Name => "Error to RT owner: public key", # loc + Description => + "Inform RT owner that user(s) have problems with public keys", # loc + Content => q{Subject: Some users have problems with public keys + +You received this message as RT has problems with public keys of the following user: +{ + foreach my $e ( @BadRecipients ) { + $OUT .= "* ". $e->{'Message'} ."\n"; + } +}} + }, + { Queue => 0, + Name => "Error: no private key", # loc + Description => + "Inform user that we received an encrypted email and we have no private keys to decrypt", # loc + Content => q{Subject: we received message we cannot decrypt + +You sent an encrypted message with subject '{ $Message->head->get('Subject') }', +but we have no private key it's encrypted to. + +Please, check that you encrypt messages with correct keys +or contact the system administrator.} + }, + { Queue => 0, + Name => "Error: bad GnuPG data", # loc + Description => + "Inform user that a message he sent has invalid GnuPG data", # loc + Content => q{Subject: We received a message we cannot handle + +You sent us a message that we cannot handle due to corrupted GnuPG signature or encrypted block. we get the following error(s): +{ foreach my $msg ( @Messages ) { + $OUT .= "* $msg\n"; + } +}} + }, + { Queue => 0, + Name => "PasswordChange", # loc + Description => + "Inform user that his password has been reset", # loc + Content => q{Subject: [{RT->Config->Get('rtname')}] Password reset + +Greetings, + +Someone at {$ENV{'REMOTE_ADDR'}} requested a password reset for you on {RT->Config->Get('WebURL')} + +Your new password is: + {$NewPassword} +} + }, + + { Queue => '0', + Name => 'Email Digest', # loc + Description => 'Email template for periodic notification digests', # loc + Content => q[Subject: RT Email Digest + +{ $Argument } +], + }, + +{ + Queue => 0, + Name => "Error: Missing dashboard", # loc + Description => + "Inform user that a dashboard he subscribed to is missing", # loc + Content => q{Subject: [{RT->Config->Get('rtname')}] Missing dashboard! + +Greetings, + +You are subscribed to a dashboard that is currently missing. Most likely, the dashboard was deleted. + +RT will remove this subscription as it is no longer useful. Here's the information RT had about your subscription: + +DashboardID: { $SubscriptionObj->SubValue('DashboardId') } +Frequency: { $SubscriptionObj->SubValue('Frequency') } +Hour: { $SubscriptionObj->SubValue('Hour') } +{ + $SubscriptionObj->SubValue('Frequency') eq 'weekly' + ? "Day of week: " . $SubscriptionObj->SubValue('Dow') + : $SubscriptionObj->SubValue('Frequency') eq 'monthly' + ? "Day of month: " . $SubscriptionObj->SubValue('Dom') + : '' +} +} +}, +); +# }}} + +@Scrips = ( + { Description => 'On Correspond Open Tickets', + ScripCondition => 'On Correspond', + ScripAction => 'Open Tickets', + Template => 'Blank' }, + { Description => 'On Owner Change Notify Owner', + ScripCondition => 'On Owner Change', + ScripAction => 'Notify Owner', + Template => 'Transaction' }, + { Description => 'On Create Autoreply To Requestors', + ScripCondition => 'On Create', + ScripAction => 'AutoReply To Requestors', + Template => 'AutoReply' }, + { Description => 'On Create Notify AdminCcs', + ScripCondition => 'On Create', + ScripAction => 'Notify AdminCcs', + Template => 'Transaction' }, + { Description => 'On Correspond Notify AdminCcs', + ScripCondition => 'On Correspond', + ScripAction => 'Notify AdminCcs', + Template => 'Admin Correspondence' }, + { Description => 'On Correspond Notify Requestors and Ccs', + ScripCondition => 'On Correspond', + ScripAction => 'Notify Requestors And Ccs', + Template => 'Correspondence' }, + { Description => 'On Correspond Notify Other Recipients', + ScripCondition => 'On Correspond', + ScripAction => 'Notify Other Recipients', + Template => 'Correspondence' }, + { Description => 'On Comment Notify AdminCcs as Comment', + ScripCondition => 'On Comment', + ScripAction => 'Notify AdminCcs As Comment', + Template => 'Admin Comment' }, + { Description => 'On Comment Notify Other Recipients as Comment', + ScripCondition => 'On Comment', + ScripAction => 'Notify Other Recipients As Comment', + Template => 'Correspondence' }, + { Description => 'On Resolve Notify Requestors', + ScripCondition => 'On Resolve', + ScripAction => 'Notify Requestors', + Template => 'Resolved' }, + { Description => "On transaction, add any tags in the transaction's subject to the ticket's subject", + ScripCondition => 'On Transaction', + ScripAction => 'Extract Subject Tag', + Template => 'Blank' }, +); + +@ACL = ( + { UserId => 'root', # - principalid + Right => 'SuperUser', }, + + { GroupDomain => 'SystemInternal', + GroupType => 'privileged', + Right => 'ShowApprovalsTab', }, + +); + +# Predefined searches + +@Attributes = ( + { Name => 'Search - My Tickets', + Description => '[_1] highest priority tickets I own', # loc + Content => + { Format => q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',} + . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',} + . q{Priority, QueueName, ExtendedStatus}, + Query => " Owner = '__CurrentUser__' AND ( Status = 'new' OR Status = 'open')", + OrderBy => 'Priority', + Order => 'DESC' + }, + }, + { Name => 'Search - Unowned Tickets', + Description => '[_1] newest unowned tickets', # loc + Content => +# 'Take' #loc + { Format => q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',} + . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',} + . q{QueueName, ExtendedStatus, CreatedRelative, } + . q{'<A HREF="__WebPath__/Ticket/Display.html?Action=Take&id=__id__">__loc(Take)__</a>/TITLE:NBSP'}, + Query => " Owner = 'Nobody' AND ( Status = 'new' OR Status = 'open')", + OrderBy => 'Created', + Order => 'DESC' + }, + }, + { Name => 'Search - Bookmarked Tickets', + Description => 'Bookmarked Tickets', #loc + Content => + { Format => q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',} + . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',} + . q{Priority, QueueName, ExtendedStatus, Bookmark}, + Query => "id = '__Bookmarked__'", + OrderBy => 'LastUpdated', + Order => 'DESC' }, + }, + { Name => 'HomepageSettings', + Description => 'HomepageSettings', + Content => + { 'body' => # loc + [ { type => 'system', name => 'My Tickets' }, + { type => 'system', name => 'Unowned Tickets' }, + { type => 'system', name => 'Bookmarked Tickets' }, + { type => 'component', name => 'QuickCreate' }, + ], + 'summary' => # loc + [ + { type => 'component', name => 'MyReminders' }, + { type => 'component', name => 'Quicksearch' }, + { type => 'component', name => 'Dashboards' }, + { type => 'component', name => 'RefreshHomepage' }, + ], + }, + }, +); diff --git a/rt/etc/schema.Informix b/rt/etc/schema.Informix new file mode 100644 index 000000000..6a4e5334e --- /dev/null +++ b/rt/etc/schema.Informix @@ -0,0 +1,364 @@ +-- This schema was adopted from the oracle schema by +-- Andre Koppel. +-- Version 0.2 Date 2003.10.21 +-- The work is still in progress + +CREATE TABLE Attachments ( + id SERIAL, + TransactionId INTEGER NOT NULL, + Parent INTEGER DEFAULT 0 NOT NULL, + MessageId VARCHAR(160), + Subject VARCHAR(255), + Filename VARCHAR(255), + ContentType VARCHAR(80), + ContentEncoding VARCHAR(80), + Content BYTE, + Headers BYTE, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); +CREATE INDEX Attachments1 ON Attachments (Parent); +CREATE INDEX Attachments2 ON Attachments (TransactionId); +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId); + + +CREATE TABLE Queues ( + id SERIAL, + Name VARCHAR(200) DEFAULT '' NOT NULL, + Description VARCHAR(255) DEFAULT NULL, + CorrespondAddress VARCHAR(120) DEFAULT NULL, + CommentAddress VARCHAR(120) DEFAULT NULL, + InitialPriority INTEGER DEFAULT 0 NOT NULL, + FinalPriority INTEGER DEFAULT 0 NOT NULL, + DefaultDueIn INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + Disabled INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE UNIQUE INDEX Queues1 ON Queues (Name); +CREATE INDEX Queues2 ON Queues (Disabled); + + +CREATE TABLE Links ( + id SERIAL, + Base VARCHAR(240) DEFAULT NULL, + Target VARCHAR(240) DEFAULT NULL, + Type VARCHAR(20) DEFAULT '' NOT NULL, + LocalTarget INTEGER DEFAULT 0 NOT NULL, + LocalBase INTEGER DEFAULT 0 NOT NULL, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); +-- CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type); +CREATE INDEX Links2 ON Links (Base, Type); +CREATE INDEX Links3 ON Links (Target, Type); +CREATE INDEX Links4 ON Links(Type,LocalBase); + + +CREATE TABLE Principals ( + id SERIAL, + PrincipalType VARCHAR(16) DEFAULT '' NOT NULL, + ObjectId INTEGER DEFAULT 0, + Disabled INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX Principals2 ON Principals (ObjectId); + + +CREATE TABLE Groups ( + id SERIAL, + Name VARCHAR(200) DEFAULT NULL, + Description VARCHAR(255) DEFAULT NULL, + Domain VARCHAR(64) DEFAULT '', + Type VARCHAR(64) DEFAULT '', + Instance INTEGER DEFAULT 0 NOT NULL, +-- Instance VARCHAR(64) DEFAULT '' NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX Groups1 ON Groups (Domain, Instance, Type, id); +CREATE INDEX Groups2 ON Groups (Type, Instance, Domain); + + +CREATE TABLE ScripConditions ( + id SERIAL, + Name VARCHAR(200), + Description VARCHAR(255), + ExecModule VARCHAR(60), + Argument VARCHAR(255), + ApplicableTransTypes VARCHAR(60), + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + + +CREATE TABLE Transactions ( + id SERIAL, + ObjectType VARCHAR(255), + ObjectId INTEGER DEFAULT 0 NOT NULL, + TimeTaken INTEGER DEFAULT 0 NOT NULL, + Type VARCHAR(20), + Field VARCHAR(40), + OldValue VARCHAR(255), + NewValue VARCHAR(255), + ReferenceType VARCHAR(255), + OldReference INTEGER DEFAULT 0, + NewReference INTEGER DEFAULT 0, + Data VARCHAR(255), + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + + +CREATE TABLE Scrips ( + id SERIAL, + Description VARCHAR(255) DEFAULT '', + ScripCondition INTEGER DEFAULT 0 NOT NULL, + ScripAction INTEGER DEFAULT 0 NOT NULL, + ConditionRules BYTE, + ActionRules BYTE, + CustomIsApplicableCode BYTE, + CustomPrepareCode BYTE, + CustomCommitCode BYTE, + Stage VARCHAR(32), + Queue INTEGER DEFAULT 0 NOT NULL, + Template INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + + +CREATE TABLE ACL ( + id SERIAL, + PrincipalType VARCHAR(25) NOT NULL, + PrincipalId INTEGER NOT NULL, + RightName VARCHAR(25) NOT NULL, + ObjectType VARCHAR(25) NOT NULL, + ObjectId INTEGER DEFAULT 0 NOT NULL, + DelegatedBy INTEGER DEFAULT 0 NOT NULL, + DelegatedFrom INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX ACL1 ON ACL(RightName, ObjectType, ObjectId, PrincipalType, PrincipalId); + + +CREATE TABLE GroupMembers ( + id SERIAL, + GroupId INTEGER DEFAULT 0 NOT NULL, + MemberId INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE UNIQUE INDEX GroupMembers1 ON GroupMembers (GroupId, MemberId); + + +CREATE TABLE CachedGroupMembers ( + id SERIAL, + GroupId INTEGER DEFAULT 0, + MemberId INTEGER DEFAULT 0, + Via INTEGER DEFAULT 0, + ImmediateParentId INTEGER DEFAULT 0, + Disabled INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX DisGrouMem ON CachedGroupMembers (GroupId, MemberId, Disabled); +CREATE INDEX GrouMem ON CachedGroupMembers (GroupId, MemberId); + + +CREATE TABLE Users ( + id SERIAL, + Name VARCHAR(200) NOT NULL, + Password VARCHAR(40), + Comments BYTE, + Signature BYTE, + EmailAddress VARCHAR(120), + FreeFormContactInfo BYTE, + Organization VARCHAR(200), + RealName VARCHAR(120), + NickName VARCHAR(16), + Lang VARCHAR(16), + EmailEncoding VARCHAR(16), + WebEncoding VARCHAR(16), + ExternalContactInfoId VARCHAR(100), + ContactInfoSystem VARCHAR(30), + ExternalAuthId VARCHAR(100), + AuthSystem VARCHAR(30), + Gecos VARCHAR(16), + HomePhone VARCHAR(30), + WorkPhone VARCHAR(30), + MobilePhone VARCHAR(30), + PagerPhone VARCHAR(30), + Address1 VARCHAR(200), + Address2 VARCHAR(200), + City VARCHAR(100), + State VARCHAR(100), + Zip VARCHAR(16), + Country VARCHAR(50), + Timezone VARCHAR(50), + PGPKey BYTE, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); +-- CREATE UNIQUE INDEX Users1 ON Users (Name); +CREATE INDEX Users2 ON Users (Name); +CREATE INDEX Users3 ON Users (id, EmailAddress); +CREATE INDEX Users4 ON Users (EmailAddress); + + +CREATE TABLE Tickets ( + id SERIAL, + EffectiveId INTEGER DEFAULT 0 NOT NULL, + Queue INTEGER DEFAULT 0 NOT NULL, + Type VARCHAR(16), + IssueStatement INTEGER DEFAULT 0 NOT NULL, + Resolution INTEGER DEFAULT 0 NOT NULL, + Owner INTEGER DEFAULT 0 NOT NULL, + Subject VARCHAR(200) DEFAULT '[no subject]', + InitialPriority INTEGER DEFAULT 0 NOT NULL, + FinalPriority INTEGER DEFAULT 0 NOT NULL, + Priority INTEGER DEFAULT 0 NOT NULL, + TimeEstimated INTEGER DEFAULT 0 NOT NULL, + TimeWorked INTEGER DEFAULT 0 NOT NULL, + Status VARCHAR(10), + TimeLeft INTEGER DEFAULT 0 NOT NULL, + Told DATETIME YEAR TO SECOND, + Starts DATETIME YEAR TO SECOND, + Started DATETIME YEAR TO SECOND, + Due DATETIME YEAR TO SECOND, + Resolved DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + Disabled INTEGER DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX Tickets1 ON Tickets (Queue, Status); +CREATE INDEX Tickets2 ON Tickets (Owner); +CREATE INDEX Tickets3 ON Tickets (EffectiveId); +CREATE INDEX Tickets4 ON Tickets (id, Status); +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId); +CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type); + + +CREATE TABLE ScripActions ( + id SERIAL, + Name VARCHAR(200), + Description VARCHAR(255), + ExecModule VARCHAR(60), + Argument VARCHAR(255), + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + + +CREATE TABLE Templates ( + id SERIAL, + Queue INTEGER DEFAULT 0 NOT NULL, + Name VARCHAR(200) NOT NULL, + Description VARCHAR(255), + Type VARCHAR(16), + Language VARCHAR(16), + TranslationOf INTEGER DEFAULT 0 NOT NULL, + Content BYTE, + LastUpdated DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + + +CREATE TABLE TicketCustomFieldValues ( + id SERIAL, + Ticket INTEGER NOT NULL, + CustomField INTEGER NOT NULL, + Content VARCHAR(255), + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + +CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content); +CREATE INDEX TicketCustomFieldValues2 ON TicketCustomFieldValues (CustomField,Ticket); + +CREATE TABLE CustomFields ( + id SERIAL, + Name VARCHAR(200), + Type VARCHAR(200), + MaxValues INTEGER DEFAULT 0 NOT NULL, + Pattern VARCHAR(255), + LookupType VARCHAR(255), + Description VARCHAR(255), + SortOrder INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + Disabled SMALLINT DEFAULT 0 NOT NULL, + PRIMARY KEY (id) +); + + +CREATE TABLE CustomFieldValues ( + id SERIAL, + CustomField INTEGER NOT NULL, + Name VARCHAR(200), + Description VARCHAR(255), + SortOrder INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +CREATE TABLE Attributes ( + id SERIAL, + Name VARCHAR(255) DEFAULT '' NOT NULL, + Description VARCHAR(255) DEFAULT NULL, + Content BYTE, + ContentType VARCHAR(16), + ObjectType VARCHAR(25) NOT NULL, + ObjectId INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + + +CREATE TABLE sessions ( + id VARCHAR(32) NOT NULL, + a_session BYTE, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + diff --git a/rt/etc/schema.Pg b/rt/etc/schema.Pg new file mode 100755 index 000000000..48525c8d7 --- /dev/null +++ b/rt/etc/schema.Pg @@ -0,0 +1,637 @@ +------------------------------------------------------------------ +-- My2Pg 1.23 translated dump +-- +------------------------------------------------------------------ + + + +-- +-- Sequences for table ATTACHMENTS +-- + +CREATE SEQUENCE attachments_id_seq; + +-- {{{ Attachments + +CREATE TABLE Attachments ( + id INTEGER DEFAULT nextval('attachments_id_seq'), + TransactionId integer NOT NULL , + Parent integer NOT NULL DEFAULT 0 , + MessageId varchar(160) NULL , + Subject varchar(255) NULL , + Filename varchar(255) NULL , + ContentType varchar(80) NULL , + ContentEncoding varchar(80) NULL , + Content text NULL , + Headers text NULL , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +CREATE INDEX Attachments1 ON Attachments (Parent) ; +CREATE INDEX Attachments2 ON Attachments (TransactionId) ; +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; +-- }}} + +-- {{{ Queues + + +-- +-- Sequences for table QUEUES +-- + +CREATE SEQUENCE queues_id_seq; + +CREATE TABLE Queues ( + id INTEGER DEFAULT nextval('queues_id_seq'), + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + CorrespondAddress varchar(120) NULL , + CommentAddress varchar(120) NULL , + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + DefaultDueIn integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); +CREATE UNIQUE INDEX Queues1 ON Queues (Name) ; + +-- }}} + +-- {{{ Links + + + +-- +-- Sequences for table LINKS +-- + +CREATE SEQUENCE links_id_seq; + +CREATE TABLE Links ( + id INTEGER DEFAULT nextval('links_id_seq'), + Base varchar(240) NULL , + Target varchar(240) NULL , + Type varchar(20) NOT NULL , + LocalTarget integer NOT NULL DEFAULT 0 , + LocalBase integer NOT NULL DEFAULT 0 , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + PRIMARY KEY (id) + +); +CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ; +CREATE INDEX Links4 ON Links(Type,LocalBase); + +-- }}} + +-- {{{ Principals + + + +-- +-- Sequences for table PRINCIPALS +-- + +CREATE SEQUENCE principals_id_seq; + +CREATE TABLE Principals ( + id INTEGER DEFAULT nextval('principals_id_seq') not null, + PrincipalType VARCHAR(16) not null, + ObjectId integer, + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); + +CREATE INDEX Principals2 ON Principals (ObjectId); + + +-- }}} + +-- {{{ Groups + + + +-- +-- Sequences for table GROUPS +-- + +CREATE SEQUENCE groups_id_seq; + +CREATE TABLE Groups ( + id INTEGER DEFAULT nextval('groups_id_seq'), + Name varchar(200) NULL , + Description varchar(255) NULL , + Domain varchar(64), + Type varchar(64), + Instance integer, + PRIMARY KEY (id) + +); +CREATE UNIQUE INDEX Groups1 ON Groups (Domain,Instance,Type,id, Name); +CREATE INDEX Groups2 On Groups (Type, Instance, Domain); + + +-- }}} + +-- {{{ ScripConditions + + + +-- +-- Sequences for table SCRIPCONDITIONS +-- + +CREATE SEQUENCE scripconditions_id_seq; + +CREATE TABLE ScripConditions ( + id INTEGER DEFAULT nextval('scripconditions_id_seq'), + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + ApplicableTransTypes varchar(60) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ Transactions + + +-- +-- Sequences for table TRANSACTIONS +-- + +CREATE SEQUENCE transactions_id_seq; + +CREATE TABLE Transactions ( + id INTEGER DEFAULT nextval('transactions_id_seq'), + ObjectType varchar(255) NOT NULL , + ObjectId integer NOT NULL DEFAULT 0 , + TimeTaken integer NOT NULL DEFAULT 0 , + Type varchar(20) NULL , + Field varchar(40) NULL , + OldValue varchar(255) NULL , + NewValue varchar(255) NULL , + ReferenceType varchar(255) NULL, + OldReference integer NULL , + NewReference integer NULL , + Data varchar(255) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + PRIMARY KEY (id) + +); +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +-- }}} + +-- {{{ Scrips + + + +-- +-- Sequences for table SCRIPS +-- + +CREATE SEQUENCE scrips_id_seq; + +CREATE TABLE Scrips ( + id INTEGER DEFAULT nextval('scrips_id_seq'), + Description varchar(255), + ScripCondition integer NOT NULL DEFAULT 0 , + ScripAction integer NOT NULL DEFAULT 0 , + ConditionRules text NULL , + ActionRules text NULL , + CustomIsApplicableCode text NULL , + CustomPrepareCode text NULL , + CustomCommitCode text NULL , + Stage varchar(32) NULL , + Queue integer NOT NULL DEFAULT 0 , + Template integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ ACL + + +-- +-- Sequences for table ACL +-- + +CREATE SEQUENCE acl_id_seq; + +CREATE TABLE ACL ( + id INTEGER DEFAULT nextval('acl_id_seq'), + PrincipalType varchar(25) NOT NULL, + + PrincipalId integer NOT NULL , + RightName varchar(25) NOT NULL , + ObjectType varchar(25) NOT NULL , + ObjectId integer NOT NULL DEFAULT 0, + DelegatedBy integer NOT NULL DEFAULT 0, + DelegatedFrom integer NOT NULL DEFAULT 0, + PRIMARY KEY (id) + +); + +CREATE INDEX ACL1 on ACL(RightName, ObjectType, ObjectId,PrincipalType,PrincipalId); + + +-- }}} + +-- {{{ GroupMembers + + + +-- +-- Sequences for table GROUPMEMBERS +-- + +CREATE SEQUENCE groupmembers_id_seq; + +CREATE TABLE GroupMembers ( + id INTEGER DEFAULT nextval('groupmembers_id_seq'), + GroupId integer NOT NULL DEFAULT 0, + MemberId integer NOT NULL DEFAULT 0, + PRIMARY KEY (id) + +); + +CREATE UNIQUE INDEX GroupMembers1 ON GroupMembers(GroupId, MemberId); + +-- }}} + +-- {{{ GroupMembersCache + + + +-- +-- Sequences for table CACHEDGROUPMEMBERS +-- + +CREATE SEQUENCE cachedgroupmembers_id_seq; + +CREATE TABLE CachedGroupMembers ( + id int DEFAULT nextval('cachedgroupmembers_id_seq'), + GroupId int, + MemberId int, + Via int, + ImmediateParentId int, + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); + +CREATE INDEX CachedGroupMembers2 on CachedGroupMembers (MemberId); +CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (GroupId); +CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled); + +-- }}} + +-- {{{ Users + + + +-- +-- Sequences for table USERS +-- + +CREATE SEQUENCE users_id_seq; + +CREATE TABLE Users ( + id INTEGER DEFAULT nextval('users_id_seq'), + Name varchar(200) NOT NULL , + Password varchar(40) NULL , + Comments text NULL , + Signature text NULL , + EmailAddress varchar(120) NULL , + FreeformContactInfo text NULL , + Organization varchar(200) NULL , + RealName varchar(120) NULL , + NickName varchar(16) NULL , + Lang varchar(16) NULL , + EmailEncoding varchar(16) NULL , + WebEncoding varchar(16) NULL , + ExternalContactInfoId varchar(100) NULL , + ContactInfoSystem varchar(30) NULL , + ExternalAuthId varchar(100) NULL , + AuthSystem varchar(30) NULL , + Gecos varchar(16) NULL , + HomePhone varchar(30) NULL , + WorkPhone varchar(30) NULL , + MobilePhone varchar(30) NULL , + PagerPhone varchar(30) NULL , + Address1 varchar(200) NULL , + Address2 varchar(200) NULL , + City varchar(100) NULL , + State varchar(100) NULL , + Zip varchar(16) NULL , + Country varchar(50) NULL , + Timezone varchar(50) NULL , + PGPKey text NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + + +CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users3 ON Users (id, EmailAddress); +CREATE INDEX Users4 ON Users (EmailAddress); + + +-- }}} + +-- {{{ Tickets + + + +-- +-- Sequences for table TICKETS +-- + +CREATE SEQUENCE tickets_id_seq; + +CREATE TABLE Tickets ( + id INTEGER DEFAULT nextval('tickets_id_seq'), + EffectiveId integer NOT NULL DEFAULT 0 , + Queue integer NOT NULL DEFAULT 0 , + Type varchar(16) NULL , + IssueStatement integer NOT NULL DEFAULT 0 , + Resolution integer NOT NULL DEFAULT 0 , + Owner integer NOT NULL DEFAULT 0 , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + Priority integer NOT NULL DEFAULT 0 , + TimeEstimated integer NOT NULL DEFAULT 0 , + TimeWorked integer NOT NULL DEFAULT 0 , + Status varchar(10) NULL , + TimeLeft integer NOT NULL DEFAULT 0 , + Told TIMESTAMP NULL , + Starts TIMESTAMP NULL , + Started TIMESTAMP NULL , + Due TIMESTAMP NULL , + Resolved TIMESTAMP NULL , + + + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets3 ON Tickets (EffectiveId) ; +CREATE INDEX Tickets4 ON Tickets (id, Status) ; +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ; + +-- }}} + +-- {{{ ScripActions + + + +-- +-- Sequences for table SCRIPACTIONS +-- + +CREATE SEQUENCE scripactions_id_seq; + +CREATE TABLE ScripActions ( + id INTEGER DEFAULT nextval('scripactions_id_seq'), + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ Templates + + + +-- +-- Sequences for table TEMPLATES +-- + +CREATE SEQUENCE templates_id_seq; + +CREATE TABLE Templates ( + id INTEGER DEFAULT nextval('templates_id_seq'), + Queue integer NOT NULL DEFAULT 0 , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + Type varchar(16) NULL , + Language varchar(16) NULL , + TranslationOf integer NOT NULL DEFAULT 0 , + Content text NULL , + LastUpdated TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ ObjectCustomFieldValues + + + +-- +-- Sequences for table TICKETCUSTOMFIELDVALUES +-- + +CREATE SEQUENCE objectcustomfieldvalues_id_s; + +CREATE TABLE ObjectCustomFieldValues ( + id INTEGER DEFAULT nextval('objectcustomfieldvalues_id_s'), + CustomField int NOT NULL , + ObjectType varchar(255) NULL , + ObjectId int NOT NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Content varchar(255) NULL , + LargeContent text NULL, + ContentType varchar(80) NULL, + ContentEncoding varchar(80) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); + +CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId,Content); +CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); + +-- }}} + +-- {{{ CustomFields + + + +-- +-- Sequences for table CUSTOMFIELDS +-- + +CREATE SEQUENCE customfields_id_seq; + +CREATE TABLE CustomFields ( + id INTEGER DEFAULT nextval('customfields_id_seq'), + Name varchar(200) NULL , + Type varchar(200) NULL , + MaxValues integer NOT NULL DEFAULT 0 , + Repeated integer NOT NULL DEFAULT 0 , + Pattern varchar(65536) NULL , + LookupType varchar(255) NOT NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + Disabled integer NOT NULL DEFAULT 0 , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ ObjectCustomFields + +CREATE SEQUENCE objectcustomfields_id_s; + +CREATE TABLE ObjectCustomFields ( + id INTEGER DEFAULT nextval('objectcustomfields_id_s'), + CustomField integer NOT NULL, + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +-- }}} + +-- {{{ CustomFieldValues + + + +-- +-- Sequences for table CUSTOMFIELDVALUES +-- + +CREATE SEQUENCE customfieldvalues_id_seq; + +CREATE TABLE CustomFieldValues ( + id INTEGER DEFAULT nextval('customfieldvalues_id_seq'), + CustomField int NOT NULL , + Name varchar(200) NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +-- }}} + + +-- {{{ Attributes + +CREATE SEQUENCE attributes_id_seq; + +CREATE TABLE Attributes ( + id INTEGER DEFAULT nextval('attributes_id_seq'), + Name varchar(255) NOT NULL , + Description varchar(255) NULL , + Content text, + ContentType varchar(16), + ObjectType varchar(64), + ObjectId integer, + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +-- }}} + +-- {{{ Sessions + +-- sessions is used by Apache::Session to keep sessions in the database. +-- We should have a reaper script somewhere. + +CREATE TABLE sessions ( + id char(32) NOT NULL, + a_session bytea, + LastUpdated TIMESTAMP not null default current_timestamp, + PRIMARY KEY (id) + +); + +-- }}} + diff --git a/rt/etc/schema.SQLite b/rt/etc/schema.SQLite new file mode 100644 index 000000000..ce75ccc13 --- /dev/null +++ b/rt/etc/schema.SQLite @@ -0,0 +1,442 @@ +--- {{{ Attachments + +CREATE TABLE Attachments ( + id INTEGER PRIMARY KEY , + TransactionId INTEGER , + Parent integer NULL , + MessageId varchar(160) NULL , + Subject varchar(255) NULL , + Filename varchar(255) NULL , + ContentType varchar(80) NULL , + ContentEncoding varchar(80) NULL , + Content LONGTEXT NULL , + Headers LONGTEXT NULL , + Creator integer NULL , + Created DATETIME NULL + +) ; + +CREATE INDEX Attachments1 ON Attachments (Parent) ; +CREATE INDEX Attachments2 ON Attachments (TransactionId) ; +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; +--- }}} + +--- {{{ Queues +CREATE TABLE Queues ( + id INTEGER PRIMARY KEY , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + CorrespondAddress varchar(120) NULL , + CommentAddress varchar(120) NULL , + InitialPriority integer NULL , + FinalPriority integer NULL , + DefaultDueIn integer NULL , + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 + +) ; +CREATE UNIQUE INDEX Queues1 ON Queues (Name) ; + +--- }}} + +--- {{{ Links + +CREATE TABLE Links ( + id INTEGER PRIMARY KEY , + Base varchar(240) NULL , + Target varchar(240) NULL , + Type varchar(20) NOT NULL , + LocalTarget integer NULL , + LocalBase integer NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL , + Creator integer NULL , + Created DATETIME NULL + +) ; +CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ; +CREATE INDEX Links4 ON Links(Type,LocalBase); + +--- }}} + +--- {{{ Principals + +CREATE TABLE Principals ( + id INTEGER PRIMARY KEY, + PrincipalType VARCHAR(16) not null, + ObjectId integer, + Disabled int2 NOT NULL DEFAULT 0 + +) ; + +--- }}} + +--- {{{ Groups + +CREATE TABLE Groups ( + id INTEGER , + Name varchar(200) NULL , + Description varchar(255) NULL , + Domain varchar(64), + Type varchar(64), + Instance integer + +) ; + +CREATE UNIQUE INDEX Groups1 ON Groups (Name,Domain,Type,Instance) ; + +--- }}} + +--- {{{ ScripConditions + +CREATE TABLE ScripConditions ( + id INTEGER PRIMARY KEY , + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + ApplicableTransTypes varchar(60) NULL , + + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; + +--- }}} + +--- {{{ Transactions +CREATE TABLE Transactions ( + id INTEGER PRIMARY KEY , + ObjectType varchar(255) NULL , + ObjectId integer NULL , + TimeTaken integer NULL , + Type varchar(20) NULL , + Field varchar(40) NULL , + OldValue varchar(255) NULL , + NewValue varchar(255) NULL , + ReferenceType varchar(255) NULL , + OldReference integer NULL , + NewReference integer NULL , + Data varchar(255) NULL , + + Creator integer NULL , + Created DATETIME NULL + +) ; +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +--- }}} + +--- {{{ Scrips + +CREATE TABLE Scrips ( + id INTEGER PRIMARY KEY , + Description varchar(255), + ScripCondition integer NULL , + ScripAction integer NULL , + ConditionRules text NULL , + ActionRules text NULL , + CustomIsApplicableCode text NULL , + CustomPrepareCode text NULL , + CustomCommitCode text NULL , + Stage varchar(32) NULL , + Queue integer NULL , + Template integer NULL , + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; + +--- }}} + +--- {{{ ACL +CREATE TABLE ACL ( + id INTEGER PRIMARY KEY , + PrincipalType varchar(25) NOT NULL, + + PrincipalId INTEGER, + RightName varchar(25) NOT NULL , + ObjectType varchar(25) NOT NULL , + ObjectId INTEGER default 0, + DelegatedBy integer NOT NULL default 0, + DelegatedFrom integer NOT NULL default 0 + +) ; + + +--- }}} + +--- {{{ GroupMembers + +CREATE TABLE GroupMembers ( + id INTEGER PRIMARY KEY , + GroupId integer NULL, + MemberId integer NULL + +) ; + +--- }}} + +--- {{{ CachedGroupMembers + +create table CachedGroupMembers ( + id integer primary key , + GroupId int, + MemberId int, + Via int, + ImmediateParentId int, + Disabled int2 NOT NULL DEFAULT 0 # if this cached group member is a member of this group by way of a disabled + # group or this group is disabled, this will be set to 1 + # this allows us to not find members of disabled subgroups when listing off + # group members recursively. + # Also, this allows us to have the ACL system elide members of disabled groups + + +) ; + +--- }}} + +--- {{{ Users + +CREATE TABLE Users ( + id INTEGER , + Name varchar(200) NOT NULL , + Password varchar(40) NULL , + Comments blob NULL , + Signature blob NULL , + EmailAddress varchar(120) NULL , + FreeformContactInfo blob NULL , + Organization varchar(200) NULL , + RealName varchar(120) NULL , + NickName varchar(16) NULL , + Lang varchar(16) NULL , + EmailEncoding varchar(16) NULL , + WebEncoding varchar(16) NULL , + ExternalContactInfoId varchar(100) NULL , + ContactInfoSystem varchar(30) NULL , + ExternalAuthId varchar(100) NULL , + AuthSystem varchar(30) NULL , + Gecos varchar(16) NULL , + HomePhone varchar(30) NULL , + WorkPhone varchar(30) NULL , + MobilePhone varchar(30) NULL , + PagerPhone varchar(30) NULL , + Address1 varchar(200) NULL , + Address2 varchar(200) NULL , + City varchar(100) NULL , + State varchar(100) NULL , + Zip varchar(16) NULL , + Country varchar(50) NULL , + Timezone char(50) NULL , + PGPKey text NULL, + + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; + + +CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users2 ON Users (Name); +CREATE INDEX Users3 ON Users (id, EmailAddress); +CREATE INDEX Users4 ON Users (EmailAddress); + + +--- }}} + +--- {{{ Tickets + +CREATE TABLE Tickets ( + id INTEGER PRIMARY KEY , + EffectiveId integer NULL , + Queue integer NULL , + Type varchar(16) NULL , + IssueStatement integer NULL , + Resolution integer NULL , + Owner integer NULL , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NULL , + FinalPriority integer NULL , + Priority integer NULL , + TimeEstimated integer NULL , + TimeWorked integer NULL , + Status varchar(10) NULL , + TimeLeft integer NULL , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + + + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL , + Creator integer NULL , + Created DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 + +) ; + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets3 ON Tickets (EffectiveId) ; +CREATE INDEX Tickets4 ON Tickets (id, Status) ; +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ; + +--- }}} + +--- {{{ ScripActions + +CREATE TABLE ScripActions ( + id INTEGER PRIMARY KEY , + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; + +--- }}} + +--- {{{ Templates + +CREATE TABLE Templates ( + id INTEGER PRIMARY KEY , + Queue integer NOT NULL DEFAULT 0 , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + Type varchar(16) NULL , + Language varchar(16) NULL , + TranslationOf integer NULL , + Content blob NULL , + LastUpdated DATETIME NULL , + LastUpdatedBy integer NULL , + Creator integer NULL , + Created DATETIME NULL + +) ; + +--- }}} + + + +# {{{ ObjectCustomFieldValues + +CREATE TABLE ObjectCustomFieldValues ( + id INTEGER NOT NULL , + CustomField int NOT NULL , + ObjectType varchar(255) NOT NULL, # Final target of the Object + ObjectId int NOT NULL , # New -- Replaces Ticket + SortOrder integer NOT NULL DEFAULT 0 , + + Content varchar(255) NULL , + LargeContent LONGTEXT NULL, # New -- to hold 255+ strings + ContentType varchar(80) NULL, # New -- only text/* gets searched + ContentEncoding varchar(80) NULL , # New -- for binary Content + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) ; + +CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content); +CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); + +# }}} + +# {{{ CustomFields + +CREATE TABLE CustomFields ( + id INTEGER NOT NULL , + Name varchar(200) NULL , + Type varchar(200) NULL , # Changed -- 'Single' and 'Multiple' is moved out + MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0) + Pattern varchar(65536) NULL , # New -- Must validate against this + Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + LookupType varchar(255) NOT NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ ObjectCustomFields + +CREATE TABLE ObjectCustomFields ( + id INTEGER NOT NULL , + CustomField int NOT NULL , + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ CustomFieldValues + +CREATE TABLE CustomFieldValues ( + id INTEGER NOT NULL , + CustomField int NOT NULL , + Name varchar(200) NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +# }}} + +--- {{{ Attributes +CREATE TABLE Attributes ( + id INTEGER PRIMARY KEY , + Name varchar(255) NOT NULL , + Description varchar(255) NULL , + Content LONGTEXT NULL , + ContentType varchar(16), + ObjectType varchar(25) NOT NULL , + ObjectId INTEGER default 0, + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +--- }}} + diff --git a/rt/etc/schema.Sybase b/rt/etc/schema.Sybase new file mode 100644 index 000000000..67a411d13 --- /dev/null +++ b/rt/etc/schema.Sybase @@ -0,0 +1,444 @@ +# {{{ Attachments + +CREATE TABLE rt3.Attachments ( + id numeric(38,0) identity, + TransactionId integer NOT NULL , + Parent integer NOT NULL , + MessageId varchar(160) NULL , + Subject varchar(255) NULL , + Filename varchar(255) NULL , + ContentType varchar(80) NULL , + ContentEncoding varchar(80) NULL , + Content TEXT NULL , + Headers TEXT NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX Attachments1 ON Attachments (Parent) ; +CREATE INDEX Attachments2 ON Attachments (TransactionId) ; +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; +# }}} + +# {{{ Queues +CREATE TABLE rt3.Queues ( + id numeric(38,0) identity, + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + CorrespondAddress varchar(120) NULL , + CommentAddress varchar(120) NULL , + InitialPriority integer NOT NULL , + FinalPriority integer NOT NULL , + DefaultDueIn integer NOT NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + Disabled numeric(1) NOT NULL , + PRIMARY KEY (id) +) ; +CREATE UNIQUE INDEX Queues1 ON Queues (Name) ; +CREATE INDEX Queues2 ON Queues (Disabled) ; + +# }}} + +# {{{ Links + +CREATE TABLE rt3.Links ( + id numeric(38,0) identity, + Base varchar(240) NULL , + Target varchar(240) NULL , + Type varchar(20) NOT NULL , + LocalTarget integer NOT NULL , + LocalBase integer NOT NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ; +CREATE INDEX Links2 ON Links (Base, Type) ; +CREATE INDEX Links3 ON Links (Target, Type) ; +CREATE INDEX Links4 ON Links(Type,LocalBase); + +# }}} + +# {{{ Principals + +CREATE TABLE rt3.Principals ( + id numeric(38,0) identity, + PrincipalType VARCHAR(16) not null, + ObjectId integer, Disabled numeric(1) NOT NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX Principals2 ON Principals (ObjectId); + +# }}} + +# {{{ Groups + +CREATE TABLE rt3.Groups ( + id numeric(38,0) identity, + Name varchar(200) NULL , + Description varchar(255) NULL , + Domain varchar(64), + Type varchar(64), + Instance integer, + PRIMARY KEY (id) +) ; + +CREATE INDEX Groups1 ON Groups (Domain,Instance,Type,id); +CREATE INDEX Groups2 On Groups (Type, Instance, Domain); + +# }}} + +# {{{ ScripConditions + +CREATE TABLE rt3.ScripConditions ( + id numeric(38,0) identity, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + ApplicableTransTypes varchar(60) NULL , + + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ Transactions +CREATE TABLE rt3.Transactions ( + id numeric(38,0) identity, + EffectiveTicket integer NOT NULL , + Ticket integer NOT NULL , + TimeTaken integer NOT NULL , + Type varchar(20) NULL , + Field varchar(40) NULL , + OldValue varchar(255) NULL , + NewValue varchar(255) NULL , + Data varchar(255) NULL , + + Creator integer NOT NULL , + Created DATETIME NULL , + PRIMARY KEY (id) +) ; +CREATE INDEX Transactions1 ON Transactions (Ticket); +CREATE INDEX Transactions2 ON Transactions (EffectiveTicket); + +# }}} + +# {{{ Scrips + +CREATE TABLE rt3.Scrips ( + id numeric(38,0) identity, + Description varchar(255), + ScripCondition integer NOT NULL , + ScripAction integer NOT NULL , + ConditionRules text NULL , + ActionRules text NULL , + CustomIsApplicableCode text NULL , + CustomPrepareCode text NULL , + CustomCommitCode text NULL , + Stage varchar(32) NULL , + Queue integer NOT NULL , + Template integer NOT NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ ACL +CREATE TABLE rt3.ACL ( + id numeric(38,0) identity, + PrincipalType varchar(25) NOT NULL, #"User" "Group", "Owner", "Cc" "AdminCc", "Requestor", "Requestor" + + PrincipalId integer NOT NULL , #Foreign key to principals + RightName varchar(25) NOT NULL , + ObjectType varchar(25) NOT NULL , + ObjectId integer NOT NULL , + DelegatedBy integer NOT NULL , #foreign key to principals with a userid + DelegatedFrom integer NOT NULL , #foreign key to ACL + PRIMARY KEY (id) +) ; + +CREATE INDEX ACL1 on ACL(RightName, ObjectType, ObjectId,PrincipalType,PrincipalId); + +# }}} + +# {{{ GroupMembers + +CREATE TABLE rt3.GroupMembers ( + id numeric(38,0) identity, + GroupId integer NOT NULL , + MemberId integer NOT NULL , #Foreign key to Principals + PRIMARY KEY (id) +) ; +CREATE UNIQUE INDEX GroupMembers1 on GroupMembers (GroupId, MemberId); + + +# }}} + +# {{{ GroupMembersCache + +CREATE TABLE rt3.CachedGroupMembers ( + id numeric(38,0) identity, + GroupId int, # foreign key to Principals + MemberId int, # foreign key to Principals + Via int, #foreign key to CachedGroupMembers. (may point to $self->id) + ImmediateParentId int, #foreign key to prinicpals. + # this points to the group that the member is + # a member of, for ease of deletes. + Disabled numeric(1) NOT NULL , # if this cached group member is a member of this group by way of a disabled + # group or this group is disabled, this will be set to 1 + # this allows us to not find members of disabled subgroups when listing off + # group members recursively. + # Also, this allows us to have the ACL system elide members of disabled groups + PRIMARY KEY (id) +) ; + +CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled); +CREATE INDEX GrouMem on CachedGroupMembers (GroupId,MemberId); + +# }}} + +# {{{ Users + +CREATE TABLE rt3.Users ( + id numeric(38,0) identity, + Name varchar(200) NOT NULL , + Password varchar(40) NULL , + Comments text NULL , + Signature text NULL , + EmailAddress varchar(120) NULL , + FreeformContactInfo text NULL , + Organization varchar(200) NULL , + RealName varchar(120) NULL , + NickName varchar(16) NULL , + Lang varchar(16) NULL , + EmailEncoding varchar(16) NULL , + WebEncoding varchar(16) NULL , + ExternalContactInfoId varchar(100) NULL , + ContactInfoSystem varchar(30) NULL , + ExternalAuthId varchar(100) NULL , + AuthSystem varchar(30) NULL , + Gecos varchar(16) NULL , + HomePhone varchar(30) NULL , + WorkPhone varchar(30) NULL , + MobilePhone varchar(30) NULL , + PagerPhone varchar(30) NULL , + Address1 varchar(200) NULL , + Address2 varchar(200) NULL , + City varchar(100) NULL , + State varchar(100) NULL , + Zip varchar(16) NULL , + Country varchar(50) NULL , + Timezone varchar(50) NULL , + PGPKey text NULL, + + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + + +CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users2 ON Users (Name); +CREATE INDEX Users3 ON Users (id, EmailAddress); +CREATE INDEX Users4 ON Users (EmailAddress); + + +# }}} + +# {{{ Tickets + +CREATE TABLE rt3.Tickets ( + id numeric(38,0) identity, + EffectiveId integer NOT NULL , + Queue integer NOT NULL , + Type varchar(16) NULL , + IssueStatement integer NOT NULL , + Resolution integer NOT NULL , + Owner integer NOT NULL , + Subject varchar(200) NULL, + InitialPriority integer NOT NULL , + FinalPriority integer NOT NULL , + Priority integer NOT NULL , + TimeEstimated integer NOT NULL , + TimeWorked integer NOT NULL , + Status varchar(10) NULL , + TimeLeft integer NOT NULL , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + + + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + Disabled numeric(1) NOT NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets3 ON Tickets (EffectiveId) ; +CREATE INDEX Tickets4 ON Tickets (id, Status) ; +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ; +CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type) ; + +# }}} + +# {{{ ScripActions + +CREATE TABLE rt3.ScripActions ( + id numeric(38,0) identity, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ Templates + +CREATE TABLE rt3.Templates ( + id numeric(38,0) identity, + Queue integer NOT NULL , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + Type varchar(16) NULL , + Language varchar(16) NULL , + TranslationOf integer NOT NULL , + Content text NULL , + LastUpdated DATETIME NULL , + LastUpdatedBy integer NOT NULL , + Creator integer NOT NULL , + Created DATETIME NULL , + PRIMARY KEY (id) +) ; + +# }}} + +# {{{ TicketCustomFieldValues + +CREATE TABLE rt3.TicketCustomFieldValues ( + id numeric(38,0) identity, + Ticket int NOT NULL , + CustomField int NOT NULL , + Content varchar(255) NULL , + + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX TicketCustomFieldValues1 ON TicketCustomFieldValues (CustomField,Ticket,Content); +CREATE INDEX TicketCustomFieldValues2 ON TicketCustomFieldValues (CustomField,Ticket); + +# }}} + +# {{{ CustomFields + +CREATE TABLE rt3.CustomFields ( + id numeric(38,0) identity, + Name varchar(200) NULL , + Type varchar(200) NULL , + Queue integer NOT NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL , + + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + Disabled numeric(1) NOT NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX CustomFields1 on CustomFields (Disabled, Queue); + + +# }}} + +# {{{ CustomFieldValues + +CREATE TABLE rt3.CustomFieldValues ( + id numeric(38,0) identity, + CustomField int NOT NULL , + Name varchar(200) NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL , + + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +# }}} + + +# {{{ Attributes + +CREATE TABLE rt3.Attributes ( + id numeric(38,0) identity, + Name varchar(255) NULL , + Description varchar(255) NULL , + Content text, + ContentType varchar(16), + ObjectType varchar(64), + ObjectId integer, # foreign key to anything + Creator integer NOT NULL , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) ; + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +# }}} + +# {{{ Sessions + +# sessions is used by Apache::Session to keep sessions in the database. +# We should have a reaper script somewhere. + +CREATE TABLE rt3.sessions ( + id char(32) NOT NULL, + a_session TEXT, + LastUpdated DATETIME, + PRIMARY KEY (id) +); + +# }}} diff --git a/rt/etc/schema.mysql-4.0 b/rt/etc/schema.mysql-4.0 new file mode 100755 index 000000000..c4299d472 --- /dev/null +++ b/rt/etc/schema.mysql-4.0 @@ -0,0 +1,464 @@ +# {{{ Attachments + +CREATE TABLE Attachments ( + id INTEGER NOT NULL AUTO_INCREMENT, + TransactionId integer NOT NULL , + Parent integer NOT NULL DEFAULT 0 , + MessageId varchar(160) NULL , + Subject varchar(255) NULL , + Filename varchar(255) NULL , + ContentType varchar(80) NULL , + ContentEncoding varchar(80) NULL , + Content LONGTEXT NULL , + Headers LONGTEXT NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Attachments2 ON Attachments (TransactionId) ; +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; +# }}} + +# {{{ Queues +CREATE TABLE Queues ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + CorrespondAddress varchar(120) NULL , + CommentAddress varchar(120) NULL , + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + DefaultDueIn integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB; +CREATE UNIQUE INDEX Queues1 ON Queues (Name) ; +CREATE INDEX Queues2 ON Queues (Disabled) ; + +# }}} + +# {{{ Links + +CREATE TABLE Links ( + id INTEGER NOT NULL AUTO_INCREMENT, + Base varchar(240) NULL , + Target varchar(240) NULL , + Type varchar(20) NOT NULL , + LocalTarget integer NOT NULL DEFAULT 0 , + LocalBase integer NOT NULL DEFAULT 0 , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Links2 ON Links (Base, Type) ; +CREATE INDEX Links3 ON Links (Target, Type) ; +CREATE INDEX Links4 ON Links (Type,LocalBase); + +# }}} + +# {{{ Principals + +CREATE TABLE Principals ( + id INTEGER AUTO_INCREMENT not null, + PrincipalType VARCHAR(16) not null, + ObjectId integer, # foreign key to Users or Groups, depending + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Principals2 ON Principals (ObjectId); + +# }}} + +# {{{ Groups + +CREATE TABLE Groups ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + Domain varchar(64), + Type varchar(64), + Instance integer, + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Groups1 ON Groups (Domain,Instance,Type,id); +CREATE INDEX Groups2 On Groups (Type, Instance); + +# }}} + +# {{{ ScripConditions + +CREATE TABLE ScripConditions ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + ApplicableTransTypes varchar(60) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ Transactions +CREATE TABLE Transactions ( + id INTEGER NOT NULL AUTO_INCREMENT, + ObjectType varchar(64) NOT NULL, + ObjectId integer NOT NULL DEFAULT 0 , + TimeTaken integer NOT NULL DEFAULT 0 , + Type varchar(20) NULL , + Field varchar(40) NULL , + OldValue varchar(255) NULL , + NewValue varchar(255) NULL , + ReferenceType varchar(255) NULL, + OldReference integer NULL , + NewReference integer NULL , + Data varchar(255) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +# }}} + +# {{{ Scrips + +CREATE TABLE Scrips ( + id INTEGER NOT NULL AUTO_INCREMENT, + Description varchar(255), + ScripCondition integer NOT NULL DEFAULT 0 , + ScripAction integer NOT NULL DEFAULT 0 , + ConditionRules text NULL , + ActionRules text NULL , + CustomIsApplicableCode text NULL , + CustomPrepareCode text NULL , + CustomCommitCode text NULL , + Stage varchar(32) NULL , + Queue integer NOT NULL DEFAULT 0 , + Template integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ ACL +CREATE TABLE ACL ( + id INTEGER NOT NULL AUTO_INCREMENT, + PrincipalType varchar(25) NOT NULL, #"User" "Group", "Owner", "Cc" "AdminCc", "Requestor", "Requestor" + + PrincipalId integer NOT NULL , #Foreign key to principals + RightName varchar(25) NOT NULL , + ObjectType varchar(25) NOT NULL , + ObjectId integer NOT NULL default 0, + DelegatedBy integer NOT NULL default 0, #foreign key to principals with a userid + DelegatedFrom integer NOT NULL default 0, #foreign key to ACL + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX ACL1 on ACL(RightName, ObjectType, ObjectId,PrincipalType,PrincipalId); + +# }}} + +# {{{ GroupMembers + +CREATE TABLE GroupMembers ( + id INTEGER NOT NULL AUTO_INCREMENT, + GroupId integer NOT NULL DEFAULT 0, + MemberId integer NOT NULL DEFAULT 0, #Foreign key to Principals + PRIMARY KEY (id) +) TYPE=InnoDB; +CREATE UNIQUE INDEX GroupMembers1 on GroupMembers (GroupId, MemberId); + + +# }}} + +# {{{ GroupMembersCache + +create table CachedGroupMembers ( + id int auto_increment, + GroupId int, # foreign key to Principals + MemberId int, # foreign key to Principals + Via int, #foreign key to CachedGroupMembers. (may point to $self->id) + ImmediateParentId int, #foreign key to prinicpals. + # this points to the group that the member is + # a member of, for ease of deletes. + Disabled int2 NOT NULL DEFAULT 0 , # if this cached group member is a member of this group by way of a disabled + # group or this group is disabled, this will be set to 1 + # this allows us to not find members of disabled subgroups when listing off + # group members recursively. + # Also, this allows us to have the ACL system elide members of disabled groups + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled); +CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId); + +# }}} + +# {{{ Users + +CREATE TABLE Users ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NOT NULL , + Password varchar(40) NULL , + Comments blob NULL , + Signature blob NULL , + EmailAddress varchar(120) NULL , + FreeformContactInfo blob NULL , + Organization varchar(200) NULL , + RealName varchar(120) NULL , + NickName varchar(16) NULL , + Lang varchar(16) NULL , + EmailEncoding varchar(16) NULL , + WebEncoding varchar(16) NULL , + ExternalContactInfoId varchar(100) NULL , + ContactInfoSystem varchar(30) NULL , + ExternalAuthId varchar(100) NULL , + AuthSystem varchar(30) NULL , + Gecos varchar(16) NULL , + HomePhone varchar(30) NULL , + WorkPhone varchar(30) NULL , + MobilePhone varchar(30) NULL , + PagerPhone varchar(30) NULL , + Address1 varchar(200) NULL , + Address2 varchar(200) NULL , + City varchar(100) NULL , + State varchar(100) NULL , + Zip varchar(16) NULL , + Country varchar(50) NULL , + Timezone varchar(50) NULL , + PGPKey text NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + + +CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users4 ON Users (EmailAddress); + + +# }}} + +# {{{ Tickets + +CREATE TABLE Tickets ( + id INTEGER NOT NULL AUTO_INCREMENT, + EffectiveId integer NOT NULL DEFAULT 0 , + Queue integer NOT NULL DEFAULT 0 , + Type varchar(16) NULL , + IssueStatement integer NOT NULL DEFAULT 0 , + Resolution integer NOT NULL DEFAULT 0 , + Owner integer NOT NULL DEFAULT 0 , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + Priority integer NOT NULL DEFAULT 0 , + TimeEstimated integer NOT NULL DEFAULT 0 , + TimeWorked integer NOT NULL DEFAULT 0 , + Status varchar(10) NULL , + TimeLeft integer NOT NULL DEFAULT 0 , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + + + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type) ; + +# }}} + +# {{{ ScripActions + +CREATE TABLE ScripActions ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) NULL , + Argument varchar(255) NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ Templates + +CREATE TABLE Templates ( + id INTEGER NOT NULL AUTO_INCREMENT, + Queue integer NOT NULL DEFAULT 0 , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + Type varchar(16) NULL , + Language varchar(16) NULL , + TranslationOf integer NOT NULL DEFAULT 0 , + Content blob NULL , + LastUpdated DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ ObjectCustomFieldValues + +CREATE TABLE ObjectCustomFieldValues ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + ObjectType varchar(255) NOT NULL, # Final target of the Object + ObjectId int NOT NULL , # New -- Replaces Ticket + SortOrder integer NOT NULL DEFAULT 0 , # New -- ordering for multiple values + + Content varchar(255) NULL , + LargeContent LONGTEXT NULL, # New -- to hold 255+ strings + ContentType varchar(80) NULL, # New -- only text/* gets searched + ContentEncoding varchar(80) NULL , # New -- for binary Content + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , # New -- whether the value was current + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content); +CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); + +# }}} + +# {{{ CustomFields + +CREATE TABLE CustomFields ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Type varchar(200) NULL , # Changed -- 'Single' and 'Multiple' is moved out + MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0) + Pattern TEXT NULL , # New -- Must validate against this + Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + LookupType varchar(255) NOT NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ ObjectCustomFields + +CREATE TABLE ObjectCustomFields ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +# }}} + +# {{{ CustomFieldValues + +CREATE TABLE CustomFieldValues ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + Name varchar(200) NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +# }}} + + +# {{{ Attributes + +CREATE TABLE Attributes ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(255) NULL , + Description varchar(255) NULL , + Content text, + ContentType varchar(16), + ObjectType varchar(64), + ObjectId integer, # foreign key to anything + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +# }}} + +# {{{ Sessions + +# sessions is used by Apache::Session to keep sessions in the database. +# We should have a reaper script somewhere. + +CREATE TABLE sessions ( + id char(32) NOT NULL, + a_session LONGTEXT, + LastUpdated TIMESTAMP, + PRIMARY KEY (id) +); + +# }}} diff --git a/rt/etc/schema.mysql-4.1 b/rt/etc/schema.mysql-4.1 new file mode 100755 index 000000000..172e477c1 --- /dev/null +++ b/rt/etc/schema.mysql-4.1 @@ -0,0 +1,466 @@ +# {{{ Attachments + +CREATE TABLE Attachments ( + id INTEGER NOT NULL AUTO_INCREMENT, + TransactionId integer NOT NULL , + Parent integer NOT NULL DEFAULT 0 , + MessageId varchar(160) CHARACTER SET ascii NULL , + Subject varchar(255) NULL , + Filename varchar(255) NULL , + ContentType varchar(80) CHARACTER SET ascii NULL , + ContentEncoding varchar(80) CHARACTER SET ascii NULL , + Content LONGBLOB NULL , + Headers LONGTEXT NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX Attachments2 ON Attachments (TransactionId) ; +CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; +# }}} + +# {{{ Queues +CREATE TABLE Queues ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + CorrespondAddress varchar(120) CHARACTER SET ascii NULL, + CommentAddress varchar(120) CHARACTER SET ascii NULL, + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + DefaultDueIn integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE UNIQUE INDEX Queues1 ON Queues (Name) ; +CREATE INDEX Queues2 ON Queues (Disabled) ; + +# }}} + +# {{{ Links + +CREATE TABLE Links ( + id INTEGER NOT NULL AUTO_INCREMENT, + Base varchar(240) NULL, + Target varchar(240) NULL, + Type varchar(20) NOT NULL, + LocalTarget integer NOT NULL DEFAULT 0 , + LocalBase integer NOT NULL DEFAULT 0 , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET ascii; + +CREATE INDEX Links2 ON Links (Base, Type) ; +CREATE INDEX Links3 ON Links (Target, Type) ; +CREATE INDEX Links4 ON Links (Type,LocalBase); + +# }}} + +# {{{ Principals + +CREATE TABLE Principals ( + id INTEGER AUTO_INCREMENT not null, + PrincipalType VARCHAR(16) not null, + ObjectId integer, # foreign key to Users or Groups, depending + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET ascii; + +CREATE INDEX Principals2 ON Principals (ObjectId); + +# }}} + +# {{{ Groups + +CREATE TABLE Groups ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + Domain varchar(64) CHARACTER SET ascii NULL, + Type varchar(64) CHARACTER SET ascii NULL, + Instance integer, + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX Groups1 ON Groups (Domain,Instance,Type,id); +CREATE INDEX Groups2 On Groups (Type, Instance); + +# }}} + +# {{{ ScripConditions + +CREATE TABLE ScripConditions ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) CHARACTER SET ascii NULL, + Argument VARBINARY(255) NULL , + ApplicableTransTypes varchar(60) CHARACTER SET ascii NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ Transactions +CREATE TABLE Transactions ( + id INTEGER NOT NULL AUTO_INCREMENT, + ObjectType varchar(64) CHARACTER SET ascii NOT NULL, + ObjectId integer NOT NULL DEFAULT 0 , + TimeTaken integer NOT NULL DEFAULT 0 , + Type varchar(20) CHARACTER SET ascii NULL, + Field varchar(40) CHARACTER SET ascii NULL, + OldValue varchar(255) NULL , + NewValue varchar(255) NULL , + ReferenceType varchar(255) CHARACTER SET ascii NULL, + OldReference integer NULL , + NewReference integer NULL , + Data varchar(255) NULL , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +# }}} + +# {{{ Scrips + +CREATE TABLE Scrips ( + id INTEGER NOT NULL AUTO_INCREMENT, + Description varchar(255), + ScripCondition integer NOT NULL DEFAULT 0 , + ScripAction integer NOT NULL DEFAULT 0 , + ConditionRules text NULL , + ActionRules text NULL , + CustomIsApplicableCode text NULL , + CustomPrepareCode text NULL , + CustomCommitCode text NULL , + Stage varchar(32) CHARACTER SET ascii NULL , + Queue integer NOT NULL DEFAULT 0 , + Template integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ ACL +CREATE TABLE ACL ( + id INTEGER NOT NULL AUTO_INCREMENT, + PrincipalType varchar(25) CHARACTER SET ascii NOT NULL, #"User" "Group", "Owner", "Cc" "AdminCc", "Requestor" + + PrincipalId integer NOT NULL , #Foreign key to principals + RightName varchar(25) CHARACTER SET ascii NOT NULL, + ObjectType varchar(25) CHARACTER SET ascii NOT NULL, + ObjectId integer NOT NULL default 0, + DelegatedBy integer NOT NULL default 0, #foreign key to principals with a userid + DelegatedFrom integer NOT NULL default 0, #foreign key to ACL + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX ACL1 on ACL(RightName, ObjectType, ObjectId,PrincipalType,PrincipalId); + +# }}} + +# {{{ GroupMembers + +CREATE TABLE GroupMembers ( + id INTEGER NOT NULL AUTO_INCREMENT, + GroupId integer NOT NULL DEFAULT 0, + MemberId integer NOT NULL DEFAULT 0, #Foreign key to Principals + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; +CREATE UNIQUE INDEX GroupMembers1 on GroupMembers (GroupId, MemberId); + + +# }}} + +# {{{ GroupMembersCache + +create table CachedGroupMembers ( + id int auto_increment, + GroupId int, # foreign key to Principals + MemberId int, # foreign key to Principals + Via int, #foreign key to CachedGroupMembers. (may point to $self->id) + ImmediateParentId int, #foreign key to prinicpals. + # this points to the group that the member is + # a member of, for ease of deletes. + Disabled int2 NOT NULL DEFAULT 0 , # if this cached group member is a member of this group by way of a disabled + # group or this group is disabled, this will be set to 1 + # this allows us to not find members of disabled subgroups when listing off + # group members recursively. + # Also, this allows us to have the ACL system elide members of disabled groups + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled); +CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId); + +# }}} + +# {{{ Users + +CREATE TABLE Users ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NOT NULL , + Password VARBINARY(40) NULL , + Comments TEXT NULL , + Signature TEXT NULL , + EmailAddress varchar(120) NULL , + FreeformContactInfo TEXT NULL , + Organization varchar(200) NULL , + RealName varchar(120) NULL , + NickName varchar(16) NULL , + Lang varchar(16) NULL , + EmailEncoding varchar(16) NULL , + WebEncoding varchar(16) NULL , + ExternalContactInfoId varchar(100) NULL , + ContactInfoSystem varchar(30) NULL , + ExternalAuthId varchar(100) NULL , + AuthSystem varchar(30) NULL , + Gecos varchar(16) NULL , + HomePhone varchar(30) NULL , + WorkPhone varchar(30) NULL , + MobilePhone varchar(30) NULL , + PagerPhone varchar(30) NULL , + Address1 varchar(200) NULL , + Address2 varchar(200) NULL , + City varchar(100) NULL , + State varchar(100) NULL , + Zip varchar(16) NULL , + Country varchar(50) NULL , + Timezone varchar(50) NULL , + PGPKey text NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + + +CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users4 ON Users (EmailAddress); + + +# }}} + +# {{{ Tickets + +CREATE TABLE Tickets ( + id INTEGER NOT NULL AUTO_INCREMENT, + EffectiveId integer NOT NULL DEFAULT 0 , + Queue integer NOT NULL DEFAULT 0 , + Type varchar(16) CHARACTER SET ascii NULL , + IssueStatement integer NOT NULL DEFAULT 0 , + Resolution integer NOT NULL DEFAULT 0 , + Owner integer NOT NULL DEFAULT 0 , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NOT NULL DEFAULT 0 , + FinalPriority integer NOT NULL DEFAULT 0 , + Priority integer NOT NULL DEFAULT 0 , + TimeEstimated integer NOT NULL DEFAULT 0 , + TimeWorked integer NOT NULL DEFAULT 0 , + Status varchar(10) NULL , + TimeLeft integer NOT NULL DEFAULT 0 , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + + + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type) ; + +# }}} + +# {{{ ScripActions + +CREATE TABLE ScripActions ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Description varchar(255) NULL , + ExecModule varchar(60) CHARACTER SET ascii NULL, + Argument VARBINARY(255) NULL , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ Templates + +CREATE TABLE Templates ( + id INTEGER NOT NULL AUTO_INCREMENT, + Queue integer NOT NULL DEFAULT 0 , + Name varchar(200) NOT NULL , + Description varchar(255) NULL , + Type varchar(16) CHARACTER SET ascii NULL , + Language varchar(16) CHARACTER SET ascii NULL , + TranslationOf integer NOT NULL DEFAULT 0 , + Content TEXT NULL , + LastUpdated DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ ObjectCustomFieldValues + +CREATE TABLE ObjectCustomFieldValues ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + ObjectType varchar(255) CHARACTER SET ascii NOT NULL, # Final target of the Object + ObjectId int NOT NULL , # New -- Replaces Ticket + SortOrder integer NOT NULL DEFAULT 0 , # New -- ordering for multiple values + + Content varchar(255) NULL , + LargeContent LONGBLOB NULL, # New -- to hold 255+ strings + ContentType varchar(80) CHARACTER SET ascii NULL, # New -- only text/* gets searched + ContentEncoding varchar(80) CHARACTER SET ascii NULL , # New -- for binary Content + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , # New -- whether the value was current + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content); +CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); + +# }}} + +# {{{ CustomFields + +CREATE TABLE CustomFields ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(200) NULL , + Type varchar(200) CHARACTER SET ascii NULL , # Changed -- 'Single' and 'Multiple' is moved out + MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0) + Pattern TEXT NULL , # New -- Must validate against this + Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + LookupType varchar(255) CHARACTER SET ascii NOT NULL, + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ ObjectCustomFields + +CREATE TABLE ObjectCustomFields ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField integer NOT NULL , + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +# }}} + +# {{{ CustomFieldValues + +CREATE TABLE CustomFieldValues ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + Name varchar(200) NULL , + Description varchar(255) NULL , + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); + +# }}} + + +# {{{ Attributes + +CREATE TABLE Attributes ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(255) NULL , + Description varchar(255) NULL , + Content BLOB, + ContentType varchar(16) CHARACTER SET ascii, + ObjectType varchar(64) CHARACTER SET ascii, + ObjectId integer, # foreign key to anything + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB CHARACTER SET utf8; + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +# }}} + +# {{{ Sessions + +# sessions is used by Apache::Session to keep sessions in the database. +# We should have a reaper script somewhere. + +CREATE TABLE sessions ( + id char(32) NOT NULL, + a_session LONGBLOB, + LastUpdated TIMESTAMP, + PRIMARY KEY (id) +); + +# }}} diff --git a/rt/etc/upgrade/3.1.0/acl.Informix b/rt/etc/upgrade/3.1.0/acl.Informix new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/acl.Informix @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.1.0/acl.Oracle b/rt/etc/upgrade/3.1.0/acl.Oracle new file mode 100755 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/acl.Oracle @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.1.0/acl.Pg b/rt/etc/upgrade/3.1.0/acl.Pg new file mode 100755 index 000000000..9c8878260 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/acl.Pg @@ -0,0 +1,19 @@ +sub acl { + my $dbh = shift; + + my @acls; + + my @tables = qw ( + attributes_id_seq + attributes + ); + + foreach my $table (@tables) { + push @acls, + "GRANT SELECT, INSERT, UPDATE, DELETE ON $table to " + . RT->Config->Get('DatabaseUser') . ";"; + + } + return (@acls); +} +1; diff --git a/rt/etc/upgrade/3.1.0/acl.SQLite b/rt/etc/upgrade/3.1.0/acl.SQLite new file mode 100755 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/acl.SQLite @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.1.0/acl.mysql b/rt/etc/upgrade/3.1.0/acl.mysql new file mode 100755 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/acl.mysql @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.1.0/content b/rt/etc/upgrade/3.1.0/content new file mode 100644 index 000000000..3117dafc5 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/content @@ -0,0 +1,2 @@ +# nothing to do +1; diff --git a/rt/etc/upgrade/3.1.0/schema.Informix b/rt/etc/upgrade/3.1.0/schema.Informix new file mode 100644 index 000000000..722eb70b3 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/schema.Informix @@ -0,0 +1,17 @@ +CREATE TABLE Attributes ( + id SERIAL, + Name VARCHAR(255) DEFAULT '' NOT NULL, + Description VARCHAR(255) DEFAULT NULL, + Content BYTE, + ContentType VARCHAR(16), + ObjectType VARCHAR(25) NOT NULL, + ObjectId INTEGER DEFAULT 0 NOT NULL, + Creator INTEGER DEFAULT 0 NOT NULL, + Created DATETIME YEAR TO SECOND, + LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, + LastUpdated DATETIME YEAR TO SECOND, + PRIMARY KEY (id) +); + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); diff --git a/rt/etc/upgrade/3.1.0/schema.Oracle b/rt/etc/upgrade/3.1.0/schema.Oracle new file mode 100644 index 000000000..a8aae18b5 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/schema.Oracle @@ -0,0 +1,17 @@ +CREATE SEQUENCE ATTRIBUTES_seq; +CREATE TABLE Attributes ( + id NUMBER(11,0) PRIMARY KEY, + Name VARCHAR2(255) NOT NULL, + Description VARCHAR2(255), + Content CLOB, + ContentType VARCHAR(16), + ObjectType VARCHAR2(25) NOT NULL, + ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL, + Creator NUMBER(11,0) DEFAULT 0 NOT NULL, + Created DATE, + LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, + LastUpdated DATE +); + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); diff --git a/rt/etc/upgrade/3.1.0/schema.Pg b/rt/etc/upgrade/3.1.0/schema.Pg new file mode 100755 index 000000000..94c3fe70d --- /dev/null +++ b/rt/etc/upgrade/3.1.0/schema.Pg @@ -0,0 +1,25 @@ +-- {{{ Attributes + +CREATE SEQUENCE attributes_id_seq; + +CREATE TABLE Attributes ( + id INTEGER DEFAULT nextval('attributes_id_seq'), + Name varchar(255) NOT NULL , + Description varchar(255) NULL , + Content text, + ContentType varchar(16), + ObjectType varchar(64), + ObjectId integer, + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +-- }}} + diff --git a/rt/etc/upgrade/3.1.0/schema.SQLite b/rt/etc/upgrade/3.1.0/schema.SQLite new file mode 100644 index 000000000..1dd466fa7 --- /dev/null +++ b/rt/etc/upgrade/3.1.0/schema.SQLite @@ -0,0 +1,21 @@ +--- {{{ Attributes +CREATE TABLE Attributes ( + id INTEGER PRIMARY KEY , + Name varchar(255) NOT NULL , + Description varchar(255) NULL , + Content LONGTEXT NULL , + ContentType varchar(16), + ObjectType varchar(25) NOT NULL , + ObjectId INTEGER default 0, + Creator integer NULL , + Created DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL + +) ; + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +--- }}} + diff --git a/rt/etc/upgrade/3.1.0/schema.mysql b/rt/etc/upgrade/3.1.0/schema.mysql new file mode 100755 index 000000000..c4a345d3e --- /dev/null +++ b/rt/etc/upgrade/3.1.0/schema.mysql @@ -0,0 +1,21 @@ +# {{{ Attributes + +CREATE TABLE Attributes ( + id INTEGER NOT NULL AUTO_INCREMENT, + Name varchar(255) NULL , + Description varchar(255) NULL , + Content text, + ContentType varchar(16), + ObjectType varchar(64), + ObjectId integer, # foreign key to anything + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + +CREATE INDEX Attributes1 on Attributes(Name); +CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); + +# }}} diff --git a/rt/etc/upgrade/3.1.15/content b/rt/etc/upgrade/3.1.15/content new file mode 100644 index 000000000..d23125a0b --- /dev/null +++ b/rt/etc/upgrade/3.1.15/content @@ -0,0 +1,7 @@ +@Scrips = ( + { ScripCondition => 'On Owner Change', + ScripAction => 'Notify Owner', + Template => 'Transaction' }, +); + +1; diff --git a/rt/etc/upgrade/3.1.17/content b/rt/etc/upgrade/3.1.17/content new file mode 100644 index 000000000..1d648d82f --- /dev/null +++ b/rt/etc/upgrade/3.1.17/content @@ -0,0 +1,22 @@ +@ScripActions = ( + { Name => 'Notify Ccs as Comment', # loc + Description => 'Sends mail to the Ccs as a comment', # loc + ExecModule => 'NotifyAsComment', + Argument => 'Cc' }, + { Name => 'Notify Ccs', # loc + Description => 'Sends mail to the Ccs', # loc + ExecModule => 'Notify', + Argument => 'Cc' }, +); + + +@ScripConditions = ( + { + Name => 'On Priority Change', # loc + Description => 'Whenever a ticket\'s priority changes', # loc + ApplicableTransTypes => 'Set', + ExecModule => 'PriorityChange', + }, +); + +1; diff --git a/rt/etc/upgrade/3.3.0/acl.Informix b/rt/etc/upgrade/3.3.0/acl.Informix new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/acl.Informix @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.0/acl.Oracle b/rt/etc/upgrade/3.3.0/acl.Oracle new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/acl.Oracle @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.0/acl.Pg b/rt/etc/upgrade/3.3.0/acl.Pg new file mode 100644 index 000000000..bd2e36c48 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/acl.Pg @@ -0,0 +1,20 @@ +sub acl { + my $dbh = shift; + + my @acls; + + my @tables = qw ( + objectcustomfieldvalues + objectcustomfields_id_s + objectcustomfields + ); + + foreach my $table (@tables) { + push @acls, + "GRANT SELECT, INSERT, UPDATE, DELETE ON $table to " + . RT->Config->Get('DatabaseUser') . ";"; + + } + return (@acls); +} +1; diff --git a/rt/etc/upgrade/3.3.0/acl.SQLite b/rt/etc/upgrade/3.3.0/acl.SQLite new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/acl.SQLite @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.0/acl.mysql b/rt/etc/upgrade/3.3.0/acl.mysql new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/acl.mysql @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.0/content b/rt/etc/upgrade/3.3.0/content new file mode 100644 index 000000000..0afc6045c --- /dev/null +++ b/rt/etc/upgrade/3.3.0/content @@ -0,0 +1 @@ +1; diff --git a/rt/etc/upgrade/3.3.0/schema.Oracle b/rt/etc/upgrade/3.3.0/schema.Oracle new file mode 100644 index 000000000..f81feeb79 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/schema.Oracle @@ -0,0 +1,65 @@ +alter Table Transactions ADD ObjectType VARCHAR2(64); +UPDATE Transactions set ObjectType = 'RT::Ticket'; +ALTER TABLE Transactions modify ObjectType NOT NULL; +ALTER TABLE Transactions drop column EffectiveTicket; +ALTER TABLE Transactions ADD ReferenceType VARCHAR2(255) NULL; +ALTER TABLE Transactions ADD OldReference NUMBER(11,0) NULL; +ALTER TABLE Transactions ADD NewReference NUMBER(11,0) NULL; +DROP INDEX transactions1; +ALTER TABLE Transactions rename column Ticket to ObjectId; +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +ALTER TABLE TicketCustomFieldValues rename to ObjectCustomFieldValues; +ALTER TABLE ObjectCustomFieldValues rename column Ticket to ObjectId; +ALTER TABLE ObjectCustomFieldValues ADD ObjectType VARCHAR2(255); +UPDATE ObjectCustomFieldValues set ObjectType = 'RT::Ticket'; +ALTER TABLE ObjectCustomFieldValues MODIFY ObjectType NOT NULL; +ALTER TABLE ObjectCustomFieldValues ADD Disabled NUMBER(11,0); +ALTER TABLE ObjectCustomFieldValues MODIFY Disabled default 0; +UPDATE ObjectCustomFieldValues SET Disabled = 0; +ALTER TABLE ObjectCustomFieldValues MODIFY Disabled NOT NULL; +ALTER TABLE ObjectCustomFieldValues ADD LargeContent CLOB NULL; +ALTER TABLE ObjectCustomFieldValues ADD ContentType VARCHAR2(80) NULL; +ALTER TABLE ObjectCustomFieldValues ADD ContentEncoding VARCHAR2(80) NULL; +ALTER TABLE ObjectCustomFieldValues ADD SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL; + + + +CREATE INDEX ObjectCustomFieldValues1 on ObjectCustomFieldValues (CustomField,ObjectType,ObjectId,Content); +CREATE INDEX ObjectCustomFieldValues2 on ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); + + + +CREATE SEQUENCE OBJECTCUSTOMFIELDS_seq; +CREATE TABLE ObjectCustomFields ( + id NUMBER(11,0) + CONSTRAINT ObjectCustomFields_Key PRIMARY KEY, + CustomField NUMBER(11,0) NOT NULL, + ObjectId NUMBER(11,0) NOT NULL, + SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, + Creator NUMBER(11,0) DEFAULT 0 NOT NULL, + Created DATE, + LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, + LastUpdated DATE +); + + +INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT objectcustomfields_seq.nextval, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields; + +ALTER TABLE CustomFields ADD LookupType VARCHAR2(255); +ALTER TABLE CustomFields ADD Repeated NUMBER(11,0); +ALTER TABLE CustomFields ADD Pattern VARCHAR2(255) NULL; +ALTER TABLE CustomFields ADD MaxValues NUMBER(11,0); + +UPDATE CustomFields SET MaxValues = 0 WHERE Type LIKE '%Multiple'; +UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single'; +UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%'; +UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%'; +UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket'; +ALTER TABLE CustomFields MODIFY LookupType NOT NULL; +UPDATE CustomFields Set Repeated = 0; +ALTER TABLE CustomFields MODIFY Repeated DEFAULT 0; +ALTER TABLE CustomFields MODIFY Repeated NOT NULL; +ALTER TABLE CustomFields drop column Queue; + + diff --git a/rt/etc/upgrade/3.3.0/schema.Pg b/rt/etc/upgrade/3.3.0/schema.Pg new file mode 100644 index 000000000..427eae798 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/schema.Pg @@ -0,0 +1,74 @@ +alter Table Transactions ADD Column ObjectType varchar(64); +update Transactions set ObjectType = 'RT::Ticket'; +ALTER TABLE Transactions ALTER COLUMN ObjectType SET NOT NULL; +alter table Transactions drop column EffectiveTicket; +alter table Transactions add column ReferenceType varchar(255) NULL; +alter table Transactions add column OldReference integer NULL; +alter table Transactions add column NewReference integer NULL; +drop index transactions1; +alter table Transactions rename column Ticket to ObjectId; + + +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +alter table TicketCustomFieldValues rename to ObjectCustomFieldValues; + +alter table ObjectCustomFieldValues rename column Ticket to ObjectId; + +alter table objectcustomfieldvalues add column ObjectType varchar(255); + +update objectcustomfieldvalues set ObjectType = 'RT::Ticket'; + +ALTER TABLE objectcustomfieldvalues ALTER COLUMN ObjectType SET NOT NULL; + +alter table objectcustomfieldvalues add column Current int; + +alter table objectcustomfieldvalues alter column Current SET default 1; + +UPDATE objectcustomfieldvalues SET Current = 1; + +alter table objectcustomfieldvalues add column LargeContent TEXT NULL; + +alter table objectcustomfieldvalues add column ContentType varchar(80) NULL; + +alter table objectcustomfieldvalues add column ContentEncoding varchar(80) NULL; + +create index ObjectCustomFieldValues1 on objectcustomfieldvalues (CustomField,ObjectType,ObjectId,Content); + +create index ObjectCustomFieldValues2 on objectcustomfieldvalues (CustomField,ObjectType,ObjectId); + + +CREATE SEQUENCE objectcustomfields_id_s; + +CREATE TABLE ObjectCustomFields ( + id INTEGER DEFAULT nextval('objectcustomfields_id_s'), + CustomField integer NOT NULL, + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created TIMESTAMP NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated TIMESTAMP NULL , + PRIMARY KEY (id) + +); + + +INSERT into ObjectCustomFields (CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields; + +alter table CustomFields add column LookupType varchar(255); +alter table CustomFields add column Repeated int2; +alter table CustomFields add column Pattern varchar(255) NULL; +alter table CustomFields add column MaxValues integer; + +UPDATE CustomFields SET MaxValues = 0 WHERE Type LIKE '%Multiple'; +UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single'; +UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%'; +UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%'; +UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket'; +ALTER TABLE CustomFields ALTER COLUMN LookupType SET NOT NULL; +UPDATE CustomFields Set Repeated = 0; +ALTER TABLE CustomFields ALTER COLUMN Repeated SET DEFAULT 0; +ALTER TABLE CustomFields ALTER COLUMN Repeated SET NOT NULL; +alter table CustomFields drop column Queue; diff --git a/rt/etc/upgrade/3.3.0/schema.mysql b/rt/etc/upgrade/3.3.0/schema.mysql new file mode 100644 index 000000000..0e33a2819 --- /dev/null +++ b/rt/etc/upgrade/3.3.0/schema.mysql @@ -0,0 +1,65 @@ +alter Table Transactions ADD Column (ObjectType varchar(64) not null); +update Transactions set ObjectType = 'RT::Ticket'; +alter table Transactions drop column EffectiveTicket; +alter table Transactions add column ReferenceType varchar(255) NULL; +alter table Transactions add column OldReference integer NULL; +alter table Transactions add column NewReference integer NULL; +alter table Transactions drop index transactions1; +alter table Transactions change Ticket ObjectId integer NOT NULL DEFAULT 0 ; + +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); + +alter table TicketCustomFieldValues rename ObjectCustomFieldValues; + +alter table ObjectCustomFieldValues change Ticket ObjectId integer NOT NULL DEFAULT 0 ; + +alter table ObjectCustomFieldValues add column ObjectType varchar(255) not null; + +update ObjectCustomFieldValues set ObjectType = 'RT::Ticket'; + +alter table ObjectCustomFieldValues add column Current bool default 1; + +alter table ObjectCustomFieldValues add column LargeContent LONGTEXT NULL; + +alter table ObjectCustomFieldValues add column ContentType varchar(80) NULL; + +alter table ObjectCustomFieldValues add column ContentEncoding varchar(80) NULL; + +# These could fail if there's no such index and there's no "drop index if exists" syntax +#alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues1; +#alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues2; + +alter table ObjectCustomFieldValues add index ObjectCustomFieldValues1 (Content); + +alter table ObjectCustomFieldValues add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId); + + +CREATE TABLE ObjectCustomFields ( + id INTEGER NOT NULL AUTO_INCREMENT, + CustomField int NOT NULL , + ObjectId integer NOT NULL, + SortOrder integer NOT NULL DEFAULT 0 , + + Creator integer NOT NULL DEFAULT 0 , + Created DATETIME NULL , + LastUpdatedBy integer NOT NULL DEFAULT 0 , + LastUpdated DATETIME NULL , + PRIMARY KEY (id) +) TYPE=InnoDB; + + +INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT null, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields; + +alter table CustomFields add column LookupType varchar(255) NOT NULL; +alter table CustomFields add column Repeated int2 NOT NULL DEFAULT 0 ; +alter table CustomFields add column Pattern varchar(255) NULL; +alter table CustomFields add column MaxValues integer; +# See above +# alter table CustomFields drop index CustomFields1; + +UPDATE CustomFields SET MaxValues = 0 WHERE Type LIKE '%Multiple'; +UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single'; +UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%'; +UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%'; +UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket'; +alter table CustomFields drop column Queue; diff --git a/rt/etc/upgrade/3.3.11/acl.Oracle b/rt/etc/upgrade/3.3.11/acl.Oracle new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/acl.Oracle @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.11/acl.Pg b/rt/etc/upgrade/3.3.11/acl.Pg new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/acl.Pg @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.11/acl.SQLite b/rt/etc/upgrade/3.3.11/acl.SQLite new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/acl.SQLite @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.11/acl.mysql b/rt/etc/upgrade/3.3.11/acl.mysql new file mode 100644 index 000000000..73c16ae03 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/acl.mysql @@ -0,0 +1,4 @@ +sub acl { + return (); +} +1; diff --git a/rt/etc/upgrade/3.3.11/content b/rt/etc/upgrade/3.3.11/content new file mode 100644 index 000000000..0afc6045c --- /dev/null +++ b/rt/etc/upgrade/3.3.11/content @@ -0,0 +1 @@ +1; diff --git a/rt/etc/upgrade/3.3.11/schema.Oracle b/rt/etc/upgrade/3.3.11/schema.Oracle new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/rt/etc/upgrade/3.3.11/schema.Oracle diff --git a/rt/etc/upgrade/3.3.11/schema.Pg b/rt/etc/upgrade/3.3.11/schema.Pg new file mode 100644 index 000000000..6ab5d6581 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/schema.Pg @@ -0,0 +1,11 @@ +ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER; +UPDATE ObjectCustomFieldValues SET SortOrder = 0; +ALTER TABLE ObjectCustomFieldValues ALTER COLUMN SortOrder SET DEFAULT 0; +ALTER TABLE ObjectCustomFieldValues ALTER COLUMN SortOrder SET NOT NULL; +ALTER TABLE ObjectCustomFieldValues ADD COLUMN Disabled INTEGER; +UPDATE ObjectCustomFieldValues SET Disabled = 1 WHERE Current = 0; +UPDATE ObjectCustomFieldValues SET Disabled = 0 WHERE Current != 0; +ALTER TABLE ObjectCustomFieldValues ALTER COLUMN Disabled SET DEFAULT 0; +ALTER TABLE ObjectCustomFieldValues ALTER COLUMN Disabled SET NOT NULL; + +ALTER TABLE ObjectCustomFieldValues DROP COLUMN Current; diff --git a/rt/etc/upgrade/3.3.11/schema.SQLite b/rt/etc/upgrade/3.3.11/schema.SQLite new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/rt/etc/upgrade/3.3.11/schema.SQLite diff --git a/rt/etc/upgrade/3.3.11/schema.mysql b/rt/etc/upgrade/3.3.11/schema.mysql new file mode 100644 index 000000000..cc35d40f2 --- /dev/null +++ b/rt/etc/upgrade/3.3.11/schema.mysql @@ -0,0 +1,5 @@ +ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER NOT NULL DEFAULT 0; +ALTER TABLE ObjectCustomFieldValues ADD COLUMN Disabled int2 NOT NULL DEFAULT 0; + +UPDATE ObjectCustomFieldValues SET Disabled = 1 WHERE Current = 0; +ALTER TABLE ObjectCustomFieldValues DROP COLUMN Current; diff --git a/rt/etc/upgrade/3.5.1/content b/rt/etc/upgrade/3.5.1/content new file mode 100644 index 000000000..02d6a0cac --- /dev/null +++ b/rt/etc/upgrade/3.5.1/content @@ -0,0 +1,36 @@ +@Attributes = ( + { Name => 'Search - My Tickets', + Description => '[_1] highest priority tickets I own', + Content => + { Format => q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#', '<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject', Priority, QueueName, ExtendedStatus}, + Query => " Owner = '__CurrentUser__' AND ( Status = 'new' OR Status = 'open')", + OrderBy => 'Priority', + Order => 'DESC' }, + }, + { Name => 'Search - Unowned Tickets', + Description => '[_1] newest unowned tickets', + Content => + { Format => "'<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__id__</a>/TITLE:#', '<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__Subject__</a>/TITLE:Subject', QueueName, ExtendedStatus, CreatedRelative, '<A HREF=\"__WebPath__/Ticket/Display.html?Action=Take&id=__id__\">__loc(Take)__</a>/TITLE: ' ", + Query => " Owner = 'Nobody' AND ( Status = 'new' OR Status = 'open')", + OrderBy => 'Created', + Order => 'DESC' }, + }, + { Name => 'HomepageSettings', + Description => 'HomepageSettings', + Content => + { 'body' => + [ { type => 'system', name => 'My Tickets' }, + { type => 'system', name => 'Unowned Tickets' }, + { type => 'component', name => 'QuickCreate'}, + ], + 'summary' => + [ + { type => 'component', name => 'MyReminders' }, + { type => 'component', name => 'Quicksearch' }, + { type => 'component', name => 'RefreshHomepage' }, + ] + }, +} +); + +1; diff --git a/rt/etc/upgrade/3.7.1/content b/rt/etc/upgrade/3.7.1/content new file mode 100644 index 000000000..fdd506144 --- /dev/null +++ b/rt/etc/upgrade/3.7.1/content @@ -0,0 +1,14 @@ +@ScripConditions = ( + { Name => 'On Close', # loc + Description => 'Whenever a ticket is closed', # loc + ApplicableTransTypes => 'Status,Set', + ExecModule => 'CloseTicket', + }, + { Name => 'On Reopen', # loc + Description => 'Whenever a ticket is reopened', # loc + ApplicableTransTypes => 'Status,Set', + ExecModule => 'ReopenTicket', + }, +); + + diff --git a/rt/etc/upgrade/3.7.10/content b/rt/etc/upgrade/3.7.10/content new file mode 100644 index 000000000..d19f9e6fa --- /dev/null +++ b/rt/etc/upgrade/3.7.10/content @@ -0,0 +1,49 @@ + +@Templates = ( + { Queue => 0, + Name => "Error: public key", # loc + Description => + "Inform user that he has problems with public key and couldn't recieve encrypted content", # loc + Content => q{Subject: We have no your public key or it's wrong + +You received this message as we have no your public PGP key or we have a problem with your key. Inform the administrator about the problem. +} + }, + { Queue => 0, + Name => "Error to RT owner: public key", # loc + Description => + "Inform RT owner that user(s) have problems with public keys", # loc + Content => q{Subject: Some users have problems with public keys + +You received this message as RT has problems with public keys of the following user: +{ + foreach my $e ( @BadRecipients ) { + $OUT .= "* ". $e->{'Message'} ."\n"; + } +}} + }, + { Queue => 0, + Name => "Error: no private key", # loc + Description => + "Inform user that we received an encrypted email and we have no private keys to decrypt", # loc + Content => q{Subject: we received message we cannot decrypt + +You sent an encrypted message with subject '{ $Message->head->get('Subject') }', +but we have no private key it's encrypted to. + +Please, check that you encrypt messages with correct keys +or contact the system administrator.} + }, + { Queue => 0, + Name => "Error: bad GnuPG data", # loc + Description => + "Inform user that a message he sent has invalid GnuPG data", # loc + Content => q{Subject: We received a message we cannot handle + +You sent us a message that we cannot handle due to corrupted GnuPG signature or encrypted block. we get the following error(s): +{ foreach my $msg ( @Messages ) { + $OUT .= "* $msg\n"; + } +}} + }, +); diff --git a/rt/etc/upgrade/3.7.15/content b/rt/etc/upgrade/3.7.15/content new file mode 100644 index 000000000..9d97c356c --- /dev/null +++ b/rt/etc/upgrade/3.7.15/content @@ -0,0 +1,12 @@ + +@Templates = ( + { Queue => 0, + Name => "Forward", # loc + Description => "Heading of a forwarded message", # loc + Content => q{ + +This is forward of transaction #{ $Transaction->id } of a ticket #{ $Ticket->id } +} + }, +); + diff --git a/rt/etc/upgrade/3.7.19/content b/rt/etc/upgrade/3.7.19/content new file mode 100644 index 000000000..ac34ebeb5 --- /dev/null +++ b/rt/etc/upgrade/3.7.19/content @@ -0,0 +1,37 @@ + +{ use strict; +add_description_to_all_scrips(); + +sub add_description_to_all_scrips { + require RT::Scrips; + my $scrips = RT::Scrips->new( $RT::SystemUser ); + $scrips->Limit( FIELD => 'Description', OPERATOR => 'IS', VALUE => 'NULL' ); + $scrips->Limit( FIELD => 'Description', VALUE => '' ); + while ( my $scrip = $scrips->Next ) { + my $desc = $scrip->Description; + next if defined $desc && length $desc; + + $desc = gen_scrip_description( $scrip ); + + my ($status, $msg) = $scrip->SetDescription( $desc ); + unless ( $status ) { + print STDERR "Couldn't set description of a scrip: $msg"; + } else { + print "Added description to scrip #". $scrip->id ."\n"; + } + } +} + +sub gen_scrip_description { + my $scrip = shift; + my $condition = $scrip->ConditionObj->Name + || $scrip->ConditionObj->Description + || ('On Condition #'. $scrip->Condition); + my $action = $scrip->ActionObj->Name + || $scrip->ActionObj->Description + || ('Run Action #'. $scrip->Action); + return join ' ', $condition, $action; +} +} + +1; diff --git a/rt/etc/upgrade/3.7.3/schema.Oracle b/rt/etc/upgrade/3.7.3/schema.Oracle new file mode 100644 index 000000000..6136efae7 --- /dev/null +++ b/rt/etc/upgrade/3.7.3/schema.Oracle @@ -0,0 +1,5 @@ +alter table CustomFields add Pattern_TMP clob; +update CustomFields set Pattern_TMP = Pattern; +commit; +alter table CustomFields drop column Pattern; +alter table CustomFields rename column Pattern_TMP to Pattern; diff --git a/rt/etc/upgrade/3.7.3/schema.Pg b/rt/etc/upgrade/3.7.3/schema.Pg new file mode 100644 index 000000000..5d0312e92 --- /dev/null +++ b/rt/etc/upgrade/3.7.3/schema.Pg @@ -0,0 +1 @@ +ALTER TABLE customfields ALTER COLUMN pattern TYPE VARCHAR(65536); diff --git a/rt/etc/upgrade/3.7.3/schema.mysql b/rt/etc/upgrade/3.7.3/schema.mysql new file mode 100644 index 000000000..51c376d81 --- /dev/null +++ b/rt/etc/upgrade/3.7.3/schema.mysql @@ -0,0 +1 @@ +ALTER TABLE CustomFields CHANGE Pattern Pattern TEXT NULL; diff --git a/rt/etc/upgrade/3.7.81/schema.Oracle b/rt/etc/upgrade/3.7.81/schema.Oracle new file mode 100644 index 000000000..02da4ece9 --- /dev/null +++ b/rt/etc/upgrade/3.7.81/schema.Oracle @@ -0,0 +1,2 @@ +CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId); + diff --git a/rt/etc/upgrade/3.7.81/schema.mysql b/rt/etc/upgrade/3.7.81/schema.mysql new file mode 100644 index 000000000..02da4ece9 --- /dev/null +++ b/rt/etc/upgrade/3.7.81/schema.mysql @@ -0,0 +1,2 @@ +CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId); + diff --git a/rt/etc/upgrade/3.7.82/content b/rt/etc/upgrade/3.7.82/content new file mode 100644 index 000000000..a1c555f78 --- /dev/null +++ b/rt/etc/upgrade/3.7.82/content @@ -0,0 +1,13 @@ +@Attributes = ( + { Name => 'Search - Bookmarked Tickets', + Description => 'Bookmarked Tickets', #loc + Content => + { Format => q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#',} + . q{'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject',} + . q{Priority, QueueName, ExtendedStatus, Bookmark}, + Query => "__Bookmarks__", + OrderBy => 'LastUpdated', + Order => 'DESC' }, + }, +); + diff --git a/rt/etc/upgrade/3.7.85/content b/rt/etc/upgrade/3.7.85/content new file mode 100644 index 000000000..49ab2860f --- /dev/null +++ b/rt/etc/upgrade/3.7.85/content @@ -0,0 +1,11 @@ +@Templates = ( + + { Queue => '0', + Name => 'Email Digest', # loc + Description => 'Email template for periodic notification digests', # loc + Content => q[Subject: RT Email Digest + +{ $Argument } +], + }, +); diff --git a/rt/etc/upgrade/3.7.86/content b/rt/etc/upgrade/3.7.86/content new file mode 100644 index 000000000..da087ed75 --- /dev/null +++ b/rt/etc/upgrade/3.7.86/content @@ -0,0 +1,23 @@ +@Final = ( + sub { + $RT::Logger->debug("Adding search for bookmarked tickets to defaults"); + my $sys = RT::System->new($RT::SystemUser); + + my $attrs = RT::Attributes->new( $RT::SystemUser ); + $attrs->LimitToObject( $sys ); + my ($attr) = $attrs->Named( 'HomepageSettings' ); + unless ($attr) { + $RT::Logger->error("You have no global home page settings"); + return; + } + my $content = $attr->Content; + unshift @{ $content->{'body'} ||= [] }, + { type => 'system', name => 'Bookmarked Tickets' }; + + my ($status, $msg) = $attr->SetContent( $content ); + $RT::Logger->error($msg) unless $status; + + $RT::Logger->debug("done."); + return 1; + }, +); diff --git a/rt/etc/upgrade/3.7.87/content b/rt/etc/upgrade/3.7.87/content new file mode 100644 index 000000000..0c677c4a1 --- /dev/null +++ b/rt/etc/upgrade/3.7.87/content @@ -0,0 +1,28 @@ +@Templates = ( +{ + Queue => 0, + Name => "Error: Missing dashboard", # loc + Description => + "Inform user that a dashboard he subscribed to is missing", # loc + Content => q{Subject: [{RT->Config->Get('rtname')}] Missing dashboard! + +Greetings, + +You are subscribed to a dashboard that is currently missing. Most likely, the dashboard was deleted. + +RT will remove this subscription as it is no longer useful. Here's the information RT had about your subscription: + +DashboardID: { $SubscriptionObj->SubValue('DashboardId') } +Frequency: { $SubscriptionObj->SubValue('Frequency') } +Hour: { $SubscriptionObj->SubValue('Hour') } +{ + $SubscriptionObj->SubValue('Frequency') eq 'weekly' + ? "Day of week: " . $SubscriptionObj->SubValue('Dow') + : $SubscriptionObj->SubValue('Frequency') eq 'monthly' + ? "Day of month: " . $SubscriptionObj->SubValue('Dom') + : '' +} +} +}, +); + diff --git a/rt/etc/upgrade/3.8-branded-queues-extension b/rt/etc/upgrade/3.8-branded-queues-extension new file mode 100755 index 000000000..6a0ea48b6 --- /dev/null +++ b/rt/etc/upgrade/3.8-branded-queues-extension @@ -0,0 +1,95 @@ +#!/usr/bin/perl +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "local/lib"; +use lib "lib"; + + +use RT; +RT::LoadConfig(); +RT::Init(); + +use RT::Queues; + +my $queues = RT::Queues->new( $RT::SystemUser ); +$queues->UnLimit(); +while ( my $queue = $queues->Next ) { + print "Processing queue ". ($queue->Name || $queue->id) ."...\n"; + my $old_attr = $queue->FirstAttribute('BrandedSubjectTag'); + unless ( $old_attr ) { + print "\thas no old-style subject tag. skipping\n"; + next; + } + my $old_value = $old_attr->Content; + unless ( $old_value ) { + print "\thas empty old-style subject tag\n"; + } else { + my ($status, $msg) = $queue->SetSubjectTag( $old_value ); + unless ( $status ) { + print STDERR "\tERROR. Couldn't set tag: $msg\n"; + next; + } else { + print "\thave set new-style subject tag to '$old_value'\n"; + } + } + + my ($status, $msg) = $queue->DeleteAttribute('BrandedSubjectTag'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't delete old-style tag: $msg\n"; + next; + } else { + print "\tdeleted old-style tag entry\n"; + } + print "\tDONE\n"; +} + +exit 0; + diff --git a/rt/etc/upgrade/3.8-branded-queues-extension.in b/rt/etc/upgrade/3.8-branded-queues-extension.in new file mode 100755 index 000000000..2f07d6e60 --- /dev/null +++ b/rt/etc/upgrade/3.8-branded-queues-extension.in @@ -0,0 +1,95 @@ +#!@PERL@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "@LOCAL_LIB_PATH@"; +use lib "@RT_LIB_PATH@"; + + +use RT; +RT::LoadConfig(); +RT::Init(); + +use RT::Queues; + +my $queues = RT::Queues->new( $RT::SystemUser ); +$queues->UnLimit(); +while ( my $queue = $queues->Next ) { + print "Processing queue ". ($queue->Name || $queue->id) ."...\n"; + my $old_attr = $queue->FirstAttribute('BrandedSubjectTag'); + unless ( $old_attr ) { + print "\thas no old-style subject tag. skipping\n"; + next; + } + my $old_value = $old_attr->Content; + unless ( $old_value ) { + print "\thas empty old-style subject tag\n"; + } else { + my ($status, $msg) = $queue->SetSubjectTag( $old_value ); + unless ( $status ) { + print STDERR "\tERROR. Couldn't set tag: $msg\n"; + next; + } else { + print "\thave set new-style subject tag to '$old_value'\n"; + } + } + + my ($status, $msg) = $queue->DeleteAttribute('BrandedSubjectTag'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't delete old-style tag: $msg\n"; + next; + } else { + print "\tdeleted old-style tag entry\n"; + } + print "\tDONE\n"; +} + +exit 0; + diff --git a/rt/etc/upgrade/3.8-ical-extension b/rt/etc/upgrade/3.8-ical-extension new file mode 100755 index 000000000..9561b9735 --- /dev/null +++ b/rt/etc/upgrade/3.8-ical-extension @@ -0,0 +1,96 @@ +#!/usr/bin/perl +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "local/lib"; +use lib "lib"; + + +use RT; +RT::LoadConfig(); +RT::Init(); + +use RT::Attributes; +my $attrs = RT::Attributes->new( $RT::SystemUser ); +$attrs->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => 'RT::User'); +$attrs->Limit(FIELD => 'Name', OPERATOR=> '=', VALUE => 'ical-auth-token'); +while ( my $attr = $attrs->Next ) { + my $uid = $attr->ObjectId; + print "Processing auth token of user #". $uid ."...\n"; + + my $user = RT::User->new( $RT::SystemUser ); + $user->Load( $uid ); + unless ( $user->id ) { + print STDERR "\tERROR. Couldn't load user record\n"; + next; + } + + my ($status, $msg); + + ($status, $msg) = $user->DeleteAttribute('AuthToken') + if $user->FirstAttribute('AuthToken'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't delete duplicated attribute: $msg\n"; + next; + } else { + print "\tdeleted duplicate attribute\n"; + } + + ($status, $msg) = $attr->SetName('AuthToken'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't rename attribute: $msg\n"; + next; + } else { + print "\trenamed attribute\n"; + } + print "\tDONE\n"; +} + +exit 0; diff --git a/rt/etc/upgrade/3.8-ical-extension.in b/rt/etc/upgrade/3.8-ical-extension.in new file mode 100644 index 000000000..510419c5a --- /dev/null +++ b/rt/etc/upgrade/3.8-ical-extension.in @@ -0,0 +1,96 @@ +#!@PERL@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "@LOCAL_LIB_PATH@"; +use lib "@RT_LIB_PATH@"; + + +use RT; +RT::LoadConfig(); +RT::Init(); + +use RT::Attributes; +my $attrs = RT::Attributes->new( $RT::SystemUser ); +$attrs->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => 'RT::User'); +$attrs->Limit(FIELD => 'Name', OPERATOR=> '=', VALUE => 'ical-auth-token'); +while ( my $attr = $attrs->Next ) { + my $uid = $attr->ObjectId; + print "Processing auth token of user #". $uid ."...\n"; + + my $user = RT::User->new( $RT::SystemUser ); + $user->Load( $uid ); + unless ( $user->id ) { + print STDERR "\tERROR. Couldn't load user record\n"; + next; + } + + my ($status, $msg); + + ($status, $msg) = $user->DeleteAttribute('AuthToken') + if $user->FirstAttribute('AuthToken'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't delete duplicated attribute: $msg\n"; + next; + } else { + print "\tdeleted duplicate attribute\n"; + } + + ($status, $msg) = $attr->SetName('AuthToken'); + unless ( $status ) { + print STDERR "\tERROR. Couldn't rename attribute: $msg\n"; + next; + } else { + print "\trenamed attribute\n"; + } + print "\tDONE\n"; +} + +exit 0; diff --git a/rt/etc/upgrade/3.8.0/content b/rt/etc/upgrade/3.8.0/content new file mode 100644 index 000000000..f4e389b90 --- /dev/null +++ b/rt/etc/upgrade/3.8.0/content @@ -0,0 +1,22 @@ +@Final = ( + # by incident we've changed 'My Bookmarks' to 'Bookmarked Tickets' when + # 3.7.82 upgrade script still was creating 'My Bookmarks', try to fix it + sub { + $RT::Logger->debug("Going to rename 'My Bookmarks' to 'Bookmarked Tickets'"); + my $sys = RT::System->new($RT::SystemUser); + + my $attrs = RT::Attributes->new( $RT::SystemUser ); + $attrs->LimitToObject( $sys ); + my ($attr) = $attrs->Named( 'Search - My Bookmarks' ); + unless ($attr) { + $RT::Logger->debug("You have no global search 'My Bookmarks'. Skipped."); + return 1; + } + my ($status, $msg) = $attr->SetName( 'Search - Bookmarked Tickets' ); + $RT::Logger->error($msg) and return undef unless $status; + + $RT::Logger->debug("Renamed."); + return 1; + }, +); + diff --git a/rt/etc/upgrade/3.8.1/content b/rt/etc/upgrade/3.8.1/content new file mode 100644 index 000000000..89db596ec --- /dev/null +++ b/rt/etc/upgrade/3.8.1/content @@ -0,0 +1,24 @@ +@Final = ( + sub { + $RT::Logger->debug("Going to adjust 'Bookmarked Tickets'"); + my $sys = RT::System->new($RT::SystemUser); + + my $attrs = RT::Attributes->new( $RT::SystemUser ); + $attrs->LimitToObject( $sys ); + my ($attr) = $attrs->Named( 'Search - Bookmarked Tickets' ); + unless ($attr) { + $RT::Logger->debug("You have no global search 'Bookmarked Tickets'. Skipped."); + return 1; + } + my $props = $attr->Content; + $props->{'Query'} =~ s/__Bookmarks__/id = '__Bookmarked__'/g; + + my ($status, $msg) = $attr->SetContent( $props ); + $RT::Logger->error($msg) and return undef unless $status; + + $RT::Logger->debug("Fixed."); + return 1; + }, +); + + diff --git a/rt/etc/upgrade/3.8.2/content b/rt/etc/upgrade/3.8.2/content new file mode 100644 index 000000000..9bd92be21 --- /dev/null +++ b/rt/etc/upgrade/3.8.2/content @@ -0,0 +1,186 @@ +@Initial = ( + sub { + $RT::Logger->warning( + "Going to add [OLD] prefix to all temlates in approvals queue." + ." If you never used approvals then you can delete all these" + ." templates with [OLD] prefix. Leave new there may be you will" + ." want to use approvals some time." + ); + + my $approvals_q = RT::Queue->new( $RT::SystemUser ); + $approvals_q->Load('___Approvals'); + unless ( $approvals_q->id ) { + $RT::Logger->error("You have no approvals queue."); + return 1; + } + + my $templates = RT::Templates->new( $RT::SystemUser ); + $templates->LimitToQueue( $approvals_q->id ); + while ( my $tmpl = $templates->Next ) { + my ($status, $msg) = $tmpl->SetName( "[OLD] ". $tmpl->Name ); + unless ( $status ) { + $RT::Logger->error("Couldn't rename template #". $tmpl->id .": $msg"); + } + } + return 1; + }, +); +@ACL = ( + { GroupDomain => 'SystemInternal', + GroupType => 'privileged', + Right => 'ShowApprovalsTab', }, +); + +@Templates = ( + { Queue => '___Approvals', + Name => "New Pending Approval", # loc + Description => + "Notify Owners and AdminCcs of new items pending their approval", # loc + Content => 'Subject: New Pending Approval: {$Ticket->Subject} + +Greetings, + +There is a new item pending your approval: "{$Ticket->Subject()}", +a summary of which appears below. + +Please visit {RT->Config->Get(\'WebURL\')}Approvals/Display.html?id={$Ticket->id} +to approve or reject this ticket, or {RT->Config->Get(\'WebURL\')}Approvals/ to +batch-process all your pending approvals. + +------------------------------------------------------------------------- +{$Transaction->Content()} +' + }, + { Queue => '___Approvals', + Name => "Approval Passed", # loc + Description => + "Notify Requestor of their ticket has been approved by some approver", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +Your ticket has been approved by { eval { $Approval->OwnerObj->Name } }. +Other approvals may be pending. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "All Approvals Passed", # loc + Description => + "Notify Requestor of their ticket has been approved by all approvers", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +Your ticket has been approved by { eval { $Approval->OwnerObj->Name } }. +Its Owner may now start to act on it. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "Approval Rejected", # loc + Description => + "Notify Owner of their rejected ticket", # loc + Content => 'Subject: Ticket Rejected: {$Ticket->Subject} + +Greetings, + +Your ticket has been rejected by { eval { $Approval->OwnerObj->Name } }. + +Approver\'s notes: { $Notes } +' + }, + { Queue => '___Approvals', + Name => "Approval Ready for Owner", # loc + Description => + "Notify Owner of their ticket has been approved and is ready to be acted on", # loc + Content => 'Subject: Ticket Approved: {$Ticket->Subject} + +Greetings, + +The ticket has been approved, you may now start to act on it. + +' + }, +); + +@Final = ( + sub { + $RT::Logger->debug("Going to adjust dashboards"); + my $sys = RT::System->new($RT::SystemUser); + + my $attrs = RT::Attributes->new( $RT::SystemUser ); + $attrs->UnLimit; + my @dashboards = $attrs->Named('Dashboard'); + + if (@dashboards == 0) { + $RT::Logger->debug("You have no dashboards. Skipped."); + return 1; + } + + for my $attr (@dashboards) { + my $props = $attr->Content; + if (exists $props->{Searches}) { + $props->{Panes} = { + body => [ + map { + my ($privacy, $id, $desc) = @$_; + + { + portlet_type => 'search', + privacy => $privacy, + id => $id, + description => $desc, + pane => 'body', + } + } @{ delete $props->{Searches} } + ], + }; + } + my ($status, $msg) = $attr->SetContent( $props ); + $RT::Logger->error($msg) unless $status; + } + + $RT::Logger->debug("Fixed."); + return 1; + }, + sub { + my $approvals_q = RT::Queue->new( $RT::SystemUser ); + $approvals_q->Load('___Approvals'); + unless ( $approvals_q->id ) { + $RT::Logger->error("You have no approvals queue."); + return 1; + } + + require File::Temp; + my ($tmp_fh, $tmp_fn) = File::Temp::tempfile( 'rt-approvals-scrips-XXXX', CLEANUP => 0 ); + unless ( $tmp_fh ) { + $RT::Logger->error("Couldn't create temporary file."); + return 0; + } + + $RT::Logger->warning( + "IMPORTANT: We're going to delete all scrips in Approvals queue" + ." and save them in '$tmp_fn' file." + ); + + require Data::Dumper; + + my $scrips = RT::Scrips->new( $RT::SystemUser ); + $scrips->LimitToQueue( $approvals_q->id ); + while ( my $scrip = $scrips->Next ) { + my %tmp = + map { $tmp->{ $_ } = $scrip->_Value( $_ ) } + $scrip->ReadableAttributes; + + print $tmp_fh Data::Dumper::Dumper( \%tmp ); + + my ($status, $msg) = $scrip->Delete; + unless ( $status ) { + $RT::Logger->error( "Couldn't delete scrip: $msg"); + } + } + }, +); diff --git a/rt/etc/upgrade/3.8.3/content b/rt/etc/upgrade/3.8.3/content new file mode 100644 index 000000000..8538e4287 --- /dev/null +++ b/rt/etc/upgrade/3.8.3/content @@ -0,0 +1,91 @@ +@ScripConditions = ( + { Name => 'On Reject', # loc + Description => 'Whenever a ticket is rejected', # loc + ApplicableTransTypes => 'Status', + ExecModule => 'StatusChange', + Argument => 'rejected' + + }, +); + +@Final = ( + sub { + $RT::Logger->debug("Going to correct descriptions of notify actions in the DB"); + + my $actions = RT::ScripActions->new( $RT::SystemUser ); + $actions->Limit( + FIELD => 'ExecModule', + VALUE => 'Notify', + ); + $actions->Limit( + FIELD => 'Argument', + VALUE => 'All', + ); + while ( my $action = $actions->Next ) { + my ($status, $msg) = $action->__Set( Field => 'Name', Value => 'Notify Owner, Requestors, Ccs and AdminCcs' ); + $RT::Logger->warning( "Couldn't change action name: $msg" ) + unless $status; + + ($status, $msg) = $action->__Set( Field => 'Description', Value => 'Send mail to owner and all watchers' ); + $RT::Logger->warning( "Couldn't change action description: $msg" ) + unless $status; + } + + $actions = RT::ScripActions->new( $RT::SystemUser ); + $actions->Limit( + FIELD => 'ExecModule', + VALUE => 'NotifyAsComment', + ); + $actions->Limit( + FIELD => 'Argument', + VALUE => 'All', + ); + while ( my $action = $actions->Next ) { + my ($status, $msg) = $action->__Set( Field => 'Name', Value => 'Notify Owner, Requestors, Ccs and AdminCcs as Comment' ); + $RT::Logger->warning( "Couldn't change action name: $msg" ) + unless $status; + + ($status, $msg) = $action->__Set( Field => 'Description', Value => 'Send mail to owner and all watchers as a "comment"' ); + $RT::Logger->warning( "Couldn't change action description: $msg" ) + unless $status; + } + + $RT::Logger->debug("Corrected descriptions of notify actions in the DB."); + return 1; + }, +); + + +{ +$RT::Logger->debug("Going to add in Extract Subject Tag actions if they were missed during a previous upgrade"); + +$actions = RT::ScripActions->new( $RT::SystemUser ); +$actions->Limit( + FIELD => 'ExecModule', + VALUE => 'ExtractSubjectTag', +); +my $extract_action = $actions->First; + +if ( $extract_action && $extract_action->Id ) { + $RT::Logger->debug("You appear to already have an Extract Subject Tag action, skipping"); + return 1; +} else { + $RT::Logger->debug("Didn't find an existing Extract Subject Tag action, adding it"); + push @ScripActions, ( + { Name => 'Extract Subject Tag', # loc + Description => 'Extract tags from a Transaction\'s subject and add them to the Ticket\'s subject.', # loc + ExecModule => 'ExtractSubjectTag' + }, + ); + + $RT::Logger->debug("Adding Extract Subject Tag Scrip"); + push @Scrips, ( + { Description => "On transaction, add any tags in the transaction's subject to the ticket's subject", + ScripCondition => 'On Transaction', + ScripAction => 'Extract Subject Tag', + Template => 'Blank' + }, + ); +} +} + diff --git a/rt/etc/upgrade/3.8.3/schema.Pg b/rt/etc/upgrade/3.8.3/schema.Pg new file mode 100644 index 000000000..bbe55365d --- /dev/null +++ b/rt/etc/upgrade/3.8.3/schema.Pg @@ -0,0 +1,3 @@ + +CREATE UNIQUE INDEX GroupMembers1 ON GroupMembers(GroupId, MemberId); + diff --git a/rt/etc/upgrade/3.8.4/content b/rt/etc/upgrade/3.8.4/content new file mode 100644 index 000000000..be5a6bf39 --- /dev/null +++ b/rt/etc/upgrade/3.8.4/content @@ -0,0 +1,59 @@ + +@Final = ( + sub { + $RT::Logger->debug("Going to correct arguments of NotifyGroup actions if you have any"); + use strict; + + my $actions = RT::ScripActions->new( $RT::SystemUser ); + $actions->Limit( + FIELD => 'ExecModule', + VALUE => 'NotifyGroup', + ); + $actions->Limit( + FIELD => 'ExecModule', + VALUE => 'NotifyGroupAsComment', + ); + + my $converter = sub { + my $arg = shift; + my @res; + foreach my $r ( @{ $arg } ) { + my $obj; + next unless $r->{'Type'}; + if( lc $r->{'Type'} eq 'user' ) { + $obj = RT::User->new( $RT::SystemUser ); + } elsif ( lc $r->{'Type'} eq 'group' ) { + $obj = RT::Group->new( $RT::SystemUser ); + } else { + next; + } + $obj->Load( $r->{'Instance'} ); + my $id = $obj->id; + next unless( $id ); + + push @res, $id; + } + + return join ',', @res; + }; + + require Storable; + while ( my $action = $actions->Next ) { + my $argument = $action->Argument; + my $new = ''; + local $@; + if ( my $struct = eval { Storable::thaw( $argument ) } ) { + $new = $converter->( $struct ); + } else { + $new = join /, /, grep length, split /[^0-9]+/, $argument; + } + next if $new eq $argument; + + my ($status, $msg) = $action->__Set( Field => 'Argument', Value => $new ); + $RT::Logger->warning( "Couldn't change argument value of the action: $msg" ) + unless $status; + } + }, +); + + diff --git a/rt/etc/upgrade/3.8.6/content b/rt/etc/upgrade/3.8.6/content new file mode 100644 index 000000000..a9793c6e1 --- /dev/null +++ b/rt/etc/upgrade/3.8.6/content @@ -0,0 +1,10 @@ +@Templates = ( + { Queue => 0, + Name => "Forward Ticket", # loc + Description => "Heading of a forwarded Ticket", # loc + Content => q{ + +This is a forward of ticket #{ $Ticket->id } +} + }, +); diff --git a/rt/etc/upgrade/3.8.8/content b/rt/etc/upgrade/3.8.8/content new file mode 100644 index 000000000..ee1943304 --- /dev/null +++ b/rt/etc/upgrade/3.8.8/content @@ -0,0 +1,38 @@ +@Initial = ( + sub { + # make sure global CFs are not applied to local objects + my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); + $ocfs->Limit( FIELD => 'ObjectId', OPERATOR => '!=', VALUE => 0 ); + my $alias = $ocfs->Join( + FIELD1 => 'CustomField', + TABLE2 => 'ObjectCustomFields', + FIELD2 => 'CustomField', + ); + $ocfs->Limit( ALIAS => $alias, FIELD => 'ObjectId', VALUE => 0 ); + while ( my $ocf = $ocfs->Next ) { + $ocf->Delete; + } + }, + sub { + # sort SortOrder + my $sth = $RT::Handle->dbh->prepare( + "SELECT cfs.LookupType, ocfs.id" + ." FROM ObjectCustomFields ocfs, CustomFields cfs" + ." WHERE cfs.id = ocfs.CustomField" + ." ORDER BY cfs.LookupType, ocfs.SortOrder, cfs.Name" + ); + $sth->execute; + + my ($i, $prev_type) = (0, ''); + while ( my ($lt, $id) = $sth->fetchrow_array ) { + $i = 0 if $prev_type ne $lt; + my $ocf = RT::ObjectCustomField->new( $RT::SystemUser ); + $ocf->Load( $id ); + my ($status, $msg) = $ocf->SetSortOrder( $i++ ); + $RT::Logger->warning("Couldn't set SortOrder: $msg") + unless $status; + $prev_type = $lt; + } + }, +); + diff --git a/rt/etc/upgrade/shrink_cgm_table.pl b/rt/etc/upgrade/shrink_cgm_table.pl new file mode 100644 index 000000000..3d153c709 --- /dev/null +++ b/rt/etc/upgrade/shrink_cgm_table.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use 5.8.3; +use strict; +use warnings; + +use RT; +RT::LoadConfig(); +RT->Config->Set('LogToScreen' => 'debug'); +RT::Init(); + +use RT::CachedGroupMembers; +my $cgms = RT::CachedGroupMembers->new( $RT::SystemUser ); +$cgms->Limit( + FIELD => 'id', + OPERATOR => '!=', + VALUE => 'main.Via', + QUOTEVALUE => 0, + ENTRYAGGREGATOR => 'AND', +); +$cgms->FindAllRows; + +my $alias = $cgms->Join( + TYPE => 'LEFT', + FIELD1 => 'Via', + TABLE2 => 'CachedGroupMembers', + FIELD2 => 'id', +); +$cgms->Limit( + ALIAS => $alias, + FIELD => 'MemberId', + OPERATOR => '=', + VALUE => $alias .'.GroupId', + QUOTEVALUE => 0, + ENTRYAGGREGATOR => 'AND', +); +$cgms->Limit( + ALIAS => $alias, + FIELD => 'id', + OPERATOR => '=', + VALUE => $alias .'.Via', + QUOTEVALUE => 0, + ENTRYAGGREGATOR => 'AND', +); + +FetchNext( $cgms, 'init' ); +while ( my $rec = FetchNext( $cgms ) ) { + $RT::Handle->BeginTransaction; + my ($status) = $rec->Delete; + unless ($status) { + print STDERR "Couldn't delete CGM #". $rec->id; + exit 1; + } + $RT::Handle->Commit; +} + +use constant PAGE_SIZE => 1000; +sub FetchNext { + my ($objs, $init) = @_; + if ( $init ) { + $objs->RowsPerPage( PAGE_SIZE ); + $objs->FirstPage; + return; + } + + my $obj = $objs->Next; + return $obj if $obj; + $objs->RedoSearch; + $objs->FirstPage; + return $objs->Next; +} + diff --git a/rt/etc/upgrade/split-out-cf-categories b/rt/etc/upgrade/split-out-cf-categories new file mode 100755 index 000000000..d4077ce54 --- /dev/null +++ b/rt/etc/upgrade/split-out-cf-categories @@ -0,0 +1,171 @@ +#!/usr/bin/perl +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "local/lib"; +use lib "lib"; + +use RT; +RT::LoadConfig(); +RT->Config->Set('LogToScreen' => 'debug'); +RT::Init(); + +$| = 1; + +$RT::Handle->BeginTransaction(); + +use RT::CustomFields; +my $CFs = RT::CustomFields->new( $RT::SystemUser ); +$CFs->UnLimit; +$CFs->Limit( FIELD => 'Type', VALUE => 'Select' ); + +my $seen; +while (my $cf = $CFs->Next ) { + next if $cf->BasedOnObj->Id; + my @categories; + my %mapping; + my $values = $cf->Values; + while (my $value = $values->Next) { + next unless defined $value->Category and length $value->Category; + push @categories, $value->Category unless grep {$_ eq $value->Category} @categories; + $mapping{$value->Name} = $value->Category; + } + next unless @categories; + + $seen++; + print "Found CF '@{[$cf->Name]}' with categories:\n"; + print " $_\n" for @categories; + + print "Split this CF's categories into a hierarchical custom field (Y/n)? "; + my $dothis = <>; + next if $dothis =~ /n/i; + + print "Enter name of CF to create as category ('@{[$cf->Name]} category'): "; + my $newname = <>; + chomp $newname; + $newname = $cf->Name . " category" unless length $newname; + + # bump the CF's sort oder up by one + $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 ); + + # ..and add a new CF before it + my $new = RT::CustomField->new( $RT::SystemUser ); + my ($id, $msg) = $new->Create( + Name => $newname, + Type => 'Select', + MaxValues => 1, + LookupType => $cf->LookupType, + SortOrder => $cf->SortOrder - 1, + ); + die "Can't create custom field '$newname': $msg" unless $id; + + # Set the CF to be based on what we just made + $cf->SetBasedOn( $new->Id ); + + # Apply it to all of the same things + { + my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); + $ocfs->LimitToCustomField( $cf->Id ); + while (my $ocf = $ocfs->Next) { + my $newocf = RT::ObjectCustomField->new( $RT::SystemUser ); + ($id, $msg) = $newocf->Create( + SortOrder => $ocf->SortOrder, + CustomField => $new->Id, + ObjectId => $ocf->ObjectId, + ); + die "Can't create ObjectCustomField: $msg" unless $id; + } + } + + # Copy over all of the rights + { + my $acl = RT::ACL->new( $RT::SystemUser ); + $acl->LimitToObject( $cf ); + while (my $ace = $acl->Next) { + my $newace = RT::ACE->new( $RT::SystemUser ); + ($id, $msg) = $newace->Create( + PrincipalId => $ace->PrincipalId, + PrincipalType => $ace->PrincipalType, + RightName => $ace->RightName, + Object => $new, + ); + die "Can't assign rights: $msg" unless $id; + } + } + + # Add values for all of the categories + for my $i (0..$#categories) { + ($id, $msg) = $new->AddValue( + Name => $categories[$i], + SortOrder => $i + 1, + ); + die "Can't create custom field value: $msg" unless $id; + } + + # Grovel through all ObjectCustomFieldValues, and add the + # appropriate category + { + my $ocfvs = RT::ObjectCustomFieldValues->new( $RT::SystemUser ); + $ocfvs->LimitToCustomField( $cf->Id ); + while (my $ocfv = $ocfvs->Next) { + next unless exists $mapping{$ocfv->Content}; + my $newocfv = RT::ObjectCustomFieldValue->new( $RT::SystemUser ); + ($id, $msg) = $newocfv->Create( + CustomField => $new->Id, + ObjectType => $ocfv->ObjectType, + ObjectId => $ocfv->ObjectId, + Content => $mapping{$ocfv->Content}, + ); + } + } +} + +$RT::Handle->Commit; +print "No custom fields with categories found\n" unless $seen; diff --git a/rt/etc/upgrade/split-out-cf-categories.in b/rt/etc/upgrade/split-out-cf-categories.in new file mode 100644 index 000000000..f34a1b616 --- /dev/null +++ b/rt/etc/upgrade/split-out-cf-categories.in @@ -0,0 +1,171 @@ +#!@PERL@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC +# <jesse@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "@LOCAL_LIB_PATH@"; +use lib "@RT_LIB_PATH@"; + +use RT; +RT::LoadConfig(); +RT->Config->Set('LogToScreen' => 'debug'); +RT::Init(); + +$| = 1; + +$RT::Handle->BeginTransaction(); + +use RT::CustomFields; +my $CFs = RT::CustomFields->new( $RT::SystemUser ); +$CFs->UnLimit; +$CFs->Limit( FIELD => 'Type', VALUE => 'Select' ); + +my $seen; +while (my $cf = $CFs->Next ) { + next if $cf->BasedOnObj->Id; + my @categories; + my %mapping; + my $values = $cf->Values; + while (my $value = $values->Next) { + next unless defined $value->Category and length $value->Category; + push @categories, $value->Category unless grep {$_ eq $value->Category} @categories; + $mapping{$value->Name} = $value->Category; + } + next unless @categories; + + $seen++; + print "Found CF '@{[$cf->Name]}' with categories:\n"; + print " $_\n" for @categories; + + print "Split this CF's categories into a hierarchical custom field (Y/n)? "; + my $dothis = <>; + next if $dothis =~ /n/i; + + print "Enter name of CF to create as category ('@{[$cf->Name]} category'): "; + my $newname = <>; + chomp $newname; + $newname = $cf->Name . " category" unless length $newname; + + # bump the CF's sort oder up by one + $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 ); + + # ..and add a new CF before it + my $new = RT::CustomField->new( $RT::SystemUser ); + my ($id, $msg) = $new->Create( + Name => $newname, + Type => 'Select', + MaxValues => 1, + LookupType => $cf->LookupType, + SortOrder => $cf->SortOrder - 1, + ); + die "Can't create custom field '$newname': $msg" unless $id; + + # Set the CF to be based on what we just made + $cf->SetBasedOn( $new->Id ); + + # Apply it to all of the same things + { + my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); + $ocfs->LimitToCustomField( $cf->Id ); + while (my $ocf = $ocfs->Next) { + my $newocf = RT::ObjectCustomField->new( $RT::SystemUser ); + ($id, $msg) = $newocf->Create( + SortOrder => $ocf->SortOrder, + CustomField => $new->Id, + ObjectId => $ocf->ObjectId, + ); + die "Can't create ObjectCustomField: $msg" unless $id; + } + } + + # Copy over all of the rights + { + my $acl = RT::ACL->new( $RT::SystemUser ); + $acl->LimitToObject( $cf ); + while (my $ace = $acl->Next) { + my $newace = RT::ACE->new( $RT::SystemUser ); + ($id, $msg) = $newace->Create( + PrincipalId => $ace->PrincipalId, + PrincipalType => $ace->PrincipalType, + RightName => $ace->RightName, + Object => $new, + ); + die "Can't assign rights: $msg" unless $id; + } + } + + # Add values for all of the categories + for my $i (0..$#categories) { + ($id, $msg) = $new->AddValue( + Name => $categories[$i], + SortOrder => $i + 1, + ); + die "Can't create custom field value: $msg" unless $id; + } + + # Grovel through all ObjectCustomFieldValues, and add the + # appropriate category + { + my $ocfvs = RT::ObjectCustomFieldValues->new( $RT::SystemUser ); + $ocfvs->LimitToCustomField( $cf->Id ); + while (my $ocfv = $ocfvs->Next) { + next unless exists $mapping{$ocfv->Content}; + my $newocfv = RT::ObjectCustomFieldValue->new( $RT::SystemUser ); + ($id, $msg) = $newocfv->Create( + CustomField => $new->Id, + ObjectType => $ocfv->ObjectType, + ObjectId => $ocfv->ObjectId, + Content => $mapping{$ocfv->Content}, + ); + } + } +} + +$RT::Handle->Commit; +print "No custom fields with categories found\n" unless $seen;
\ No newline at end of file diff --git a/rt/etc/upgrade/upgrade-mysql-schema.pl b/rt/etc/upgrade/upgrade-mysql-schema.pl new file mode 100755 index 000000000..bc59c97a1 --- /dev/null +++ b/rt/etc/upgrade/upgrade-mysql-schema.pl @@ -0,0 +1,390 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use DBI; +use DBD::mysql 4.002; + +unless (@ARGV) { + print STDERR "usage: $0 db_name[:server_name] db_user db_password\n"; + exit 1; +} + +# pretty correct support of charsets has been introduced in mysql 4.1 +# as RT doesn't use it may result in issues: +# 1) data corruptions when default charset of mysql server has data restrictions like utf8 +# 2) wrong ordering (collations) + +# we have to define correct types for all columns. RT uses UTF-8, ascii and binary. +# * ascii is subset of many mysql's charsets except may be one or two rare where some ascii +# characters replaced with local +# * for many charsets mysql allows us to store any octets sequences even when those are +# invalid for this particula set, for example we can store UTF-8 data in latin1 +# column and fetch it as UTF-8, however sorting will be wrong + +# here is tricky algorithm to change column to desired charset: +# * text to binary convertion is pretty straight forward except that text types +# have length definitions in terms of characters and in some cases we must +# use longer binary types to satisfy space requirements +# * binary to text is much easier as we know that there is ascii or UTF-8 then +# we just make convertion, also 32 chars are long enough to store 32 bytes, so +# length changes is not required +# * text to text convertion is trickier. no matter what is the current character set +# of the column we know that there is either ascii or UTF-8, so we can not use +# direct convertion, instead we do text to binary plus binary to text convertion +# instead +# * as well we add charset definition for all tables and for the DB as well, +# so all new columns by default will be in UTF-8 charset + +my @tables = qw( + ACL + Attachments + Attributes + CustomFields + CustomFieldValues + GroupMembers + Groups + Links + ObjectCustomFields + ObjectCustomFieldValues + Principals + Queues + ScripActions + ScripConditions + Scrips + sessions + Templates + Tickets + Transactions + Users +); + +my %charset = ( + ACL => { + RightName => 'ascii', + ObjectType => 'ascii', + PrincipalType => 'ascii', + }, + Attachments => { + MessageId => 'ascii', + Subject => 'utf8', + Filename => 'utf8', + ContentType => 'ascii', + ContentEncoding => 'ascii', + Content => 'binary', + Headers => 'utf8', + }, + Attributes => { + Name => 'utf8', + Description => 'utf8', + Content => 'binary', + ContentType => 'ascii', + ObjectType => 'ascii', + }, + CustomFields => { + Name => 'utf8', + Type => 'ascii', + Pattern => 'utf8', + Description => 'utf8', + LookupType => 'ascii', + }, + CustomFieldValues => { + Name => 'utf8', + Description => 'utf8', + }, + Groups => { + Name => 'utf8', + Description => 'utf8', + Domain => 'ascii', + Type => 'ascii', + }, + Links => { + Base => 'ascii', + Target => 'ascii', + Type => 'ascii', + }, + ObjectCustomFieldValues => { + ObjectType => 'ascii', + Content => 'utf8', + LargeContent => 'binary', + ContentType => 'ascii', + ContentEncoding => 'ascii', + }, + Principals => { + PrincipalType => 'ascii', + }, + Queues => { + Name => 'utf8', + Description => 'utf8', + CorrespondAddress => 'ascii', + CommentAddress => 'ascii', + }, + ScripActions => { + Name => 'utf8', + Description => 'utf8', + ExecModule => 'ascii', + Argument => 'binary', + }, + ScripConditions => { + Name => 'utf8', + Description => 'utf8', + ExecModule => 'ascii', + Argument => 'binary', + ApplicableTransTypes => 'ascii', + }, + Scrips => { + Description => 'utf8', + ConditionRules => 'utf8', + ActionRules => 'utf8', + CustomIsApplicableCode => 'utf8', + CustomPrepareCode => 'utf8', + CustomCommitCode => 'utf8', + Stage => 'ascii', + }, + sessions => { + id => 'binary', # ascii? + a_session => 'binary', + }, + Templates => { + Name => 'utf8', + Description => 'utf8', + Type => 'ascii', + Language => 'ascii', + Content => 'utf8', + }, + Tickets => { + Type => 'ascii', + Subject => 'utf8', + Status => 'ascii', + }, + Transactions => { + ObjectType => 'ascii', + Type => 'ascii', + Field => 'ascii', + OldValue => 'utf8', + NewValue => 'utf8', + ReferenceType => 'ascii', + Data => 'utf8', + }, + Users => { + Name => 'utf8', + Password => 'binary', + Comments => 'utf8', + Signature => 'utf8', + EmailAddress => 'ascii', + FreeformContactInfo => 'utf8', + Organization => 'utf8', + RealName => 'utf8', + NickName => 'utf8', + Lang => 'ascii', + EmailEncoding => 'ascii', + WebEncoding => 'ascii', + ExternalContactInfoId => 'utf8', + ContactInfoSystem => 'utf8', + ExternalAuthId => 'utf8', + AuthSystem => 'utf8', + Gecos => 'utf8', + HomePhone => 'utf8', + WorkPhone => 'utf8', + MobilePhone => 'utf8', + PagerPhone => 'utf8', + Address1 => 'utf8', + Address2 => 'utf8', + City => 'utf8', + State => 'utf8', + Zip => 'utf8', + Country => 'utf8', + Timezone => 'ascii', + PGPKey => 'binary', + }, +); + +my %max_type_length = ( + char => int 1<<8, + varchar => int 1<<8, + tinytext => int 1<<8, + mediumtext => int 1<<16, + text => int 1<<24, + longtext => int 1<<32, +); + +my @sql_commands; + +my ($db_datasource, $db_user, $db_pass) = (shift, shift, shift); +my $dbh = DBI->connect("dbi:mysql:$db_datasource", $db_user, $db_pass, { RaiseError => 1 }); +my $db_name = $db_datasource; +$db_name =~ s/:.*$//; + +my $version = ($dbh->selectrow_array("show variables like 'version'"))[1]; +($version) = $version =~ /^(\d+\.\d+)/; + +push @sql_commands, qq{ALTER DATABASE $db_name DEFAULT CHARACTER SET utf8}; +convert_table($_) foreach @tables; + +print join "\n", map(/;$/? $_ : "$_;", @sql_commands), ""; +my $use_p = $db_pass ? " -p" : ''; +print STDERR <<ENDREMINDER; +-- ** NOTICE: No database changes have been made. ** +-- Please review the generated SQL, ensure you have a full backup of your database +-- and apply it to your database using a command like: +-- mysql -u ${db_user}${use_p} $db_name < queries.sql"; +ENDREMINDER +exit 0; + +my %alter_aggregator; +sub convert_table { + my $table = shift; + @alter_aggregator{'char_to_binary','binary_to_char'} = (['DEFAULT CHARACTER SET utf8'],[]); + + my $sth = $dbh->column_info( undef, $db_name, $table, undef ); + $sth->execute; + while ( my $info = $sth->fetchrow_hashref ) { + convert_column(%$info); + } + for my $conversiontype (qw(char_to_binary binary_to_char)) { + next unless @{$alter_aggregator{$conversiontype}}; + push @sql_commands, qq{ALTER TABLE $table\n }. + join(",\n ",@{$alter_aggregator{$conversiontype}}); + } +} + +sub convert_column { + my %info = @_; + my $table = $info{'TABLE_NAME'}; + my $column = $info{'COLUMN_NAME'}; + my $type = $info{'TYPE_NAME'}; + return unless $type =~ /(CHAR|TEXT|BLOB|BINARY)$/i; + + my $required_charset = $charset{$table}{$column}; + unless ( $required_charset ) { + print STDERR join(".", @info{'TABLE_SCHEMA', 'TABLE_NAME', 'COLUMN_NAME'}) + ." has type $type however mapping is missing.\n"; + return; + } + + my $collation = column_info($table, $column)->{'collation'}; + # mysql 4.1 returns literal NULL instead of undef + my $current_charset = $collation && $collation ne 'NULL'? (split /_/, $collation)[0]: 'binary'; + return if $required_charset eq $current_charset; + + if ( $required_charset eq 'binary' ) { + char_to_binary(%info); + } + elsif ( $current_charset eq 'binary' ) { + binary_to_char( $required_charset, %info); + } else { + char_to_char( $required_charset, %info); + } +} + +sub char_to_binary { + my %info = @_; + + my $table = $info{'TABLE_NAME'}; + my $column = $info{'COLUMN_NAME'}; + my $new_type = calc_suitable_binary_type(%info); + push @{$alter_aggregator{char_to_binary}}, + "MODIFY $column $new_type ".build_column_definition(%info); + +} + +sub binary_to_char { + my ($charset, %info) = @_; + + my $table = $info{'TABLE_NAME'}; + my $column = $info{'COLUMN_NAME'}; + my $new_type = lc $info{'TYPE_NAME'}; + if ( $new_type =~ /binary/ ) { + $new_type =~ s/binary/char/; + $new_type .= '('. $info{'COLUMN_SIZE'} .')'; + } else { + $new_type =~ s/blob/text/; + } + + push @{$alter_aggregator{binary_to_char}}, + "MODIFY $column ". uc($new_type) ." CHARACTER SET ". $charset + ." ". build_column_definition(%info); +} + +sub char_to_char { + my ($charset, %info) = @_; + + my $table = $info{'TABLE_NAME'}; + my $column = $info{'COLUMN_NAME'}; + my $new_type = $info{'mysql_type_name'}; + + char_to_binary(%info); + push @{$alter_aggregator{binary_to_char}}, + "MODIFY $column ". uc($new_type)." CHARACTER SET ". $charset + ." ". build_column_definition(%info); +} + +sub calc_suitable_binary_type { + my %info = @_; + my $type = lc $info{'TYPE_NAME'}; + return 'LONGBLOB' if $type eq 'longtext'; + + my $current_max_byte_length = column_byte_length(@info{qw(TABLE_NAME COLUMN_NAME)}) || 0; + if ( $max_type_length{ $type } > $current_max_byte_length ) { + if ( $type eq 'varchar' || $type eq 'char' ) { + my $new_type = $type; + $new_type =~ s/char/binary/; + $new_type .= $info{'COLUMN_SIZE'} >= $current_max_byte_length + ? '('. $info{'COLUMN_SIZE'} .')' + : '('. $current_max_byte_length .')'; + return uc $new_type; + } else { + my $new_type = $type; + $new_type =~ s/text/blob/; + return uc $new_type; + } + } else { + my $new_type; + foreach ( sort { $max_type_length{$a} <=> $max_type_length{$b} } keys %max_type_length ) { + next if $max_type_length{ $_ } <= $current_max_byte_length; + + $new_type = $_; last; + } + $new_type =~ s/text/blob/; + return uc $new_type; + } +} + +sub build_column_definition { + my %info = @_; + + my $res = ''; + $res .= 'NOT ' unless $info{'NULLABLE'}; + $res .= 'NULL'; + my $default = column_info(@info{qw(TABLE_NAME COLUMN_NAME)})->{default}; + if ( defined $default ) { + $res .= ' DEFAULT '. $dbh->quote($default); + } elsif ( $info{'NULLABLE'} ) { + $res .= ' DEFAULT NULL'; + } + $res .= ' AUTO_INCREMENT' if $info{'mysql_is_auto_increment'}; + return $res; +} + +sub column_byte_length { + my ($table, $column) = @_; + if ( $version >= 5.0 ) { + my ($char, $octet) = @{ $dbh->selectrow_arrayref( + "SELECT CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH FROM information_schema.COLUMNS WHERE" + ." TABLE_SCHEMA = ". $dbh->quote($db_name) + ." AND TABLE_NAME = ". $dbh->quote($table) + ." AND COLUMN_NAME = ". $dbh->quote($column) + ) }; + return $octet if $octet == $char; + } + return $dbh->selectrow_arrayref("SELECT MAX(LENGTH(". $dbh->quote_identifier($column) .")) FROM $table")->[0]; +} + +sub column_info { + my ($table, $column) = @_; + # XXX: DBD::mysql doesn't provide this info, may be will do in 4.0007 if I'll write a patch + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + return $dbh->selectrow_hashref("SHOW FULL COLUMNS FROM $table LIKE " . $dbh->quote($column)); +} + |
