first pass RT4 merge, RT#13852
[freeside.git] / rt / t / customfields / iprangev6.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use RT::Test tests => 158;
7
8 my ($baseurl, $agent) =RT::Test->started_ok;
9 ok( $agent->login, 'log in' );
10
11 my $q = RT::Queue->new($RT::SystemUser);
12 $q->Load('General');
13 my $ip_cf = RT::CustomField->new($RT::SystemUser);
14
15 my ($val,$msg) = $ip_cf->Create(Name => 'IP', Type =>'IPAddressRange', LookupType => 'RT::Queue-RT::Ticket');
16 ok($val,$msg);
17 my $cf_id = $val;
18 $ip_cf->AddToObject($q);
19 use_ok('RT');
20
21 my $cf;
22 diag "load and check basic properties of the IP CF" if $ENV{'TEST_VERBOSE'};
23 {
24     my $cfs = RT::CustomFields->new( $RT::SystemUser );
25     $cfs->Limit( FIELD => 'Name', VALUE => 'IP' );
26     is( $cfs->Count, 1, "found one CF with name 'IP'" );
27
28     $cf = $cfs->First;
29     is( $cf->Type, 'IPAddressRange', 'type check' );
30     is( $cf->LookupType, 'RT::Queue-RT::Ticket', 'lookup type check' );
31     ok( !$cf->MaxValues, "unlimited number of values" );
32     ok( !$cf->Disabled, "not disabled" );
33 }
34
35 diag "check that CF applies to queue General" if $ENV{'TEST_VERBOSE'};
36 {
37     my $cfs = $q->TicketCustomFields;
38     $cfs->Limit( FIELD => 'id', VALUE => $cf->id, ENTRYAGGREGATOR => 'AND' );
39     is( $cfs->Count, 1, 'field applies to queue' );
40 }
41
42 my %valid = (
43     'abcd:' x 7 . 'abcd' => 'abcd:' x 7 . 'abcd',
44     '034:' x 7 . '034'   => '0034:' x 7 . '0034',
45     'abcd::'             => 'abcd:' . '0000:' x 6 . '0000',
46     '::abcd'             => '0000:' x 7 . 'abcd',
47     'abcd::034'          => 'abcd:' . '0000:' x 6 . '0034',
48     'abcd::192.168.1.1'  => 'abcd:' . '0000:' x 5 . 'c0a8:0101',
49     '::192.168.1.1'      => '0000:' x 6 . 'c0a8:0101',
50     '::'                 => '0000:' x 7 . '0000',
51 );
52
53 diag "create a ticket via web and set IP" if $ENV{'TEST_VERBOSE'};
54 {
55     for my $ip ( keys %valid ) {
56         ok $agent->goto_create_ticket($q), "go to create ticket";
57         my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
58         $agent->submit_form(
59             form_name => 'TicketCreate',
60             fields    => {
61                 Subject   => 'test ip',
62                 $cf_field => $ip,
63             }
64         );
65
66         $agent->content_like( qr/$valid{$ip}/, "IP on the page" );
67         my ($id) = $agent->content =~ /Ticket (\d+) created/;
68         ok( $id, "created ticket $id" );
69
70         my $ticket = RT::Ticket->new($RT::SystemUser);
71         $ticket->Load($id);
72         ok( $ticket->id, 'loaded ticket' );
73         is( $ticket->FirstCustomFieldValue('IP'), $valid{$ip},
74             'correct value' );
75     }
76 }
77
78 diag "create a ticket via web with CIDR" if $ENV{'TEST_VERBOSE'};
79 {
80     my $val = 'abcd:034::/31';
81     ok $agent->goto_create_ticket($q), "go to create ticket";
82     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
83     $agent->submit_form(
84         form_name => 'TicketCreate',
85         fields    => {
86             Subject                                       => 'test ip',
87             $cf_field => $val,
88         }
89     );
90
91     my ($id) = $agent->content =~ /Ticket (\d+) created/;
92     ok( $id, "created ticket $id" );
93
94     my $ticket = RT::Ticket->new($RT::SystemUser);
95     $ticket->Load($id);
96     ok( $ticket->id, 'loaded ticket' );
97     is(
98         $ticket->FirstCustomFieldValue('IP'),
99 'abcd:0034:0000:0000:0000:0000:0000:0000-abcd:0035:ffff:ffff:ffff:ffff:ffff:ffff',
100         'correct value'
101     );
102 }
103
104 diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'};
105 {
106     my $val = 'abcd' . ':abcd' x 7;
107     ok $agent->goto_create_ticket($q), "go to create ticket";
108     $agent->submit_form(
109         form_name => 'TicketCreate',
110         fields    => { Subject => 'test ip', }
111     );
112
113     my ($id) = $agent->content =~ /Ticket (\d+) created/;
114     ok( $id, "created ticket $id" );
115     my $cf_field = "Object-RT::Ticket-$id-CustomField-$cf_id-Values";
116
117     $agent->follow_link_ok( { text => 'Basics', n => "1" },
118         "Followed 'Basics' link" );
119     $agent->form_name('TicketModify');
120
121     is( $agent->value($cf_field), '', 'IP is empty' );
122     $agent->field( $cf_field => $val );
123     $agent->click('SubmitTicket');
124
125     $agent->content_contains( $val, "IP on the page" );
126
127     my $ticket = RT::Ticket->new($RT::SystemUser);
128     $ticket->Load($id);
129     ok( $ticket->id, 'loaded ticket' );
130     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
131
132     diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
133     $agent->follow_link_ok( { text => 'Basics', n => "1" },
134         "Followed 'Basics' link" );
135     $agent->form_name('TicketModify');
136     is( $agent->value($cf_field), $val, 'IP is in input box' );
137     $val = 'bbcd' . ':abcd' x 7;
138     $agent->field( $cf_field => "   $val   " );
139     $agent->click('SubmitTicket');
140
141     $agent->content_contains( $val, "IP on the page" );
142
143     $ticket = RT::Ticket->new($RT::SystemUser);
144     $ticket->Load($id);
145     ok( $ticket->id, 'loaded ticket' );
146     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
147
148     diag "replace IP with a range" if $ENV{'TEST_VERBOSE'};
149     $agent->follow_link_ok( { text => 'Basics', n => "1" },
150         "Followed 'Basics' link" );
151     $agent->form_name('TicketModify');
152     is( $agent->value($cf_field), $val, 'IP is in input box' );
153     $val = 'abcd' . ':0000' x 7 . '-' . 'abcd' . ':ffff' x 7;
154     $agent->field( $cf_field => 'abcd::/16' );
155     $agent->click('SubmitTicket');
156
157     $agent->content_contains( $val, "IP on the page" );
158
159     $ticket = RT::Ticket->new($RT::SystemUser);
160     $ticket->Load($id);
161     ok( $ticket->id, 'loaded ticket' );
162     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
163
164     diag "delete range, add another range using CIDR" if $ENV{'TEST_VERBOSE'};
165     $agent->follow_link_ok( { text => 'Basics', n => "1" },
166         "Followed 'Basics' link" );
167     $agent->form_name('TicketModify');
168     is( $agent->value($cf_field), $val, 'IP is in input box' );
169     $val = 'bb00' . ':0000' x 7 . '-' . 'bbff' . ':ffff' x 7;
170     $agent->field( $cf_field => $val );
171     $agent->click('SubmitTicket');
172
173     $agent->content_contains( $val, "IP on the page" );
174
175     $ticket = RT::Ticket->new($RT::SystemUser);
176     $ticket->Load($id);
177     ok( $ticket->id, 'loaded ticket' );
178     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
179 }
180
181 diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
182 {
183
184     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
185     my @invalid =
186       ( 'abcd:', 'efgh', 'abcd:' x 8 . 'abcd', 'abcd::abcd::abcd' );
187     for my $invalid (@invalid) {
188         ok $agent->goto_create_ticket($q), "go to create ticket";
189         $agent->submit_form(
190             form_name => 'TicketCreate',
191             fields    => {
192                 Subject   => 'test ip',
193                 $cf_field => $invalid,
194             }
195         );
196
197         $agent->content_like( qr/can not be parsed as an IP address range/,
198             'ticket fails to create' );
199     }
200
201 }
202
203 diag "search tickets by IP" if $ENV{'TEST_VERBOSE'};
204 {
205     my $val = 'abcd::/16';
206     ok $agent->goto_create_ticket($q), "go to create ticket";
207     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
208     $agent->submit_form(
209         form_name => 'TicketCreate',
210         fields    => {
211             Subject   => 'test ip',
212             $cf_field => $val,
213         }
214     );
215
216     my ($id) = $agent->content =~ /Ticket (\d+) created/;
217     ok( $id, "created ticket $id" );
218
219     my $ticket = RT::Ticket->new($RT::SystemUser);
220     $ticket->Load($id);
221     ok( $ticket->id, 'loaded ticket' );
222
223     my $tickets = RT::Tickets->new($RT::SystemUser);
224     $tickets->FromSQL("id = $id AND CF.{IP} = 'abcd::/16'");
225     ok( $tickets->Count, "found tickets" );
226     is(
227         $ticket->FirstCustomFieldValue('IP'),
228 'abcd:0000:0000:0000:0000:0000:0000:0000-abcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
229         'correct value'
230     );
231 }
232
233 diag "search tickets by IP range" if $ENV{'TEST_VERBOSE'};
234 {
235     my $val = 'abcd:ef00::/24';
236     ok $agent->goto_create_ticket($q), "go to create ticket";
237     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
238     $agent->submit_form(
239         form_name => 'TicketCreate',
240         fields    => {
241             Subject   => 'test ip',
242             $cf_field => $val,
243         }
244     );
245
246     my ($id) = $agent->content =~ /Ticket (\d+) created/;
247     ok( $id, "created ticket $id" );
248
249     my $ticket = RT::Ticket->new($RT::SystemUser);
250     $ticket->Load($id);
251     ok( $ticket->id, 'loaded ticket' );
252
253     my $tickets = RT::Tickets->new( $RT::SystemUser );
254     $tickets->FromSQL("id = $id AND CF.{IP} =
255             'abcd:ef::-abcd:efff:ffff:ffff:ffff:ffff:ffff:ffff'");
256     ok( $tickets->Count, "found tickets" );
257
258     is(
259         $ticket->FirstCustomFieldValue('IP'),
260 'abcd:ef00:0000:0000:0000:0000:0000:0000-abcd:efff:ffff:ffff:ffff:ffff:ffff:ffff',
261         'correct value'
262     );
263 }
264
265 diag "create two tickets with different IPs and check several searches" if $ENV{'TEST_VERBOSE'};
266 {
267     ok $agent->goto_create_ticket($q), "go to create ticket";
268     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
269     my $first_ip = 'cbcd' . ':0000' x 7;
270     my $second_ip = 'cbdd' . ':0000' x 7;
271     $agent->submit_form(
272         form_name => 'TicketCreate',
273         fields    => {
274             Subject   => 'test ip',
275             $cf_field => $first_ip,
276         }
277     );
278
279     my ($id1) = $agent->content =~ /Ticket (\d+) created/;
280     ok( $id1, "created first ticket $id1" );
281
282     ok $agent->goto_create_ticket($q), "go to create ticket";
283     $agent->submit_form(
284         form_name => 'TicketCreate',
285         fields    => {
286             Subject   => 'test ip',
287             $cf_field => $second_ip,
288         }
289     );
290
291     my ($id2) = $agent->content =~ /Ticket (\d+) created/;
292     ok( $id2, "created second ticket $id2" );
293
294     my $tickets = RT::Tickets->new( $RT::SystemUser );
295     $tickets->FromSQL("id = $id1 OR id = $id2");
296     is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
297
298     # IP
299     $tickets = RT::Tickets->new( $RT::SystemUser );
300     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '$first_ip'");
301     is( $tickets->Count, 1, "found one ticket" );
302     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
303     $tickets = RT::Tickets->new( $RT::SystemUser );
304     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '$second_ip'");
305     is( $tickets->Count, 1, "found one ticket" );
306     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
307
308     # IP/32 - one address
309     $tickets = RT::Tickets->new( $RT::SystemUser );
310     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbcd::/16'");
311     is( $tickets->Count, 1, "found one ticket" );
312     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
313     $tickets = RT::Tickets->new( $RT::SystemUser );
314     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdd::/16'");
315     is( $tickets->Count, 1, "found one ticket" );
316     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
317
318     # IP range
319     $tickets = RT::Tickets->new( $RT::SystemUser );
320     $tickets->FromSQL(
321         "(id = $id1 OR id = $id2) AND CF.{IP} = '$first_ip-cbcf::'"
322     );
323     is( $tickets->Count, 1, "found one ticket" );
324     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
325     $tickets = RT::Tickets->new( $RT::SystemUser );
326     $tickets->FromSQL(
327         "(id = $id1 OR id = $id2) AND CF.{IP} = '$second_ip-cbdf::'");
328     is( $tickets->Count, 1, "found one ticket" );
329     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
330
331     # IP range, with start IP greater than end
332     $tickets = RT::Tickets->new( $RT::SystemUser );
333     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} =
334             'cbcf::-$first_ip'");
335     is( $tickets->Count, 1, "found one ticket" );
336     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip,, "correct value" );
337     $tickets = RT::Tickets->new( $RT::SystemUser );
338     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdf::-$second_ip'");
339     is( $tickets->Count, 1, "found one ticket" );
340     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
341
342     # CIDR/12
343     $tickets = RT::Tickets->new( $RT::SystemUser );
344     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbcd::/12'");
345     is( $tickets->Count, 1, "found one ticket" );
346     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
347     $tickets = RT::Tickets->new( $RT::SystemUser );
348     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdd::/12'");
349     is( $tickets->Count, 1, "found one ticket" );
350     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
351
352     # IP is not in CIDR/24
353     $tickets = RT::Tickets->new( $RT::SystemUser );
354     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != 'cbcd::/12'");
355     is( $tickets->Count, 1, "found one ticket" );
356     is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip,, "correct value" );
357     $tickets = RT::Tickets->new( $RT::SystemUser );
358     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != 'cbdd::/12'");
359     is( $tickets->Count, 1, "found one ticket" );
360     is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
361
362     # CIDR or CIDR
363     $tickets = RT::Tickets->new( $RT::SystemUser );
364     $tickets->FromSQL("(id = $id1 OR id = $id2) AND "
365         ."(CF.{IP} = 'cbcd::/12' OR CF.{IP} = 'cbdd::/12')");
366     is( $tickets->Count, 2, "found both tickets" );
367 }
368
369 diag "create two tickets with different IP ranges and check several searches" if $ENV{'TEST_VERBOSE'};
370 {
371     ok $agent->goto_create_ticket($q), "go to create ticket";
372     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
373     $agent->submit_form(
374         form_name => 'TicketCreate',
375         fields    => {
376             Subject   => 'test ip',
377             $cf_field => 'ddcd::/16',
378         }
379     );
380
381     my ($id1) = $agent->content =~ /Ticket (\d+) created/;
382     ok( $id1, "created first ticket $id1" );
383
384     ok $agent->goto_create_ticket($q), "go to create ticket";
385     $agent->submit_form(
386         form_name => 'TicketCreate',
387         fields    => {
388             Subject   => 'test ip',
389             $cf_field => 'edcd::/16',
390         }
391     );
392
393     my ($id2) = $agent->content =~ /Ticket (\d+) created/;
394     ok( $id2, "created ticket $id2" );
395
396     my $tickets = RT::Tickets->new( $RT::SystemUser );
397     $tickets->FromSQL("id = $id1 OR id = $id2");
398     is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
399
400     # IP
401     $tickets = RT::Tickets->new( $RT::SystemUser );
402     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::'");
403     is( $tickets->Count, 1, "found one ticket" );
404     is( $tickets->First->id, $id1, "correct value" );
405     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:abcd::'");
406     is( $tickets->Count, 1, "found one ticket" );
407     is( $tickets->First->id, $id1, "correct value" );
408     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:ffff::'");
409     is( $tickets->Count, 1, "found one ticket" );
410     is( $tickets->First->id, $id1, "correct value" );
411     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::abcd'");
412     is( $tickets->Count, 1, "found one ticket" );
413     is( $tickets->First->id, $id2, "correct value" );
414     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::ffff'");
415     is( $tickets->Count, 1, "found one ticket" );
416     is( $tickets->First->id, $id2, "correct value" );
417     $tickets->FromSQL(
418 "(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff'"
419     );
420     is( $tickets->Count, 1, "found one ticket" );
421     is( $tickets->First->id, $id2, "correct value" );
422
423     # IP/32 - one address
424     $tickets = RT::Tickets->new( $RT::SystemUser );
425     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::/32'");
426     is( $tickets->Count, 1, "found one ticket" );
427     is( $tickets->First->id, $id1, "correct value" );
428     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::/32'");
429     is( $tickets->Count, 1, "found one ticket" );
430     is( $tickets->First->id, $id2, "correct value" );
431
432     # IP range, lower than both
433     $tickets = RT::Tickets->new( $RT::SystemUser );
434     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'abcd::/32'");
435     is( $tickets->Count, 0, "didn't finnd ticket" ) or diag "but found ". $tickets->First->id;
436
437     # IP range, intersect with the first range
438     $tickets->FromSQL(
439         "(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcc::-ddcd:ab::'"
440     );
441     is( $tickets->Count, 1, "found one ticket" );
442     is( $tickets->First->id, $id1, "correct value" );
443
444     # IP range, equal to the first range
445     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::/16'");
446     is( $tickets->Count, 1, "found one ticket" );
447     is( $tickets->First->id, $id1, "correct value" );
448
449     # IP range, lay inside the first range
450     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:ab::'");
451     is( $tickets->Count, 1, "found one ticket" );
452     is( $tickets->First->id, $id1, "correct value" );
453
454     # IP range, intersect with the ranges
455     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcc::-edcd:ab::'");
456     is( $tickets->Count, 2, "found both tickets" );
457
458     # IP range, equal to range from the starting IP of the first ticket to the ending IP of the second
459     $tickets->FromSQL(
460         "(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::-edcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff'"
461     );
462     is( $tickets->Count, 2, "found both tickets" );
463
464     # IP range, has the both ranges inside it
465     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'd000::/2'");
466     is( $tickets->Count, 2, "found both tickets" );
467
468     # IP range, greater than both
469     $tickets = RT::Tickets->new( $RT::SystemUser );
470     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ffff::/16'");
471     is( $tickets->Count, 0, "didn't find ticket" ) or diag "but found ". $tickets->First->id;
472 }
473
474