]> git.uio.no Git - usit-rt.git/blame - docs/initialdata.pod
Merge branch 'master' of git.uio.no:usit-rt
[usit-rt.git] / docs / initialdata.pod
CommitLineData
45030404
MKG
1=head1 Summary of initialdata files
2
3It's often useful to be able to test configuration/database changes and then
4apply the same changes in production without manually clicking around. It's
5also helpful if you're developing customizations or extensions to be able to
6get a fresh database back to the state you want for testing/development.
7
8This documentation applies to careful and thorough sysadmins as well as
9extension authors who need to make database changes easily and repeatably for
10new installs or upgrades.
11
12=head1 Examples
13
14RT ships with many initialdata files, only one of which is used to
15configure a fresh install; the rest are used for upgrades, but function
16the same despite being named differently.
17
18 etc/initialdata
19 etc/upgrade/*/content
20
21The upgrade "content" files are meant to be incremental changes applied on top
22of one another while the top level initialdata file is for fresh RT installs.
23
24Extensions may also ship with database changes in such files. You may find
25some in your install with:
26
27 find local/plugins -name initialdata -or -name content
28
29=head1 What can be in an initialdata file?
30
31initialdata files are Perl, but often consist primarily of a bunch of data
32structures defining the new records you want and not much extra code. There's
33nothing stopping you from writing a bunch of code, however!
34
35The basic template of a new initialdata file should look something like this:
36
37 use strict;
38 use warnings;
39
40 our @Queues = (
41 # some definitions here
42 );
43
44 our @Groups = (
45 # some other definitions here
46 );
47
48 1;
49
50The C<@Queues> and C<@Groups> arrays are expected by RT and should contain
51hashref definitions. There are many other arrays RT will look for and act on,
52described below. None are required, all may be used. Keep in mind that since
53they're just normal Perl arrays, you can C<push> onto them from a loop or
54C<grep> out definitions based on conditionals or generate their content with
55C<map>, etc.
56
57The complete list of possible arrays which can be used, along with
58descriptions of the values to place in them, is below.
59
60=head2 C<@Users>
61
62 push @Users, {
63 Name => 'john.doe',
64 Password => 'changethis',
65 Language => 'fr',
66 Timezone => 'America/Vancouver',
67 Privileged => 1,
68 Disabled => 0,
69 };
70
71Each hashref in C<@Users> is treated as a new user to create and passed
72straight into C<< RT::User->Create >>. All of the normal user fields are
73available, as well as C<Privileged> and C<Disabled> (both booleans) which will
74do the appropriate internal group/flag handling.
75
76For a full list of fields, read the documentation for L<RT::User/Create>.
77
78=head2 C<@Groups>
79
80 push @Groups, {
45030404
MKG
81 Name => 'Example Employees',
82 Description => 'All of the employees of my company',
c33a4027
MKG
83 Members => { Users => [ qw/ alexmv trs falcone / ],
84 Groups => [ qw/ extras / ] },
45030404
MKG
85 };
86
87Creates a new L<RT::Group> for each hashref. In almost all cases you'll want
88to follow the example above to create a group just as if you had done it from
af59614d 89the admin interface.
45030404 90
c33a4027
MKG
91In addition to the C<Members> option shown above, which can take both
92users and groups, the C<MemberOf> field may be a single value or an
93array ref. Each value should be a user-defined group name or hashref to
94pass into L<RT::Group/LoadByCols>. Each group found will have the new
95group added as a member.
45030404
MKG
96
97=head2 C<@Queues>
98
99 push @Queues, {
100 Name => 'Helpdesk',
101 CorrespondAddress => 'help@example.com',
102 CommentAddress => 'help-comment@example.com',
103 };
104
105Creates a new L<RT::Queue> for each hashref. Refer to the documentation of
106L<RT::Queue/Create> for the fields you can use.
107
108=head2 C<@CustomFields>
109
110 push @CustomFields, {
45030404
MKG
111 Name => 'Favorite color',
112 Type => 'FreeformSingle',
113 LookupType => 'RT::Queue-RT::Ticket',
114 };
115
116Creates a new L<RT::CustomField> for each hashref. It is the most complex of
117the initialdata structures. The most commonly used fields are:
118
119=over 4
120
121=item C<Name>
122
123The name of this CF as displayed in RT.
124
125=item C<Description>
126
127A short summary of what this CF is for.
128
af59614d 129=item C<ApplyTo>
45030404 130
af59614d
MKG
131May be a single value, or an array reference of such; each should be
132either an ID or Name. If omitted, the CF is applied globally. This
133should not be used for User or Group custom fields.
134
135This argument may also be passed via C<Queue>, for backwards
136compatibility, which also defaults the C<LookupType> to
137C<RT::Queue-RT::Ticket>.
45030404
MKG
138
139=item C<Type>
140
141One of the following on the left hand side:
142
143 SelectSingle # Select one value
144 SelectMultiple # Select multiple values
145
146 FreeformSingle # Enter one value
147 FreeformMultiple # Enter multiple values
148
149 Text # Fill in one text area
150 Wikitext # Fill in one wikitext area
151
152 BinarySingle # Upload one file
153 BinaryMultiple # Upload multiple files
154
155 ImageSingle # Upload one image
156 ImageMultiple # Upload multiple images
157
158 Combobox # Combobox: Select or enter one value
159
160 AutocompleteSingle # Enter one value with autocompletion
161 AutocompleteMultiple # Enter multiple values with autocompletion
162
163 Date # Select date
164 DateTime # Select datetime
165
166 IPAddressSingle # Enter one IP address
167 IPAddressMultiple # Enter multiple IP addresses
168
169 IPAddressRangeSingle # Enter one IP address range
170 IPAddressRangeMultiple # Enter multiple IP address ranges
171
172If you don't specify "Single" or "Multiple" in the type, you must specify
173C<MaxValues>.
174
175=item C<LookupType>
176
177Labeled in the CF admin page as "Applies to". This determines whether your CF
178is for Tickets, Transactions, Users, Groups, or Queues. Possible values:
179
180 RT::Queue-RT::Ticket # Tickets
181 RT::Queue-RT::Ticket-RT::Transaction # Transactions
182 RT::User # Users
183 RT::Group # Groups
184 RT::Queue # Queues
af59614d 185 RT::Class-RT::Article # Articles
45030404
MKG
186
187Ticket CFs are the most common, meaning C<RT::Queue-RT::Ticket> is the most
188common C<LookupType>.
189
190=item C<RenderType>
191
192Only valid when C<Type> is "Select". Controls how the CF is displayed when
193editing it. Valid values are: C<Select box>, C<List>, and C<Dropdown>.
194
195C<List> is either a list of radio buttons or a list of checkboxes depending on
196C<MaxValues>.
197
198=item C<MaxValues>
199
200Determines whether this CF is a Single or Multiple type. 0 means multiple. 1
201means single.
202
203Make sure to set the C<MaxValues> field appropriately, otherwise you can end up
204with unsupported CF types like a "Select multiple dates" (it doesn't Just
205Work).
206
207You can also use old-style C<Type>s which end with "Single" or "Multiple", for
208example: SelectSingle, SelectMultiple, FreeformSingle, etc.
209
210=item C<Values>
211
212C<Values> should be an array ref (never a single value!) of hashrefs
213representing new L<RT::CustomFieldValue> objects to create for the new custom
214field. This only makes sense for "Select" CFs. An example:
215
216 my $i = 1;
217 push @CustomFields, {
45030404
MKG
218 LookupType => 'RT::Queue-RT::Ticket', # for Tickets
219 Name => 'Type of food',
220 Type => 'SelectSingle', # SelectSingle is the same as: Type => 'Select', MaxValues => 1
221 RenderType => 'Dropdown',
222 Values => [
223 { Name => 'Fruit', Description => 'Berries, peaches, tomatos, etc', SortOrder => $i++ },
224 { Name => 'Vegetable', Description => 'Asparagus, peas, lettuce, etc', SortOrder => $i++ },
225 # more values as such...
226 ],
227 };
228
229In order to ensure the same sorting of C<Values>, set C<SortOrder> inside each
230value. A clever way to do this easily is with a simple variable you increment
231each time (as above with C<$i>). You can use the same variable throughout the
232whole file, and don't need one per CF.
233
234=item C<BasedOn>
235
236Name or ID of another Select Custom Field. This makes the named CF the source
237of categories for your values.
238
239=item C<Pattern>
240
241The regular expression text (not C<qr//>!) used to validate values.
242
243=back
244
245Refer to the documentation and implementation of L<RT::CustomField/Create> and
246L<RT::CustomFieldValue/Create> for the full list of available fields and
247allowed values.
248
249=head2 C<@ACL>
250
251C<@ACL> is very useful for granting rights on your newly created records or
252setting up a standard system configuration. It is one of the most complex
253initialdata structures.
254
255=head3 Pick a Right
256
257All ACL definitions expect a key named C<Right> with the internal right name
258you want to grant. The internal right names are visible in RT's admin
259interface in grey next to the longer descriptions.
260
261=head3 Pick a level: on a queue, on a CF, or globally
262
263After picking a C<Right>, you need to specify on what object the right is
264granted. This is B<different> than the user/group/role receiving the right.
265
266=over 4
267
268=item Granted on a custom field by name (or ID), potentially a global or queue
269
270 CF => 'Name',
af59614d 271 LookupType => 'RT::User', # optional, in case you need to disambiguate
45030404
MKG
272
273=item Granted on a queue
274
275 Queue => 'Name',
276
277=item Granted on a custom field applied to a specific queue
278
279 CF => 'Name',
280 Queue => 'Name',
281
c33a4027
MKG
282=item Granted on a custom field applied to some other object
283
284 # This finds the CF named "Name" applied to Articles in the
285 # "Responses" class
286 CF => 'Name',
287 LookupType => RT::Article->CustomFieldLookupType,
288 ObjectId => 'Responses',
289
af59614d
MKG
290=item Granted on some other object (article Classes, etc)
291
292 ObjectType => 'RT::Class',
293 ObjectId => 'Name',
294
45030404
MKG
295=item Granted globally
296
297Specifying none of the above will get you a global right.
298
299=back
300
301There is currently no way to grant rights on a group or article class level.
302Note that you can grant rights B<to> a group; see below. If you need to grants
303rights on a group or article class level, you'll need to write an C<@Final>
304subref to handle it using the RT Perl API.
305
306=head3 Pick a Principal: User or Group or Role
307
308Finally you need to specify to what system group, system/queue role,
309user defined group, or user you want to grant the right B<to>.
310
311=over 4
312
313=item An internal user group
314
315 GroupDomain => 'SystemInternal',
316 GroupType => 'Everyone, Privileged, or Unprivileged'
317
318=item A system-level role
319
320 GroupDomain => 'RT::System-Role',
321 GroupType => 'Requestor, Owner, AdminCc, or Cc'
322
323=item A queue-level role
324
325 GroupDomain => 'RT::Queue-Role',
326 Queue => 'Name',
327 GroupType => 'Requestor, Owner, AdminCc, or Cc',
328
329=item A group you created
330
331 GroupDomain => 'UserDefined',
332 GroupId => 'Name'
333
334=item Individual user
335
336 UserId => 'Name or email or ID'
337
338=back
339
340=head3 Common cases
341
342You're probably looking for definitions like these most of the time.
343
344=over 4
345
346=item Grant a global right to a group you created
347
348 { Right => '...',
349 GroupDomain => 'UserDefined',
350 GroupId => 'Name' }
351
352=item Grant a queue-level right to a group you created
353
354 { Queue => 'Name',
355 Right => '...',
356 GroupDomain => 'UserDefined',
357 GroupId => 'Name' }
358
359=item Grant a CF-level right to a group you created
360
361 { CF => 'Name',
362 Right => '...',
363 GroupDomain => 'UserDefined',
364 GroupId => 'Name' }
365
366=back
367
368Since you often want to grant a list of rights on the same object/level to the
369same role/group/user, we generally use Perl loops and operators to aid in the
370generation of C<@ACL> without repeating ourselves.
371
372 # Give Requestors globally the right to see tickets, reply, and see the
373 # queue their ticket is in
374 push @ACL, map {
375 {
376 Right => $_,
377 GroupDomain => 'RT::System-Role',
378 GroupType => 'Requestor',
379 }
380 } qw(ShowTicket ReplyToTicket SeeQueue);
381
382=head3 Troubleshooting
383
384The best troubleshooting is often to see how the rights you define in C<@ACL>
385show up in the RT admin interface.
386
387=head2 C<@Scrips>
388
389Creates a new L<RT::Scrip> for each hashref. Refer to the documentation of
390L<RT::Scrip/Create> for the fields you can use.
391
392Additionally, the C<Queue> field is specially handled to make it easier to
393setup the same Scrip on multiple queues:
394
395=over 4
396
397=item Globally
398
399 Queue => 0,
400
401=item Single queue
402
403 Queue => 'General', # Name or ID
404
405=item Multiple queues
406
407 Queue => ['General', 'Helpdesk', 13], # Array ref of Name or ID
408
409=back
410
411=head2 C<@ScripActions>
412
413Creates a new L<RT::ScripAction> for each hashref. Refer to the documentation
414of L<RT::ScripAction/Create> for the fields you can use.
415
416=head2 C<@ScripConditions>
417
418Creates a new L<RT::ScripCondition> for each hashref. Refer to the
419documentation of L<RT::ScripCondition/Create> for the fields you can use.
420
421=head2 C<@Templates>
422
423Creates a new L<RT::Template> for each hashref. Refer to the documentation of
424L<RT::Template/Create> for the fields you can use.
425
426=head2 C<@Attributes>
427
428An array of L<RT::Attribute>s to create. You likely don't need to mess with
429this. If you do, know that the key C<Object> is expected to be an
c33a4027
MKG
430L<RT::Record> object or a subroutine reference that returns an object on which
431to call C<AddAttribute>. If you don't provide C<Object> or it's undefined,
432C<< RT->System >> will be used.
433
434Here is an example of using a subroutine reference as a value for Object:
435
436 @Attributes = ({
437 Name => 'SavedSearch',
438 Description => 'New Tickets in SomeQueue',
439 Object => sub {
440 my $GroupName = 'SomeQueue Group';
441 my $group = RT::Group->new( RT->SystemUser );
442
443 my( $ret, $msg ) = $group->LoadUserDefinedGroup( $GroupName );
444 die $msg unless $ret;
445
446 return $group;
447 },
448 Content => {
449 Format => <<' END_OF_FORMAT',
450 ....
451 END_OF_FORMAT
452 Query => "Status = 'new' AND Queue = 'SomeQueue'",
453 OrderBy => 'id',
454 Order => 'DESC'
455 },
456 });
45030404
MKG
457
458=head2 C<@Initial>
459
460=head2 C<@Final>
461
462C<@Initial> and C<@Final> are special and let you write your own processing
463code that runs before anything else or after everything else. They are
464expected to be arrays of subrefs (usually anonymous) like so:
465
466 our @Final = (sub {
467 RT->Logger->info("Finishing up!");
468 });
469
470You have the full power of RT's Perl libraries at your disposal. Be sure to do
471error checking and log any errors with C<< RT->Logger->error("...") >>!
472
473=head1 What's missing?
474
475There is currently no way, short of writing code in C<@Final> or C<@Initial>,
476to easily create B<Classes>, B<Topics>, or B<Articles> from initialdata files.
477
478=head1 Running an initialdata file
479
480 sbin/rt-setup-database --action insert --datafile /path/to/your/initialdata
481
482This may prompt you for a database password.
483
484=head1 Implementation details
485
486All the handling of initialdata files is done in C<< RT::Handle->InsertData >>.
487If you want to know B<exactly> what's happening with each array, your best bet
488is to start reading the code there.
489
490RT takes care of the ordering so that your new queues are created before it
491processes the new ACLs for those queues. This lets you refer to new queues you
492just created by Name.